diff --git a/mt7620/build/Kconfig b/mt7620/build/Kconfig new file mode 100644 index 0000000..770bd8e --- /dev/null +++ b/mt7620/build/Kconfig @@ -0,0 +1,202 @@ +config RT2860V2_AP + tristate "Ralink RT2860 802.11n AP support" +# depends on NET_RADIO + select WIRELESS_EXT + select WEXT_SPY + select WEXT_PRIV + +config RT2860V2_AP_V24_DATA_STRUCTURE + bool + depends on RT2860V2_AP + default y + +config RT2860V2_AP_LED + bool "LED Support" + depends on RT2860V2_AP + +config RT2860V2_AP_WSC + bool "WSC (WiFi Simple Config)" + depends on RT2860V2_AP + +config RT2860V2_AP_WSC_V2 + bool "WSC 2.0(WiFi Simple Config 2.0)" + depends on RT2860V2_AP_WSC + default y + +config RT2860V2_AP_LLTD + bool "LLTD (Link Layer Topology Discovery Protocol)" + depends on RT2860V2_AP + +config RT2860V2_AP_WDS + bool "WDS" + depends on RT2860V2_AP + +#config RT2860V2_AP_WMM_ACM +# bool "WMM ACM" +# depends on RT2860V2_AP + +config RT2860V2_AP_MBSS + bool "MBSSID" + depends on RT2860V2_AP + +config NEW_MBSSID_MODE + bool "New MBSSID MODE" + depends on RT2860V2_AP + depends on RT2860V2_AP_MBSS + depends on RALINK_RT3883 || RALINK_RT3352 || RALINK_RT5350 || RALINK_RT6352 || RALINK_MT7620 + default n + +config RT2860V2_AP_APCLI + bool "AP-CLient Support" + depends on RT2860V2_AP + +config RT2860V2_AP_MAC_REPEATER + bool "MAC Repeater Support" + depends on RT2860V2_AP + depends on RT2860V2_AP_APCLI + depends on RALINK_RT6352 || RALINK_MT7620 + default n + +config RT2860V2_AP_IGMP_SNOOP + bool "IGMP snooping" + depends on RT2860V2_AP + +config RT2860V2_AP_NETIF_BLOCK + bool "NETIF Block" + depends on RT2860V2_AP + help + Support Net interface block while Tx-Sw queue full + +config RT2860V2_AP_DFS + bool "DFS" + depends on RT2860V2_AP + select RALINK_TIMER_DFS + +config RT2860V2_AP_CARRIER + bool "Carrier Detect" + depends on RT2860V2_AP + +config RT2860V2_AP_DLS + bool "DLS ((Direct-Link Setup) Support" + depends on RT2860V2_AP + +config RT2860V2_AP_IDS + bool "IDS (Intrusion Detection System) Support" + depends on RT2860V2_AP + +config RT2860V2_HW_ANTENNA_DIVERSITY + bool "Antenna Diversity Support" + depends on RT2860V2_AP + depends on RALINK_RT5350 + +#config RT2860V2_AP_WAPI +# bool "WAPI Support" +# depends on RT2860V2_AP + +config RT2860V2_AP_COC + bool "CoC Support" + depends on RT2860V2_AP + default y + +config RT2860V2_AP_MEMORY_OPTIMIZATION + bool "Memory Optimization" + depends on RT2860V2_AP + +config RT2860V2_AP_VIDEO_TURBINE + bool "Video Turbine support" + depends on RT2860V2_AP + +config RA_CLASSIFIER + tristate "Ralink Flow Classifier" + depends on RT2860V2_AP_VIDEO_TURBINE + default n + +config RT2860V2_AP_INTELLIGENT_RATE_ADAPTION + bool "Intelligent Rate Adaption" + depends on RT2860V2_AP + depends on RALINK_RT2883 || RALINK_RT3883 + +config RT2860V2_AP_TXBF + bool "Tx Bean Forming Support (Only 3883)" + depends on RT2860V2_AP + depends on RALINK_RT2883 || RALINK_RT3883 + default y + +#config RT2860V2_EXT_CHANNEL_LIST +# bool "Extension Channel List" +# depends on RT2860V2_AP + +#config RT2860V2_KTHREAD +# bool "Kernel Thread" +# depends on RT2860V2_AP + +#config RT2860V2_AUTO_CH_SELECT_ENHANCE +# bool "Auto Channel Selection Enhancement" +# depends on RT2860V2_AP + +config RT2860V2_AP_80211N_DRAFT3 + bool "802.11n Draft3" + depends on RT2860V2_AP + +config BAND_STEERING + bool "Band Steering" + depends on RT2860V2_AP + default n + +#config RT2860V2_AP_RTMP_INTERNAL_TX_ALC +# bool "TSSI Compensation" +# depends on RT2860V2_AP +# depends on RALINK_RT3350 || RALINK_RT3352 || RALINK_RT5350 || RALINK_MT7620 || RALINK_RT6352 +# default n + +config RT2860V2_ADJ_PWR_CONSUMPTION_SUPPORT + bool "Adjust Power Consumption Support" + depends on RT2860V2_AP + depends on RALINK_MT7620 || RALINK_RT6352 + default n + +config RT2860V2_SINGLE_SKU + bool "Single SKU" + depends on RT2860V2_AP + default n + +choice + prompt "Choose Power Design" + depends on RALINK_MT7620 || RALINK_RT6352 + default INTERNAL_PA_INTERNAL_LNA + config INTERNAL_PA_INTERNAL_LNA + bool "Internal PA and Internal LNA" + config INTERNAL_PA_EXTERNAL_LNA + bool "Internal PA and External LNA" + config EXTERNAL_PA_EXTERNAL_LNA + bool "External PA and External LNA" +endchoice + +config RT2860V2_AP_RTMP_INTERNAL_TX_ALC + bool "TSSI Compensation" + depends on RT2860V2_AP + depends on RALINK_RT3350 || RALINK_RT3352 || RALINK_RT5350 || RALINK_MT7620 || RALINK_RT6352 + depends on INTERNAL_PA_INTERNAL_LNA || INTERNAL_PA_EXTERNAL_LNA + default n + +config RT2860V2_AP_RTMP_TEMPERATURE_COMPENSATION + bool "Temperature Compensation" + depends on RT2860V2_AP + depends on RALINK_MT7620 || RALINK_RT6352 + default n + +#config RT2860V2_80211R_FT +# bool "802.11r Fast BSS Transition" +# depends on RT2860V2_AP + +#config RT2860V2_80211R_RR +# bool "802.11k Radio Resource Management" +# depends on RT2860V2_AP + +#config RT2860V2_MCAST_RATE_SPECIFIC +# bool "User specific tx rate of mcast pkt" +# depends on RT2860V2_AP + +#config RT2860V2_SNMP +# bool "Net-SNMP Support" +# depends on RT2860V2_AP diff --git a/mt7620/build/Makefile b/mt7620/build/Makefile new file mode 100644 index 0000000..5a12bfa --- /dev/null +++ b/mt7620/build/Makefile @@ -0,0 +1,505 @@ +ifeq ($(CONFIG_SUPPORT_OPENWRT),y) +EXTRA_CFLAGS = -I$(src)/../src/include -I$(src)/../src/ate/include +DRV_NAME = mt7620 +SRC_DIR = ../src +obj-m += $(DRV_NAME).o +else +EXTRA_CFLAGS = -Idrivers/net/wireless/rt2860v2/include -Idrivers/net/wireless/rt2860v2/ate/include +DRV_NAME = rt2860v2_ap +SRC_DIR = ../rt2860v2 +obj-$(CONFIG_RT2860V2_AP) += $(DRV_NAME).o +endif + + +$(DRV_NAME)-objs += $(SRC_DIR)/common/crypt_md5.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/crypt_sha2.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/crypt_hmac.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/crypt_aes.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/crypt_arc4.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/mlme.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_wep.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/action.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/ba_action.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_data.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/rtmp_init.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/rtmp_init_inf.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_tkip.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_aes.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_sync.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_sanity.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_info.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_cfg.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_radar.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_wpa.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/spectrum.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/ps.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/uapsd.o + +$(DRV_NAME)-objs += $(SRC_DIR)/common/rtmp_timer.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/rt_channel.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_profile.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_asic.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_cmd.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/rtmp_swmcu.o + +$(DRV_NAME)-objs += $(SRC_DIR)/common/eeprom.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/ee_flash.o + +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_mac_pci.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_data_pci.o + +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_rf_cal.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_loft_cal.o + +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_assoc.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_auth.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_connect.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_mlme.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_sanity.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_sync.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_wpa.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_data.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_autoChSel.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_qload.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_cfg.o + +$(DRV_NAME)-objs += $(SRC_DIR)/rate_ctrl/ra_ctrl.o +$(DRV_NAME)-objs += $(SRC_DIR)/rate_ctrl/alg_legacy.o +$(DRV_NAME)-objs += $(SRC_DIR)/rate_ctrl/alg_ags.o + +$(DRV_NAME)-objs += $(SRC_DIR)/os/linux/rt_proc.o +$(DRV_NAME)-objs += $(SRC_DIR)/os/linux/rt_linux.o +$(DRV_NAME)-objs += $(SRC_DIR)/os/linux/rt_profile.o +$(DRV_NAME)-objs += $(SRC_DIR)/os/linux/rt_main_dev.o +$(DRV_NAME)-objs += $(SRC_DIR)/os/linux/ap_ioctl.o +$(DRV_NAME)-objs += $(SRC_DIR)/os/linux/rt_pci_rbus.o +$(DRV_NAME)-objs += $(SRC_DIR)/os/linux/rt_rbus_pci_drv.o +$(DRV_NAME)-objs += $(SRC_DIR)/os/linux/rt_rbus_pci_util.o +$(DRV_NAME)-objs += $(SRC_DIR)/os/linux/rbus_main_dev.o + +$(DRV_NAME)-objs += $(SRC_DIR)/ate/common/rt_ate.o +$(DRV_NAME)-objs += $(SRC_DIR)/ate/common/rt_qa.o +$(DRV_NAME)-objs += $(SRC_DIR)/ate/common/ate_pci.o + +$(DRV_NAME)-objs += $(SRC_DIR)/common/rt_os_util.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/rtmp_swmcu.o +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rtmp_chip.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/rt_rf.o + +ifeq ($(CONFIG_RT2860V2_AP_WMM_ACM),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/acm_edca.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/acm_comm.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/acm_iocl.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_LED),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/rt_led.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_WSC),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/wsc.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/wsc_tlv.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/crypt_dh.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/crypt_biginteger.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/wsc_ufd.o +ifeq ($(CONFIG_RT2860V2_AP_WSC_V2),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/wsc_v2.o +endif +endif + +ifeq ($(CONFIG_RT2860V2_AP_WDS),y) +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_wds.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_wds_inf.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/client_wds.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_MBSS),y) +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_mbss.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_mbss_inf.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_APCLI),y) +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_apcli.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_apcli_inf.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/apcli_assoc.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/apcli_auth.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/apcli_ctrl.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/apcli_sync.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_mat.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_mat_iparp.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_mat_pppoe.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_mat_ipv6.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_MAC_REPEATER),y) +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_repeater.o +endif + +#ifeq ($(CONFIG_RT2860V2_AP_WAPI),y) +#$(DRV_NAME)-objs += $(SRC_DIR)/common/wapi.o +#$(DRV_NAME)-objs += wapi_crypt.obj +#$(DRV_NAME)-objs += wapi_sms4.obj +#endif + +ifeq ($(CONFIG_RT2860V2_AP_IGMP_SNOOP),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/igmp_snoop.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_NETIF_BLOCK),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/netif_block.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_DFS),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_dfs.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_CARRIER),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_cs.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_DLS),y) +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_dls.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_IDS),y) +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_ids.o +endif + +#ifeq ($(CONFIG_RT2860V2_80211R_FT),y) +#$(DRV_NAME)-objs += $(SRC_DIR)/common/ft.o +#$(DRV_NAME)-objs += $(SRC_DIR)/common/ft_tlv.o +#$(DRV_NAME)-objs += $(SRC_DIR)/common/ft_ioctl.o +#$(DRV_NAME)-objs += $(SRC_DIR)/common/ft_rc.o +#$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_ftkd.o +#endif + +#ifeq ($(CONFIG_RT2860V2_80211K_RR),y) +#$(DRV_NAME)-objs += $(SRC_DIR)/common/rrm_tlv.o +#$(DRV_NAME)-objs += $(SRC_DIR)/common/rrm_sanity.o +#$(DRV_NAME)-objs += $(SRC_DIR)/common/rrm.o +#endif + +ifeq ($(CONFIG_RT2860V2_AP_VIDEO_TURBINE),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_video.o +endif + +ifeq ($(CONFIG_RALINK_RT2880),y) +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rt2880.o +endif + +ifeq ($(CONFIG_RALINK_RT2883),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/rt_rf.o +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rt2883.o +ifeq ($(CONFIG_RT2860V2_AP_TXBF),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_txbf.o +endif +endif + +ifeq ($(CONFIG_RALINK_RT3883),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/rt_rf.o +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rt3883.o +ifeq ($(CONFIG_RT2860V2_AP_TXBF),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_txbf.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_txbf_cal.o +endif +$(DRV_NAME)-objs += $(SRC_DIR)/rate_ctrl/alg_grp.o +$(DRV_NAME)-objs += $(SRC_DIR)/ate/chips/rt3883_ate.o +endif + +ifeq ($(CONFIG_RALINK_RT3052),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/rt_rf.o +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rt305x.o +endif + +ifeq ($(CONFIG_RALINK_RT3352),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/rt_rf.o +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rt305x.o +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rt3352.o +endif + +ifeq ($(CONFIG_RT3x52),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/rt_rf.o +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rt305x.o +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rt3352.o +endif + +ifeq ($(CONFIG_RALINK_RT5350),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/rt_rf.o +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rt305x.o +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rt5350.o +endif + +ifeq ($(CONFIG_RALINK_RT6352),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/rt_rf.o +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rt6352.o +$(DRV_NAME)-objs += $(SRC_DIR)/ate/chips/rt6352_ate.o +endif + +ifeq ($(CONFIG_RALINK_MT7620),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/rt_rf.o +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rt6352.o +$(DRV_NAME)-objs += $(SRC_DIR)/ate/chips/rt6352_ate.o +endif + +################### +# CFLAGS +################## +EXTRA_CFLAGS += -DAGGREGATION_SUPPORT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT -DLINUX \ + -Wall -Wstrict-prototypes -Wno-trigraphs + +EXTRA_CFLAGS += -DCONFIG_AP_SUPPORT -DAP_SCAN_SUPPORT -DUAPSD_AP_SUPPORT -DUAPSD_SUPPORT -DRTMP_RBUS_SUPPORT -DRTMP_MAC_PCI +EXTRA_CFLAGS += -DDOT11_N_SUPPORT -DSTATS_COUNT_SUPPORT -DIAPP_SUPPORT -DDOT1X_SUPPORT +EXTRA_CFLAGS += -DRALINK_ATE -DRALINK_QA -DCONFIG_RT2880_ATE_CMD_NEW +EXTRA_CFLAGS += -DCONFIG_RA_NAT_NONE + +#provide busy time statistics for every TBTT */ +#EXTRA_CFLAGS += -DQLOAD_FUNC_BUSY_TIME_STATS + +# provide busy time alarm mechanism +# use the function to avoid to locate in some noise environments +#EXTRA_CFLAGS += -DQLOAD_FUNC_BUSY_TIME_ALARM + +ifeq ($(CONFIG_RALINK_RT2880),y) +EXTRA_CFLAGS += -DRT2880 +endif + +ifeq ($(CONFIG_RALINK_RT2883),y) +EXTRA_CFLAGS += -DRT2883 -DDOT11N_SS3_SUPPORT -DA_BAND_SUPPORT -DRTMP_RF_RW_SUPPORT +ifeq ($(CONFIG_RT2860V2_AP_TXBF),y) +EXTRA_CFLAGS += -DTXBF_SUPPORT +endif +endif + +ifeq ($(CONFIG_RALINK_RT3883),y) +EXTRA_CFLAGS += -DRT3883 -DDOT11N_SS3_SUPPORT -DA_BAND_SUPPORT -DRTMP_RF_RW_SUPPORT +EXTRA_CFLAGS += -DRTMP_FLASH_SUPPORT -DCONFIG_SWMCU_SUPPORT +EXTRA_CFLAGS += -DSPECIFIC_BCN_BUF_SUPPORT -DVCORECAL_SUPPORT +EXTRA_CFLAGS += -DRANGE_EXT_SUPPORT +ifeq ($(CONFIG_RT2860V2_AP_TXBF),y) +EXTRA_CFLAGS += -DTXBF_SUPPORT +endif +EXTRA_CFLAGS += -DSTREAM_MODE_SUPPORT -DFIFO_EXT_SUPPORT +endif + +ifeq ($(CONFIG_RALINK_RT3052),y) +EXTRA_CFLAGS += -DSPECIFIC_VCORECAL_SUPPORT +ifeq ($(CONFIG_RALINK_RT3350),y) +EXTRA_CFLAGS += -DRT3350 -DRT305x -DRTMP_RF_RW_SUPPORT +else +EXTRA_CFLAGS += -DRT3052 -DRT305x -DRTMP_RF_RW_SUPPORT +endif +endif + +ifeq ($(CONFIG_RALINK_RT3352),y) +EXTRA_CFLAGS += -DRT3352 -DRT305x -DRTMP_RF_RW_SUPPORT +EXTRA_CFLAGS += -DSPECIFIC_BCN_BUF_SUPPORT -DVCORECAL_SUPPORT +endif + +ifeq ($(CONFIG_RT3x52),y) +EXTRA_CFLAGS += -DRT3052 -DRT3352 -DRT305x -DRTMP_RF_RW_SUPPORT -DSPECIFIC_BCN_BUF_SUPPORT -DVCORECAL_SUPPORT +endif + +ifeq ($(CONFIG_RALINK_RT5350),y) +EXTRA_CFLAGS += -DRT5350 -DRT305x -DRTMP_RF_RW_SUPPORT +EXTRA_CFLAGS += -DSPECIFIC_BCN_BUF_SUPPORT -DVCORECAL_SUPPORT +endif + +ifeq ($(CONFIG_RALINK_RT6352),y) +EXTRA_CFLAGS += -DRT6352 -DRTMP_RF_RW_SUPPORT -DRF_BANK -DRTMP_FLASH_SUPPORT -DCONFIG_SWMCU_SUPPORT +EXTRA_CFLAGS += -DSPECIFIC_BCN_BUF_SUPPORT -DVCORECAL_SUPPORT +EXTRA_CFLAGS += -DRESOURCE_PRE_ALLOC +EXTRA_CFLAGS += -DENHANCED_STAT_DISPLAY +EXTRA_CFLAGS += -DLOFT_IQ_CAL_SUPPORT +EXTRA_CFLAGS += -DRTMP_TEMPERATURE_CALIBRATION +EXTRA_CFLAGS += -DDYNAMIC_VGA_SUPPORT +EXTRA_CFLAGS += -DMCS_LUT_SUPPORT -DPEER_DELBA_TX_ADAPT +ifeq ($(CONFIG_INTERNAL_PA_EXTERNAL_LNA),y) +EXTRA_CFLAGS += -DRT6352_EL_SUPPORT +endif +ifeq ($(CONFIG_EXTERNAL_PA_EXTERNAL_LNA),y) +EXTRA_CFLAGS += -DRT6352_EP_SUPPORT -DRT6352_EL_SUPPORT +endif +endif + +ifeq ($(CONFIG_RALINK_MT7620),y) +EXTRA_CFLAGS += -DRT6352 -DRTMP_RF_RW_SUPPORT -DRF_BANK -DRTMP_FLASH_SUPPORT -DCONFIG_SWMCU_SUPPORT +EXTRA_CFLAGS += -DSPECIFIC_BCN_BUF_SUPPORT -DVCORECAL_SUPPORT +EXTRA_CFLAGS += -DRESOURCE_PRE_ALLOC +EXTRA_CFLAGS += -DENHANCED_STAT_DISPLAY +EXTRA_CFLAGS += -DLOFT_IQ_CAL_SUPPORT +EXTRA_CFLAGS += -DRTMP_TEMPERATURE_CALIBRATION +EXTRA_CFLAGS += -DDYNAMIC_VGA_SUPPORT +EXTRA_CFLAGS += -DMCS_LUT_SUPPORT -DPEER_DELBA_TX_ADAPT +ifeq ($(CONFIG_INTERNAL_PA_EXTERNAL_LNA),y) +EXTRA_CFLAGS += -DRT6352_EL_SUPPORT +endif +ifeq ($(CONFIG_EXTERNAL_PA_EXTERNAL_LNA),y) +EXTRA_CFLAGS += -DRT6352_EP_SUPPORT -DRT6352_EL_SUPPORT +endif +endif + +ifeq ($(CONFIG_RT2860V2_AP_DLS),y) +EXTRA_CFLAGS += -DQOS_DLS_SUPPORT +EXTRA_CFLAGS += -DAP_DLS_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_IDS),y) +EXTRA_CFLAGS += -DIDS_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_DFS),y) +EXTRA_CFLAGS += -DDFS_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_CARRIER),y) +EXTRA_CFLAGS += -DCARRIER_DETECTION_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AUTO_CH_SELECT_ENCANCE),y) +EXTRA_CFLAGS += -DAUTO_CH_SELECT_ENHANCE +endif + +ifeq ($(CONFIG_RT2860V2_AP_80211N_DRAFT3),y) +EXTRA_CFLAGS += -DDOT11N_DRAFT3 +endif + +ifeq ($(CONFIG_RT2860V2_SNMP),y) +EXTRA_CFLAGS += -DSNMP_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_MCAST_RATE_SPECIFIC),y) +EXTRA_CFLAGS += -DMCAST_RATE_SPECIFIC +endif + +#ifeq ($(CONFIG_RT2860V2_AP_WMM_ACM),y) +#EXTRA_CFLAGS += -DWMM_ACM_SUPPORT +#endif + +ifeq ($(CONFIG_RT2860V2_AP_LED),y) +EXTRA_CFLAGS += -DLED_CONTROL_SUPPORT -DCONFIG_SWMCU_SUPPORT +ifeq ($(CONFIG_RT2860V2_AP_WSC),y) +EXTRA_CFLAGS += -DWSC_LED_SUPPORT +endif +endif + +ifeq ($(CONFIG_RT2860V2_AP_WSC),y) +EXTRA_CFLAGS += -DWSC_AP_SUPPORT +ifeq ($(CONFIG_RT2860V2_AP_WSC_V2),y) +EXTRA_CFLAGS += -DWSC_V2_SUPPORT +endif +endif + +ifeq ($(CONFIG_RT2860V2_AP_LLTD),y) +EXTRA_CFLAGS += -DLLTD_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_WDS),y) +EXTRA_CFLAGS += -DWDS_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_MBSS),y) +EXTRA_CFLAGS += -DMBSS_SUPPORT +endif + +ifeq ($(CONFIG_NEW_MBSSID_MODE),y) +EXTRA_CFLAGS += -DNEW_MBSSID_MODE +ifeq ($(CONFIG_RALINK_RT6352),y) +EXTRA_CFLAGS += -DENHANCE_NEW_MBSSID_MODE +endif +ifeq ($(CONFIG_RALINK_MT7620),y) +EXTRA_CFLAGS += -DENHANCE_NEW_MBSSID_MODE +endif +endif + +ifeq ($(CONFIG_RT2860V2_AP_APCLI),y) +EXTRA_CFLAGS += -DAPCLI_SUPPORT +EXTRA_CFLAGS += -DMAT_SUPPORT +EXTRA_CFLAGS += -DAPCLI_CONNECTION_TRIAL +endif + +ifeq ($(CONFIG_RT2860V2_AP_MAC_REPEATER),y) +ifeq ($(CONFIG_RALINK_MT7620),y) +EXTRA_CFLAGS += -DMAC_APCLI_SUPPORT +endif +EXTRA_CFLAGS += -DMAC_REPEATER_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_32B_DESC),y) +EXTRA_CFLAGS += -DDESC_32B_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_IGMP_SNOOP),y) +EXTRA_CFLAGS += -DIGMP_SNOOP_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_NETIF_BLOCK),y) +EXTRA_CFLAGS += -DBLOCK_NET_IF +endif + +ifeq ($(CONFIG_RT2860V2_HW_ANTENNA_DIVERSITY),y) +EXTRA_CFLAGS += -DHW_ANTENNA_DIVERSITY_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_WAPI),y) +EXTRA_CFLAGS += -DWAPI_SUPPORT +ifeq ($(CONFIG_RALINK_RT3052),y) +EXTRA_CFLAGS += -DSOFT_ENCRYPT +endif +endif + +ifeq ($(CONFIG_RT2860V2_AP_COC),y) +EXTRA_CFLAGS += -DGREENAP_SUPPORT -DCOC_SUPPORT +endif + +ifeq ($(CONFIG_BAND_STEERING),y) +EXTRA_CFLAGS += -DBAND_STEERING +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_band_steering.o +endif + +ifeq ($(CONFIG_RT2860V2_EXT_CHANNEL_LIST),y) +EXTRA_CFLAGS += -DEXT_BUILD_CHANNEL_LIST +endif + +ifeq ($(CONFIG_KTHREAD),y) +EXTRA_CFLAGS += -DKTHREAD_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_MEMORY_OPTIMIZATION),y) +EXTRA_CFLAGS += -DMEMORY_OPTIMIZATION +else +EXTRA_CFLAGS += -DDBG +endif + +ifeq ($(CONFIG_RT2860V2_AP_VIDEO_TURBINE),y) +EXTRA_CFLAGS += -DVIDEO_TURBINE_SUPPORT +endif + +ifeq ($(CONFIG_RA_NETWORK_WORKQUEUE_BH),y) +EXTRA_CFLAGS += -DWORKQUEUE_BH +endif + +ifeq ($(CONFIG_RT2860V2_AP_INTELLIGENT_RATE_ADAPTION),y) +EXTRA_CFLAGS += -DNEW_RATE_ADAPT_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_RTMP_INTERNAL_TX_ALC),y) +EXTRA_CFLAGS += -DRTMP_INTERNAL_TX_ALC +endif + +ifeq ($(CONFIG_RT2860V2_AP_RTMP_TEMPERATURE_COMPENSATION),y) +EXTRA_CFLAGS += -DRTMP_TEMPERATURE_COMPENSATION +endif + +ifeq ($(CONFIG_RT2860V2_ADJ_PWR_CONSUMPTION_SUPPORT),y) +EXTRA_CFLAGS += -DADJUST_POWER_CONSUMPTION_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_SINGLE_SKU),y) +ifeq ($(CONFIG_RALINK_MT7620),y) +EXTRA_CFLAGS += -DSINGLE_SKU_V2 +else +EXTRA_CFLAGS += -DSINGLE_SKU +endif +endif + diff --git a/mt7620/src/FirmwareHistory.txt b/mt7620/src/FirmwareHistory.txt new file mode 100755 index 0000000..8e1337b --- /dev/null +++ b/mt7620/src/FirmwareHistory.txt @@ -0,0 +1,53 @@ +[rt2860.bin] + 2006_11_30 Initial version V0.1 which supports LED mode, power saving. + 2006_12_06 V0.2 which fixs LED issue. + 2006_12_13 V0.3 which support signal LED mode. + 2006_??_?? V0.4 which fix led polarity, but driver skip this version + 2007_01_03 V0.5 which modify BBP access architecture. + 2007_03_02 V0.6 which fix bug when radio on/off + 2007_05_04 V0.7 which fix command 0x31 after 0x30, 0x31 may not work. + 2007_08_20 V0.8 which support carrier detection + 2008_02_15 V0.9 which support WPS LED mode on GPIO pin0 + 2008_03_25 V0.9-2 which support power save has whether turn on or off LNA/PA/PE choice + 2008_04_29 V0.10 which support LED mode 7 and 8 (WPS) + 2008_06_24 V0.11 which fix LED behavior if turn on power Consumption + 2008_07_16 V0.12 which fix LED behavior cause by open drain design (RT3090) + 2008_11_13 V0.13 which provides Low power consumption solution(RT3090) + 2008_12_15 V0.14 which read AUX_CTRL and restores AUX_CTRL + 2009_01_05 V0.15 which return erro code when MCU in sleep mode and driver still issue cmd . + 2009_01_15 V0.16 which fix LED slow blink for 3090F . + 2009_02_04 V0.16 Final. which solves two issue : ICH9 dumy interrupt issue & fast blink issue. + 2009_02_12 V0.17 which fixes 3090F Led blink double frequency issue / Fine tune slow blink + 2009_02_16 V0.18 which fixes LED Slow Blink spark issue, 35xx for current leakage issue in radio off mode + 2009_03_17 V0.19 which fixes LED mode 11 issue, patches 3592 0x30 cmd; add LED mode 12 and 13 + 2009_03_18 V0.19 which fixes PLL disable issue + 2009_04_14 V0.20 which fixes LED Mode 10, 3592 Power Saving RF State + 2009_05_25 V0.21 which supports all LED mode for AutoInstall, 0x56 MCU cmd for GPIO, Store&Restore the value of 0x1328 for PSM + 2009_07_08 v0.22 which rollback of 0x1328 PA*EN/ LNA*EN on power saving for 3572 , other using original control (pwrmgnt.c) + v0.23 (for BBP R/W failure issue) is not formal released + 2009_09_04 v0.24 fixes TRSW_en setting bug on single antenna with PSM mode. + 2009_09_05 v0.24B fixes TRSW for 3592 + 2009_10_08 v0.25 fixes led polarity bug, 3562 PSM, BT-CoExist 0x90 MCU Cmd, Auto-Install + 2009_11_20 v0.26 fixed 3593 power saving scheme, power saving level for RT3090BC4 single crystal and + modify ChipVerld definition + +[rt2870.bin] + 2007_07_10 V0.4 Add WPS LED Mode & Site Survey LED Mode + 2007_09_04 V0.5 Support carrier detection + 2008_01_11 V0.6 Update LED Mode + 2008_01_17 V0.7 Update LED Site Surbvey Mode for LED blinking time + 2008_02_15 V0.8 Support WPS LED mode on GPIO pin0 + 2008_04_18 V0.9 Support LED mode 7 and 8 (WPS) + 2008_06_18 V0.10 Support RT3070, antenna diversity, Slow LED blink + 2008_06_23 V0.11 The ACT and RDYG LED are switched on RT3070 + 2008_07_17 V0.12 LED mode 9 + 2008_12_12 V0.13 LED mode 10 + 2009_02_17 V0.14 MCU Cmd 0x36, 0x51; Power sequence of RT3xxx modification + 2009_03_17 V0.15 which fixes LED mode 11 issue, patches 3592 0x30 cmd; add LED mode 12 and 13 + 2009_03_18 V0.15 which fixes PLL disable issue + 2009_04_14 V0.16 which fixes LED mode 10 issue + 2009_05_25 V0.17 which supports all LED mode for AutoInstall, 0x56 MCU cmd for GPIO, Store&Restore the value of 0x1328 for PSM + 2009_07_29 V0.19 For fixing BBP read/write fail issue. + 2009_09_05 v0.20 fixes TRSW_en setting bug on single antenna with PSM mode. + 2009_10_28 v0.21 fix led polarity bug issue, fix 3562 ping lost issue, BT Coexistence 0x90 command, and fix auto install function. + 2009_11_11 V0.22 For fixing BT Hardkey makes GPIO0 floating issue. \ No newline at end of file diff --git a/mt7620/src/History.txt b/mt7620/src/History.txt new file mode 100755 index 0000000..1697de2 --- /dev/null +++ b/mt7620/src/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/mt7620/src/History_sta_pci.txt b/mt7620/src/History_sta_pci.txt new file mode 100755 index 0000000..4c46b22 --- /dev/null +++ b/mt7620/src/History_sta_pci.txt @@ -0,0 +1,255 @@ +[V2.X.X.X] +1. Add RT3593 PCIe support. +2. Add RT3593 STA. + +[V2.4.0.0] +1. Fix issue: No McuCmdLock initialization for RT3592/RT3390. +2. Add RT3592 PCIe chip ID. +3. Fix issue: error link list usage in 11r ric module in station mode. +4. Add an ATE command for AUTOALC. +5. Add an ATE command for interpacket GAP. +6. Add an ATE command for ATE payload pattern. +7. Fix issue: some reports from Prevent software analysis tool. +8. Fix WPS issue: some PIN cannot set successfully.(ex. 89134498) +9. Fix issue: STA send null frame with QoS field when STA connected to non-WMM AP. +10. Suport RFKILL: DO NOT set HAS_RFKILL_HW_SUPPORT=y in config.mk if device doesn't have HW radio on/off button. +11. Reduce data packets lost while doing scan if STA already connects to AP. +12. Fix issue: If there are two APs with same SSID and security mode but have different WPAPSK, + STA may always connect to AP with different WPAPSK if the RSSI of that AP is better than the correct one. +13. Support TxRx ring PRE-ALLOC in probe stage: set RESOURCE_PRE_ALLOC=y in config.mk. +14. Shorten the connection time when interface up. +15. Fix Adhoc issue: If there are more than 2 peers exist, driver didn't delete peer from entry table unless all peers left. +16. Update rt2860.bin: for fixing the 5G band RSSI loss in LED MODE 6/7/8/9/b/c. +17. Fix issue: Correct RSSI, SNR, Noise calculations +18. Fix issue: STA cannot connect to OPEN-WEP AP if WpaSupplicant set WEPAUTO(IW_AUTH_ALG_SHARED_KEY | IW_AUTH_ALG_OPEN_SYSTEM) to driver. +19. Fixed Ad-hoc issue: STA didn't use legacy rate when STA is Ad-hoc creator and security is OPEN-WEP or WPAPSK-TKIP. + +[2.3.0.0] +1. Support PSP XLINK in ad-hoc mode. +2. Add CFG80211 iw utility other commands support (supports Linux 2.6.32). +3. Fix issue: The start address of HeaderBuf must be aligned by 4 when + VENDOR_FEATURE1_SUPPORT is enabled. +4. Fix issue: sometimes rt2860_interrupt() will be called before rt28xx_init() + in fedora core 7. +5. WMM ACM: see history of acm_comm.c. +6. Fix issue in 64bit CPU: + (1) WMM ACM: see history of acm_comm.c. + (2) Fix function RTMP_MapChannelID2KHZ(). +7. Support WpaSupplicant(v0.6.9) WPS +8. Fix WPS issue: Check SelectRegistrar is TRUE or FALSE +9. Fix WPS issue: Some AP (ex. Buffalo WZR-AG300NH) would change SSID to another SSID after push WPS PBC button. + After WPS process finish, change SSID to original SSID. + Driver needs to wait AP to re-generate Beacon; otherwise, driver will update this PBC SSID to MlmeAux. +10. Fix statistics issue: It happened in big-endian platform, tx count would be zero. +11. Support WiFi Draft_3.0 11n test items. +12. Support Linux Kernel 2.6.31/2.6.32. +13. Support Ad-hoc WPS2PSK/AES (DPO doesn't support this item) +14. For GPL issue: Separate three kernel modules - util module, driver module, netif module. util module and netif module could license GPL. + Driver module couldn't license GPL. + +[V2.2.0.0] +1. Fixed issue of showing wrong statistics value. +2. Fixed problem of showing wrong SNR in wireless extension scan list. +3. Fixed WPA2PSK failed with some AP if key length is not zero in pairwise_msg_2 and pairwise_msg_4. +4. Add HAS_STATS_COUNT compile option. +5. Support TDLS. +6. Support Client WDS. +7. Support WMM ACM (Pass WiFi Test Plan v0.30). +8. Support the MAC assignment from configuration file(.dat). +9. Support Ethernet Convert in Ad-hoc mode. +10. Fixed STA cannot do WPS with AP when auth mode of STA is shared. +11. Support SKU. + +[V2.1.2.0] +>> DPA/DPB/DPC/DPD +1. Short GI sampling improvement. +2. Support Linux Kernel 2.6.29 +3. Fixed driver would send zero IWEVASSOCREQIE to Native WpaSupplicant. +4. Fixed driver would send non-zero BSSID to Navtive WpaSupplicant when STA disconnecting to AP. +5. Check Addr1, Addr2 and Addr3 of de-auth packet from AP (driver only checked Addr2 of de-auth packet before). + +[V2.1.2.0] +>> DPO +1. Short GI sampling improvement. +2. Check Addr1, Addr2 and Addr3 of de-auth packet from AP (driver only checked Addr2 of de-auth packet before). + +[V2.1.1.0] +>> Only DPO project has this version +1. Fixed driver would send zero IWEVASSOCREQIE to Native WpaSupplicant. +2. Fixed driver would send non-zero BSSID to Navtive WpaSupplicant when STA disconnecting to AP. +3. Support 2.6.29 + +[V2.1.0.0] +1. New generation schema for multiple OS porting +2. New chip support for RT3562/RT3062/RT3592 +3. Fixed Ad-hoc ping failed in noisy environment. (Probe Response has too many retry packet then cause "not enough space in MgmtRing") +4. Fixed WPA(2)PSK issue when group cipher of AP is WEP40 or WEP104. +5. Modified iwpriv ra0 get_site_survey: + In scan list result: Security shows "NONE" when AP is OPEN/NONE, + shows "WEP" when AP is OPEN/WEP or SHARED/WEP, + shows "WPAPSK(WPA2PSK)/TKIP(AES)" when AP is WPAPSK(WPA2PSK)/TKIP(AES) + shows "WPA(WPA2)/TKIP(AES)" when AP is WPA(WPA2)/TKIP(AES) +6. Fixed WPS failed with D-Link DIR-628 in 5GHz. +7. When cipher is WEP or TKIP, STA would connect to 11N AP with legacy rate. + "iwpriv ra0 set HtDisallowTKIP=val": Enable/Disable N rate with 11N ap when cipher is WEP or TKIP. + val: + 0 : FALSE + 1 : TRUE + Default setting is disable. +8. Add "iwpriv ra0 wsc_ap_band val" command for setting prefer band to do WPS with dual band WPS AP. + val: + 0 : prefer 2.4G + 1 : prefer 5G + 2 : auto + Default value is auto (2) +9. Add "iwpriv ra0 set BeaconLostTime=val" command for user to change Beacon Lost Time. + val: + 1 ~ 60 seconds + Default value is 4 seconds +10. Change FastRoaming in DAT file to AutoRoaming. + Add "iwpriv ra0 set AutoRoaming=val" command for user to enable/disable auto roaming mechanism. + 0 : disable + 1 : enable + Default setting is disable. +11. Support kthread. +12. Add "iwpriv ra0 set SiteSurvey=val" command for user to scan with specific SSID after Link Up. + val: + 0~z, 1~32 ascii characters +13. Add New A band channel list region 15 contains the whole channels in the A band region 4 and the new CE channel 167,169,171,173. +14. New IEEE802.11r functionality. +15. Fixed WPA2-Enterprise failed when AP reboot or turn off then turn on. +16. Fixed STA cannot connect to 11B only AP when the setting of is PHY_11GN. +17. Support Linux Kernel 2.6.28 & 2.6.29 (only 3062 V2.1.0.0 supports this item) + +[V2.0.1.0] +1. fix eFuse bug on big-endian platform +2. fix WMM problem for RT3091/92 +3. fix one bug for ATE TX power handling and ATE frequency offset bug. +4. fix mesh crash issue +5. fix RT309x AMPDU throughput bug after interface down/up +6. fix RT309x PCI-E compatibility issue. +7. fix RT309x difficult to enter power save mode issue. +8. fix a bug that is hard to connect with hidden-SSID AP. + +[V2.0.0.0] +1. Support new chips RT3090/91/92. +2. Lots of patch and bug fix from last release. +3. Support eFuse. +4. Support Antenna Diversity for RT3070. + +[1.8.0.0] +1. Fixed compile error when CARRIER_DETECTION_SUPPORT is enabled. +2. Add "iwpriv ra0 set CarrierDetect=0(or 1)" +3. Add new WSC hardware push button function +4. Add Ad-Hoc to support N rate. +5. Migrate Mesh supporting to Draft-2.0. +6. Support WAPI functionality +7. Fixed suspend/resume error when ra0 down, ra0 up. +8. Support Linux Kernel 2.6.27 +9. Fixed WPS failed when AP is not in scan table or AP's channel changing after user sets "iwpriv ra0 wsc_start" +10. Fixed DLS A-MPDU established failed. + +[1.7.0.0] +1. Support SIOCSIWGENIE, SIOCGIWGENIE, SIOCSIWMLME, SIOCGIWENCODEEXT, and SIOCSIWPMKSA. +2. Support IWEVGENIE in iwlist ra0 scan. +3. Support DLS +4. Fixed connection failed with Range Maximizer - 515 AP (Marvell Chip) when security is WPAPSK/TKIP. +5. Fixed length error of RSN/SSN IE for WpaSupplicant. +6. Fixed WPAPSK rekey problem when A-MSDU is enabled. +7. Fixed NetworkManager cannot detect ra0 when ra0 is not up. +8. Add IEEE802.11d Client Mode: None, Flexible, Strcit. +9. Add Station N only mode. (Only connects to N-AP) +10. Add Global country domain(ch1-11:active scan, ch12-14 passive scan) +11. Enhance PCIe advance power saving +12. Modified iwpriv ra0 get_site_survey: When security of AP is OPEN/WEP or SHARED/WEP, show UNKNOW/WEP in scan list. +13. When the secondary channel of AP exceeds the country region's range, station will auto fallback to 20MHz. i.e. need both control and secondary channel are both + in country region's channel list. +14. Fixed crash in LinkDown when there are >64 APs exists. + +[V1.6.2.0] +>> Only DPO project has this version +1. Enhance PCIe advance power saving. +2. Update rt2860.bin for PCIe advance power saving. +3. Fixed length error of RSN/SSN IE for WpaSupplicant. +4. Add vendor ID and device ID for EEEPC(VEN_AWT_PCIe_DEVICE_ID 0x1059, VEN_AWT_PCI_VENDOR_ID 0x1A3B) + +[V1.6.1.1] +>> Only DPO project has this version +1. Fixed connection failed with Range Maximizer - 515 AP (Marvell Chip) when security is WPAPSK/TKIP + +[V1.6.1.0] +1. Init MAC register 0x1204 to 0x3 + +[V1.6.0.0] +1. Fixed issue of Radar Channel flag building with HAS_EXT_BUILD_CHANNEL_LIST=n. +2. Fixed issue of Adhoc-STA would create in radar channel. +3. Support Mesh +4. Support Linux Kernel 2.6.24 +5. Support SNMP +6. Support Debug Diagnose +7. Add Makefile.NonLoadableModule for non-loadable module +8. Add two ioctl commands to change tx long/short retry limit. +9. Fixed WPS STA is hard to do WPS process with Broadcom WPS AP Proxy and Marvell WPS External Registrar. + +[V1.5.0.0] +1. New code base - RT28xx. +2. Add BaSmartHardTransmit mechanism. +3. Support Linux Kernel 2.6 suspend and resume. +4. Support extened channel list. +5. Add "iwconfig rate" setting for legacy rate. +6. Add make install/uninstall to Makfile. +7. Fixed issue of showing SNR1 information. +8. ATE: Add command "iwpriv ra0 set ATELDE2P=1" to overwrite all EEPROM contents from a .bin file. +9. Change IRQ LOCK to SEM LOCK +10. Support Non-GPL MD5 + +[V1.4.0.0] +1. Fixed Legacy Wi-Fi WMM S06 fail. +2. Fixed WPAPSK failed when 2860 STA Aggregation is enabled and connects with 2860 N/Aggregation AP. +3. Fixed "iwconfig ra0 essid" +4. Send DIS-ASSOC request to AP when ra0 down. +5. Support 5-GHz band ATE. +6. Fixed fixed rate issue in N mode and fixed rate ioctl. +7. Add Legacy Power Saving Mode. +8. Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode. +9. Fixed ping failed with Broadcom N AP when AP is GF enabled and STA is auto rate. +10. Support custom wireless event. +11. Modify rate adaptation for fast ramp-up tuning. + +[V1.3.0.0] +1. Support Monitor Mode with WireShark.(Usage: iwconfig ra0 mode monitor) +2. Update Rate Adaptation Algorithm. +3. Add ATE function(also QA supported). +4. Support IPv6 Ethernet Convert Mechanism. +5. Support NetworkManager, wpa_supplicant by using wext. +6. Fixed Auto Rate Select issue.(When RT2860 Linux STA links up with N-AP then chaged to link up with legacy-AP) +7. Fixed Fast-Roaming Fail Issue. + +[V1.2.1.0] +1. Fixed segmentation fault when size of iwpriv ra0 get_site_survey result exceeded 4096. +2. Add MAT related iwpriv commands. +3. Add AP's wireless mode info to iwpriv ra0 get_site_survey. +4. Modify bitrate info in iwlist ra0 scan. + +[V1.2.0.0] +1. Update NicConfig2 default value. +2. Modify STA to retrieve the MCS of AP(from Beacon) and save to StaActive structure. +3. Add WPS re-generate PIN command: iwpriv ra0 wsc_gen_pincode. +4. Do NOT re-build M-messages in WPS state machine timeout timer function. +5. Fixed compile error in non-DBG mode. + +[V1.1.0.0] +1. Fixed WI-FI test item 5.2.2.9 #S7, STA will fail to authenticate when AP set fragmentation to 500. +2. Fxied iwpriv security setting issue. +3. Re-organize the Rx data path. +4. Update Tx Power mechanism. +5. Support WPS In-band(EAP) & Out-Of-band(UPnP) Enrollee mode and In-band(EAP) Registrar mode. +6. Add WPS related iwpriv commands +7. Support Dongle/Clone/Dongle+Clone mechanism +8. Support Big-Endian. + +[V1.0.0.0] +1. Chariot Throughput ok +2. Driver security support: Open/Shared WEP, WPA-PSK, WPA2-PSK, WPA-NONE. +3. Support 32/64-bit OS +4. Support A-MPDU and A-MSDU diff --git a/mt7620/src/History_sta_usb.txt b/mt7620/src/History_sta_usb.txt new file mode 100755 index 0000000..82443c8 --- /dev/null +++ b/mt7620/src/History_sta_usb.txt @@ -0,0 +1,258 @@ +[V2.5.0.1] +1. Fix P2P CLIENT use PBC to connect P2P GO as negotiate by KEYPAD / DISPLAY. +2. Fix P2P CLIENT difficult connect on P2P GO need scan times with wrong BSSID. +3. Fix P2P CLIENT not use N-rate transmit data to GO. +4. Fix P2P concurrent mode as INFRA + P2P_CLIENT with different HT_BW. +5. Fix P2P Link Down not turn back to Listen Channel cause can¡¦t be found. + +[V2.5.0.0] +1. Support WIFI Direct(WIFI P2P). +2. supporting Linux Kernel 2.6.35. +3. Fixed Ad-hoc issue: STA didn't use legacy rate when STA is Ad-hoc creator and security is OPEN-WEP or WPAPSK-TKIP. +4. Fixed WPS issue: Beacon lost when STA tries to do WPS with WPS AP or STA connects to hidden AP. +5. Fixed WPS issue: WPS procedure is taking much longer than before. +6. Corrected WPS behavior: According to the response from WFA: while doing PBC, STA shall stop if STA finds more than one AP avaliable. +7. Fixed issue: WPS failed with Ralink WpaSupplicant when STA's privacy is different from AP's privacy. (for example: AP is WPA2PSK but STA is OPEN) +8. Fixed Ralink WpaSupplicant issue - Scan table didn't include RSSI. +9. Fixed issue: STA had problem to show 32-bytes SSID when user uses "iwpriv ra0 show SSID" or "iwpriv ra0 stat" to check SSID of WSC profile. +10. Fixed issue: If there are two APs have same SSID, AuthMode and EncrypType but different WPAPSK key, + driver will only try the AP with better RSSI. + If that AP with better RSSI has the different WPAPSK with STA, + driver still keeps trying to connect that AP with better RSSI. +11. Refine the stack size of all functions to be smaller than 1024B. +12. Fixed WPS issue: When session overlap detect, the WPS LED will not turn off for WPS LED mode 9 after 2 minutes timeout. +13. Fixed issue: Use wrong rate index in send_monitor_packets(). +14. Improve scan mechanism. +15. Fixed issue: STA supports the WPA authentication which group cipher is WEP. +16. Support to generate random WSC 4-digits PIN. +17. Support Intel WIDI (only DPAW has Intel WIDI) +18. Fixed issue: Single SKU Bandedge Delta value decrease all channels transmit power on FCC, it should work on Channel 1 / 11. + +[2.4.0.2] +1. Fix issue: cannot read new efuse data. + +[V2.4.0.0] +1. Rename crda.c to cfg80211.c, CRDA_SUPPORT to RT_CFG80211_SUPPORT. +2. Fix issue in 64bit CPU: + (1) WMM ACM: see history of acm_comm.c. + (2) Fix function RTMP_MapChannelID2KHZ(). +3. Fix issue: error link list usage in 11r ric module in station mode. +4. Add an ATE command for AUTOALC. +5. Add an ATE command for interpacket GAP. +6. Add an ATE command for ATE payload pattern. +7. Fix issue: some reports from Prevent software analysis tool. +8. Fix WPS issue: some PIN cannot set successfully.(ex. 89134498) +9. Fix issue: STA send null frame with QoS field when STA connected to non-WMM AP. +10. Suport RFKILL: DO NOT set HAS_RFKILL_HW_SUPPORT=y in config.mk if device doesn't have HW radio on/off button. +11. Reduce data packet lost while doing scan if STA already connects to AP. +12. Fix issue: If there are two APs with same SSID and security mode but have different WPAPSK, + STA may always connect to AP with different WPAPSK if the RSSI of that AP is better than the correct one. +13. Support TxRx ring PRE-ALLOC in probe stage: set RESOURCE_PRE_ALLOC=y in config.mk. +14. Shorten the connection time: set FastConnect=1 in DAT file. +15. Update rt2870.bin: for fixing the 5G band RSSI loss in LED MODE 6/7/8/9/b/c. +16. Fix Adhoc issue: If there are more than 2 peers exist, driver didn't delete peer from entry table unless all peers left. +17. Fix issue: Correct RSSI, SNR, Noise calculations +18. Fix issue: STA cannot connect to OPEN-WEP AP if WpaSupplicant set WEPAUTO(IW_AUTH_ALG_SHARED_KEY | IW_AUTH_ALG_OPEN_SYSTEM) to driver. + +[2.3.1.0] +1. CFG80211: Patch for Linux 2.6.32. + +[2.3.0.0] +1. Support PSP XLINK in ad-hoc mode. +2. Add mac80211 iw utility other commands support. +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. Support WpaSupplicant(v0.6.9) WPS +6. Fix WPS issue: Check SelectRegistrar is TRUE or FALSE +7. Fix WPS issue: Some AP (ex. Buffalo WZR-AG300NH) would change SSID to another SSID after push WPS PBC button. + After WPS process finish, change SSID to original SSID. + Driver needs to wait AP to re-generate Beacon; otherwise, driver will update this PBC SSID to MlmeAux. +8. Shorten the waiting time when unplug the device. +9. Fix mgmt ring full issue: It happened only in big-endian platform and quickly switch the network type between Infra and Adhoc mode. +10. Fix statistics issue: It happened in big-endian platform, tx count would be zero. +11. Support WiFi Draft_3.0 11n test items. +12. Support Linux Kernel 2.6.31 +13. Support Ad-hoc WPS2PSK/AES (DPO doesn't support this item) +14. Support Samsung Auto Provision (only for Samsung Project) +15. For GPL issue: Separate three kernel modules - util module, driver module, netif module. util module and netif module could license GPL. + Driver module couldn't license GPL. + +[V2.2.0.0] +1. Fixed issue of showing wrong statistics value. +2. Fixed problem of showing wrong SNR in wireless extension scan list. +3. Fixed WPA2PSK failed with some AP if key length is not zero in pairwise_msg_2 and pairwise_msg_4. +4. Add HAS_STATS_COUNT compile option. +5. Support TDLS. +6. Support Client WDS. +7. Support WMM ACM (Pass WiFi Test Plan v0.30). +8. Support the MAC assignment from configuration file(.dat). +9. Support Ethernet Convert in Ad-hoc mode. +10. Support SKU. + +[V2.1.2.0] +>> DPA/DPB/DPC/DPD +1. Short GI sampling improvement. +2. Support Linux Kernel 2.6.29 +3. Fixed driver would send zero IWEVASSOCREQIE to Native WpaSupplicant. +4. Fixed driver would send non-zero BSSID to Navtive WpaSupplicant when STA disconnecting to AP. +5. Check Addr1, Addr2 and Addr3 of de-auth packet from AP (driver only checked Addr2 of de-auth packet before). + +[V2.1.2.0] +>> DPO +1. Short GI sampling improvement. +2. Check Addr1, Addr2 and Addr3 of de-auth packet from AP (driver only checked Addr2 of de-auth packet before). + +[V2.1.1.0] +>> Only DPO project has this version +1. Fixed that Enqueue command to command thread would fail when HAS_KTHREAD_SUPPORT=n in config.mk. +2. Fixed driver would send zero IWEVASSOCREQIE to Native WpaSupplicant. +3. Fixed driver would send non-zero BSSID to Navtive WpaSupplicant when STA disconnecting to AP. +4. Support 2.6.29 + +[V2.1.0.0] +1. New generation schema for multiple OS porting +2. New chip support for RT3572 +3. Fixed Ad-hoc ping failed in noisy environment. (Probe Response has too many retry packet then cause "not enough space in MgmtRing") +4. Modified iwpriv ra0 get_site_survey: + In scan list result: Security shows "NONE" when AP is OPEN/NONE, + shows "WEP" when AP is OPEN/WEP or SHARED/WEP, + shows "WPAPSK(WPA2PSK)/TKIP(AES)" when AP is WPAPSK(WPA2PSK)/TKIP(AES) + shows "WPA(WPA2)/TKIP(AES)" when AP is WPA(WPA2)/TKIP(AES) +5. Fixed WPS failed with D-Link DIR-628 in 5GHz. +6. When cipher is WEP or TKIP, STA would connect to 11N AP with legacy rate. + "iwpriv ra0 set HtDisallowTKIP=val": Enable/Disable N rate with 11N ap when cipher is WEP or TKIP. + val: + 0 : FALSE + 1 : TRUE + Default setting is disable. +7. Add "iwpriv ra0 wsc_ap_band val" command for setting prefer band to do WPS with dual band WPS AP. + val: + 0 : prefer 2.4G + 1 : prefer 5G + 2 : auto + Default value is auto (2) +8. Add "iwpriv ra0 set BeaconLostTime=val" command for user to change Beacon Lost Time. + val: + 1 ~ 60 seconds + Default value is 4 seconds +9. Change FastRoaming in DAT file to AutoRoaming. + Add "iwpriv ra0 set AutoRoaming=val" command for user to enable/disable auto roaming mechanism. + 0 : disable + 1 : enable + Default setting is disable. + +10. Support kthread. +11. Add "iwpriv ra0 set SiteSurvey=val" command for user to scan with specific SSID after Link Up. + val: + 0~z, 1~32 ascii characters +12. Add New A band channel list region 15 contains the whole channels in the A band region 4 and the new CE channel 167,169,171,173. +13. New IEEE802.11r functionality. +14. New eFuse function and eFuse buffer mode. +15. fix mesh bugs. +16. fix mesh connection problem after setting WAPI security mode. +17. bug fixes. + + +[V2.0.1.0] +0. Finished verifying RT3071 STA support. +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. fix RT307x difficult to enter power save mode issue. +7. fix a bug that is hard to connect with hidden-SSID AP. +8. update RT307x new firmware. + +[V2.0.0.0] +1. Support new chips RT3070/71/72. +2. Lots of patch and bug fix from last release. +3. Support eFuse. +4. Support Antenna Diversity for RT3070. + +[V1.4.0.0] +1. Add IWEVGENIE in iwlist ra0 scan. +2. Add new WSC hardware push button function +3. Add Ad-Hoc to support N rate. +4. Add "iwpriv ra0 set CarrierDetect=0(or 1)" +5. Add Station N only mode in Infra mode. (Only connects to N-AP) +6. Add Global country domain(ch1-11:active scan, ch12-14 passive scan) +7. Fixed connection failed with Range Maximizer - 515 AP (Marvell Chip) when security is WPAPSK/TKIP. +8. Fixed crash in LinkDown when there are >64 APs exists. +9. Fixed compile error when CARRIER_DETECTION_SUPPORT is enabled. +10. Fixed suspend/resume error when ra0 down, ra0 up +11. Modified iwpriv ra0 get_site_survey: When security of AP is OPEN/WEP or SHARED/WEP, show UNKNOW/WEP in scan list. +12. When the secondary channel of AP exceeds the country region's range, station will auto fallback to 20MHz. i.e. need both control and secondary channel are both + in country region's channel list. +13. Migrate Mesh supporting to Draft-2.0. +14. Support DLS +15. Support WAPI functionality +16. Support Linux Kernel 2.6.27 +17. Fixed WPS failed when AP is not in scan table or AP's channel changing after user sets "iwpriv ra0 wsc_start" +18. Add WPS Wireless Event strings. +19. Fixed WPA(2)PSK issue when group cipher of AP is WEP40 or WEP104. + + +[V1.3.1.0] +1. Fixed compile error on Linux Kernel 2.6.26 +2. Fixed length error of RSN/SSN IE for WpaSupplicant. + +[V1.3.0.0] +1. Fixed issue of Radar Channel flag building with HAS_EXT_BUILD_CHANNEL_LIST=n. +2. Fixed issue of Adhoc-STA would create in radar channel. +3. Fixed LED issue of "ifconfig ra0 down". +4. Support Mesh (DPO doesn't have Mesh mechanism.) +5. Support Linux Kernel 2.6.24 +6. Support SNMP +7. Support Debug Diagnose +8. Add IEEE802.11d Client Mode: None, Flexible, Strcit. +9. Add two ioctl commands to change tx long/short retry limit. +10. Fixed WPS STA is hard to do WPS process with Broadcom WPS AP Proxy and Marvell WPS External Registrar. +11. Fixed WPS STA didn't send dis-assoc to AP after WPS processing. +12. Fixed WPAPSK rekey problem when A-MSDU is enabled. + +[V1.2.2.0] +1. Fixed TX Bulk-Out Failed issue. +2. Fixed "iwlist ra0 scan" to show wpa_ie and rsn_ie when AP is WPAPSKWPA2PSK. +3. Support extened channel list. + +[V1.2.1.0] +1. Fixed rate issue on Adhoc mode. +2. Fixed other Adhoc STA re-join failed with security. +3. Add "iwconfig rate" setting for legacy rate. +4. ATE: Add command "iwpriv ra0 set ATELDE2P=1" to overwrite all EEPROM contents from a .bin file. +5. Fixed issue of showing SNR1 information. +6. Add make install/uninstall to Makfile. + +[V1.2.0.0] +1. New code base - RT28xx +2. Add Legacy Power Saving Mode. +3. Add BaSmartHardTransmit mechanism. +4. Modify rate adaptation for fast ramp-up tuning. +5. Support custom wireless event. +6. Support Ethernet Convert Mechanism. +7. Support Linux Kernel 2.6 suspend and resume. +8. Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode. +9. Fixed fixed rate issue in N mode and fixed rate ioctl. + +[V 1.1.0.0] +1. WPS support. +2. Modified Link Status related information for Ralink WebUI. +3. Support WPA/WPA2-Enterprise and 802.11X WEP by using WPA_SUPPLICANT. +4. Fixed Ralink WebUI scan fault bug. +5. Fixed 1x authentication issue that STA will fail to authenticate when AP set fragmentation to 500. +6. Fixed WPS failed with Marvell external registrar. +7. Fixed mlme thread didn't de-queue when mlme queue full happened. +8. Fixed Adhoc WPANONE failed by setting from Ralink WebUI. +9. Fixed WPA(2)PSK failed when encryption type of AP is TKIP+AES. +10. Fixed Linux Kernel would dump warning messages when do RTUSB_VendorRequest in irq lock. + +[V 1.0.0.0] +Create RT2870STA +>> Supported: +1. Security Mode : OPEN/NONE, OPEN/WEP, SHARED/WEP, WPA(2)PSK/TKIP, WPA(2)PSK/AES, WPANONE/TKIP, WPANONE/AES. +2. WMM capable. +3. HT MPDU Aggregation. +4. Little endian, x86 platform. +5. Ralink WebUI diff --git a/mt7620/src/Makefile b/mt7620/src/Makefile new file mode 100644 index 0000000..3c587ee --- /dev/null +++ b/mt7620/src/Makefile @@ -0,0 +1,522 @@ +ifeq ($(WIFI_MODE),) +RT28xx_MODE = APSTA +else +RT28xx_MODE = $(WIFI_MODE) +endif + +ifeq ($(TARGET),) +TARGET = LINUX +endif + +ifeq ($(CHIPSET),) +CHIPSET = RBUS +endif + +MODULE = $(word 1, $(CHIPSET)) + +#OS ABL - YES or NO +OSABL = NO + +ifneq ($(TARGET),THREADX) +#RT28xx_DIR = home directory of RT28xx source code +RT28xx_DIR = $(shell pwd) +endif + +include $(RT28xx_DIR)/os/linux/config.mk + +RTMP_SRC_DIR = $(RT28xx_DIR)/RT$(MODULE) + +#PLATFORM: Target platform +PLATFORM = PC +#PLATFORM = 5VT +#PLATFORM = IKANOS_V160 +#PLATFORM = IKANOS_V180 +#PLATFORM = SIGMA +#PLATFORM = SIGMA_8622 +#PLATFORM = INIC +#PLATFORM = STAR +#PLATFORM = IXP +#PLATFORM = INF_TWINPASS +#PLATFORM = INF_DANUBE +#PLATFORM = INF_AR9 +#PLATFORM = INF_VR9 +#PLATFORM = BRCM_6358 +#PLATFORM = INF_AMAZON_SE +#PLATFORM = CAVM_OCTEON +#PLATFORM = CMPC +#PLATFORM = RALINK_2880 +#PLATFORM = RALINK_3052 +#PLATFORM = SMDK +#PLATFORM = RMI +#PLATFORM = RMI_64 +#PLATFORM = KODAK_DC +#PLATFORM = DM6446 +#PLATFORM = FREESCALE8377 +#PLATFORM = BL2348 +#PLATFORM = BL23570 +#PLATFORM = BLUBB +#PLATFORM = BLPMP +#PLATFORM = MT85XX +#PLATFORM = NXP_TV550 +#PLATFORM = MVL5 +#PLATFORM = RALINK_3352 +#PLATFORM = UBICOM_IPX8 +#PLATFORM = INTELP6 + +#APSOC +ifeq ($(MODULE),3050) +PLATFORM = RALINK_3050 +endif +ifeq ($(MODULE),3052) +PLATFORM = RALINK_3052 +endif +ifeq ($(MODULE),3350) +PLATFORM = RALINK_3050 +endif +ifeq ($(MODULE),3352) +PLATFORM = RALINK_3352 +endif + + +#RELEASE Package +RELEASE = ARCH + + +ifeq ($(TARGET),LINUX) +MAKE = make +endif + +ifeq ($(TARGET), UCOS) +MAKE = make +endif +ifeq ($(TARGET),THREADX) +MAKE = gmake +endif + +ifeq ($(TARGET), ECOS) +MAKE = make +MODULE = $(shell pwd | sed "s/.*\///" ).o +export MODULE +endif + +ifeq ($(PLATFORM),5VT) +LINUX_SRC = /home/ralink-2860-sdk-5vt-distribution/linux-2.6.17 +CROSS_COMPILE = /opt/crosstool/uClibc_v5te_le_gcc_4_1_1/bin/arm-linux- +endif + +ifeq ($(PLATFORM),UBICOM_IPX8) +LINUX_SRC = /home/sample/Customers/UBICOM/ubicom-linux-dist-2.1.1/linux-2.6.x +CROSS_COMPILE = ubicom32-elf- +endif + +ifeq ($(PLATFORM),IKANOS_V160) +LINUX_SRC = /home/sample/projects/LX_2618_RG_5_3_00r4_SRC/linux-2.6.18 +CROSS_COMPILE = mips-linux- +endif + +ifeq ($(PLATFORM),IKANOS_V180) +LINUX_SRC = /home/sample/projects/LX_BSP_VX180_5_4_0r1_ALPHA_26DEC07/linux-2.6.18 +CROSS_COMPILE = mips-linux- +endif + +ifeq ($(PLATFORM),SIGMA) +LINUX_SRC = /root/sigma/smp86xx_kernel_source_2.7.172.0/linux-2.6.15 +CROSS_COMPILE = /root/sigma/smp86xx_toolchain_2.7.172.0/build_mipsel_nofpu/staging_dir/bin/mipsel-linux- +endif + +ifeq ($(PLATFORM),SIGMA_8622) +LINUX_SRC = /home/snowpin/armutils_2.5.120.1/build_arm/linux-2.4.22-em86xx +CROSS_COMPILE = /home/snowpin/armutils_2.5.120.1/toolchain/bin/arm-elf- +CROSS_COMPILE_INCLUDE = /home/snowpin/armutils_2.5.120.1/toolchain/lib/gcc-lib/arm-elf/2.95.3 +endif + +ifeq ($(PLATFORM),INIC) +UCOS_SRC = /opt/uCOS/iNIC_rt2880 +CROSS_COMPILE = /usr/bin/mipsel-linux- +endif + +ifeq ($(PLATFORM),STAR) +LINUX_SRC = /opt/star/kernel/linux-2.4.27-star +CROSS_COMPILE = /opt/star/tools/arm-linux/bin/arm-linux- +endif + +ifeq ($(PLATFORM),RMI) +LINUX_SRC = /opt/rmi/1.7.0/linux/src/ +CROSS_COMPILE = /opt/rmi/1.7.0/mipscross/nptl/bin/mips64-unknown-linux-gnu- +endif + +ifeq ($(PLATFORM),RMI_64) +LINUX_SRC = /opt/rmi/1.7.0/linux_64/src/ +CROSS_COMPILE = /opt/rmi/1.7.0/mipscross/nptl/bin/mips64-unknown-linux-gnu- +endif + +ifeq ($(PLATFORM), RALINK_2880) +LINUX_SRC = /project/stable/RT288x/RT288x_SDK/source/linux-2.4.x +CROSS_COMPILE = /opt/buildroot-gdb/bin/mipsel-linux- +endif + +ifeq ($(PLATFORM),RALINK_3052) +LINUX_SRC = /home/peter/ap_soc/SDK_3_3_0_0/RT288x_SDK/source/linux-2.6.21.x +CROSS_COMPILE = /opt/buildroot-gcc342/bin/mipsel-linux-uclibc- +endif + +ifeq ($(PLATFORM),FREESCALE8377) +LINUX_SRC = /opt/ltib-mpc8377_rds-20090309/rpm/BUILD/linux-2.6.25 +CROSS_COMPILE = /opt/freescale/usr/local/gcc-4.2.187-eglibc-2.5.187/powerpc-linux-gnu/bin/powerpc-linux-gnu- +endif + +ifeq ($(PLATFORM),BL2348) +LINUX_SRC = /home/sample/Customers/BroadLight/bl234x-linux-2.6.21-small-v29 +CROSS_COMPILE = mips-wrs-linux-gnu- +endif + +ifeq ($(PLATFORM),BL23570) +LINUX_SRC = /home/FIBERHOME/linux-2.6.34.8 +CROSS_COMPILE = mips-wrs-linux-gnu-mips_74k_softfp-glibc_small- +ARCH:=mips +export $ARCH +endif + + +ifeq ($(PLATFORM),BLUBB) +LINUX_SRC = /home/sample/Customers/BroadLight/UBB/gmp20/linux-2.6.21-small +CROSS_COMPILE = mips-wrs-linux-gnu- +endif + +ifeq ($(PLATFORM),BLPMP) +LINUX_SRC = /home/sample/Customers/BroadLight/UBB/pmp16/bl234x-linux-2.6.21-small-v30.2 +CROSS_COMPILE = mips-wrs-linux-gnu- +endif + +ifeq ($(PLATFORM),PC) +# Linux 2.6 +LINUX_SRC = /lib/modules/$(shell uname -r)/build +# Linux 2.4 Change to your local setting +#LINUX_SRC = /usr/src/linux-2.4 +LINUX_SRC_MODULE = /lib/modules/$(shell uname -r)/kernel/drivers/net/wireless/ +CROSS_COMPILE = +endif + +ifeq ($(PLATFORM),INTELP6) +LINUX_SRC = /tftpboot/IntelCE-20.0.11052.243193/project_build_i686/IntelCE/kernel-20.0.11024.238456/linux-2.6.35 +CROSS_COMPILE = /tftpboot/IntelCE-20.0.11052.243193/build_i686/i686-linux-elf/bin/i686-cm-linux- +endif + +ifeq ($(PLATFORM),IXP) +LINUX_SRC = /project/stable/Gmtek/snapgear-uclibc/linux-2.6.x +CROSS_COMPILE = arm-linux- +endif + +ifeq ($(PLATFORM),INF_TWINPASS) +# Linux 2.6 +#LINUX_SRC = /lib/modules/$(shell uname -r)/build +# Linux 2.4 Change to your local setting +LINUX_SRC = /project/stable/twinpass/release/2.0.1/source/kernel/opensource/linux-2.4.31/ +CROSS_COMPILE = mips-linux- +endif + +ifeq ($(PLATFORM),INF_DANUBE) +LINUX_SRC = /opt/danube/sdk/linux-2.6.16.x +CROSS_COMPILE = mips-linux- +ROOTDIR = /opt/danube/sdk +export ROOTDIR +endif + +ifeq ($(PLATFORM),INF_AR9) +LINUX_SRC = /root/ar9/xR9_BSP1.2.2.0/source/kernel/opensource/linux-2.6.20/ +CROSS_COMPILE = /root/ar9/ifx-lxdb26-1.0.2/gcc-3.4.4/toolchain-mips/bin/ +endif + +ifeq ($(PLATFORM),INF_VR9) +LINUX_SRC = /home/public/lantiq/VR9/UGW-4.2/build_dir/linux-ifxcpe_platform_vr9/linux-2.6.20.19 +CROSS_COMPILE = /home/public/lantiq/VR9/UGW-4.2/staging_dir/toolchain-mips_gcc-3.4.6_uClibc-0.9.29/bin/mips-linux- +endif + +ifeq ($(PLATFORM),BRCM_6358) +LINUX_SRC = +CROSS_COMPILE = +endif + +ifeq ($(PLATFORM),INF_AMAZON_SE) +# Linux 2.6 +#LINUX_SRC = /lib/modules/$(shell uname -r)/build +# Linux 2.4 Change to your local setting +LINUX_SRC = /backup/ifx/3.6.2.2/source/kernel/opensource/linux-2.4.31 +#CROSS_COMPILE = mips-linux- +#LINUX_SRC = /project/Infineon/3.6.2.2/source/kernel/opensource/linux-2.4.31 +CROSS_COMPILE = /opt/uclibc-toolchain/ifx-lxdb-1-2-3-external/gcc-3.3.6/toolchain-mips/R0208V35/mips-linux-uclibc/bin/ +endif + +ifeq ($(PLATFORM),ST) +LINUX_SRC = /opt/STM/STLinux-2.2/devkit/sources/kernel/linux0039 +CROSS_COMPILE = /opt/STM/STLinux-2.2/devkit/sh4/bin/sh4-linux- +ARCH := sh +export ARCH +endif + +ifeq ($(PLATFORM),CAVM_OCTEON) +OCTEON_ROOT = /usr/local/Cavium_Networks/OCTEON-SDK +LINUX_SRC = $(OCTEON_ROOT)/linux/kernel_2.6/linux +CROSS_COMPILE = mips64-octeon-linux-gnu- +endif + +ifeq ($(PLATFORM),CMPC) +LINUX_SRC = /opt/fvt_11N_SDK_0807/fvt131x_SDK_11n/linux-2.6.17 +CROSS_COMPILE = +endif + +ifeq ($(PLATFORM),SMDK) +LINUX_SRC = /home/bhushan/itcenter/may28/linux-2.6-samsung +CROSS_COMPILE = /usr/local/arm/4.2.2-eabi/usr/bin/arm-linux- +endif + +ifeq ($(PLATFORM),RALINK_3352) +LINUX_SRC = /home/sample/3352/RT288x_SDK/source/linux-2.6.21.x +CROSS_COMPILE = /opt/buildroot-gcc342/bin/mipsel-linux- +endif + +ifeq ($(PLATFORM),KODAK_DC) +SKD_SRC = C:/SigmaTel/DC1250_SDK_v1-9/sdk +CROSS_COMPILE = $(cc) +endif + +ifeq ($(PLATFORM),DM6446) +LINUX_SRC = /home/fonchi/work/soc/ti-davinci +endif + +ifeq ($(PLATFORM),MT85XX) +LINUX_SRC = /home/john/MTK/BDP_Linux/linux-2.6.27 +CROSS_COMPILE = armv6z-mediatek-linux-gnueabi- +endif + +ifeq ($(PLATFORM),NXP_TV550) +LINUX_SRC = /data/tv550/kernel/linux-2.6.28.9 +LINUX_SRC_MODULE = /data/tv550/kernel/linux-2.6.28.9/drivers/net/wireless +CROSS_COMPILE = /opt/embeddedalley/nxp_tv550/bin/mipsel-linux- +endif + +ifeq ($(PLATFORM),MVL5) +LINUX_SRC = /home2/charlestu/AP-VT3426/linux-2.6.18 +CROSS_COMPILE = /opt/montavista/pro/devkit/arm/v5t_le_mvl5/bin/arm_v5t_le- +endif + +export OSABL RT28xx_DIR RT28xx_MODE LINUX_SRC CROSS_COMPILE CROSS_COMPILE_INCLUDE PLATFORM RELEASE CHIPSET MODULE RTMP_SRC_DIR LINUX_SRC_MODULE TARGET HAS_WOW_SUPPORT + +# The targets that may be used. +PHONY += all build_tools test UCOS THREADX LINUX release prerelease clean uninstall install libwapi osabl + +ifeq ($(TARGET),LINUX) +all: build_tools $(TARGET) +else +all: $(TARGET) +endif + + + +build_tools: + $(MAKE) -C tools + $(RT28xx_DIR)/tools/bin2h + +test: + $(MAKE) -C tools test + +UCOS: + $(MAKE) -C os/ucos/ MODE=$(RT28xx_MODE) + echo $(RT28xx_MODE) + +ECOS: + $(MAKE) -C os/ecos/ MODE=$(RT28xx_MODE) + cp -f os/ecos/$(MODULE) $(MODULE) + +THREADX: + $(MAKE) -C $(RT28xx_DIR)/os/Threadx -f $(RT28xx_DIR)/os/ThreadX/Makefile + +LINUX: +ifneq (,$(findstring 2.4,$(LINUX_SRC))) + +ifeq ($(OSABL),YES) + cp -f os/linux/Makefile.4.util $(RT28xx_DIR)/os/linux/Makefile + $(MAKE) -C $(RT28xx_DIR)/os/linux/ +endif + + cp -f os/linux/Makefile.4 $(RT28xx_DIR)/os/linux/Makefile + $(MAKE) -C $(RT28xx_DIR)/os/linux/ + +ifeq ($(OSABL),YES) + cp -f os/linux/Makefile.4.netif $(RT28xx_DIR)/os/linux/Makefile + $(MAKE) -C $(RT28xx_DIR)/os/linux/ +endif + +ifeq ($(RT28xx_MODE),AP) + cp -f $(RT28xx_DIR)/os/linux/rt$(MODULE)ap.o /tftpboot +ifeq ($(OSABL),YES) + cp -f $(RT28xx_DIR)/os/linux/rtutil$(MODULE)ap.o /tftpboot + cp -f $(RT28xx_DIR)/os/linux/rtnet$(MODULE)ap.o /tftpboot +endif +ifeq ($(PLATFORM),INF_AMAZON_SE) + cp -f /tftpboot/rt2870ap.o /backup/ifx/build/root_filesystem/lib/modules/2.4.31-Amazon_SE-3.6.2.2-R0416_Ralink/kernel/drivers/net +endif +else +ifeq ($(RT28xx_MODE),APSTA) + cp -f $(RT28xx_DIR)/os/linux/rt$(MODULE)apsta.o /tftpboot +ifeq ($(OSABL),YES) + cp -f $(RT28xx_DIR)/os/linux/rtutil$(MODULE)apsta.o /tftpboot + cp -f $(RT28xx_DIR)/os/linux/rtnet$(MODULE)apsta.o /tftpboot +endif +else + cp -f $(RT28xx_DIR)/os/linux/rt$(MODULE)sta.o /tftpboot +ifeq ($(OSABL),YES) + cp -f $(RT28xx_DIR)/os/linux/rtutil$(MODULE)sta.o /tftpboot + cp -f $(RT28xx_DIR)/os/linux/rtnet$(MODULE)sta.o /tftpboot +endif +endif +endif +else + +ifeq ($(OSABL),YES) + cp -f os/linux/Makefile.6.util $(RT28xx_DIR)/os/linux/Makefile + $(MAKE) -C $(LINUX_SRC) SUBDIRS=$(RT28xx_DIR)/os/linux modules +endif + + cp -f os/linux/Makefile.6 $(RT28xx_DIR)/os/linux/Makefile +ifeq ($(PLATFORM),DM6446) + $(MAKE) ARCH=arm CROSS_COMPILE=arm_v5t_le- -C $(LINUX_SRC) SUBDIRS=$(RT28xx_DIR)/os/linux modules +else +ifeq ($(PLATFORM),FREESCALE8377) + $(MAKE) ARCH=powerpc CROSS_COMPILE=$(CROSS_COMPILE) -C $(LINUX_SRC) SUBDIRS=$(RT28xx_DIR)/os/linux modules +else + $(MAKE) -C $(LINUX_SRC) SUBDIRS=$(RT28xx_DIR)/os/linux modules +endif +endif + +ifeq ($(OSABL),YES) + cp -f os/linux/Makefile.6.netif $(RT28xx_DIR)/os/linux/Makefile + $(MAKE) -C $(LINUX_SRC) SUBDIRS=$(RT28xx_DIR)/os/linux modules +endif + +ifeq ($(RT28xx_MODE),AP) + cp -f $(RT28xx_DIR)/os/linux/rt$(MODULE)ap.ko /tftpboot +ifeq ($(OSABL),YES) + cp -f $(RT28xx_DIR)/os/linux/rtutil$(MODULE)ap.ko /tftpboot + cp -f $(RT28xx_DIR)/os/linux/rtnet$(MODULE)ap.ko /tftpboot +endif + rm -f os/linux/rt$(MODULE)ap.ko.lzma + /root/bin/lzma e os/linux/rt$(MODULE)ap.ko os/linux/rt$(MODULE)ap.ko.lzma +else +ifeq ($(RT28xx_MODE),APSTA) + cp -f $(RT28xx_DIR)/os/linux/rt$(MODULE)apsta.ko /tftpboot +ifeq ($(OSABL),YES) + cp -f $(RT28xx_DIR)/os/linux/rtutil$(MODULE)apsta.ko /tftpboot + cp -f $(RT28xx_DIR)/os/linux/rtnet$(MODULE)apsta.ko /tftpboot +endif +else + cp -f $(RT28xx_DIR)/os/linux/rt$(MODULE)sta.ko /tftpboot +ifeq ($(OSABL),YES) + cp -f $(RT28xx_DIR)/os/linux/rtutil$(MODULE)sta.ko /tftpboot + cp -f $(RT28xx_DIR)/os/linux/rtnet$(MODULE)sta.ko /tftpboot +endif +endif +endif +endif + + +release: build_tools + $(MAKE) -C $(RT28xx_DIR)/striptool -f Makefile.release clean + $(MAKE) -C $(RT28xx_DIR)/striptool -f Makefile.release + striptool/striptool.out +ifeq ($(RELEASE), DPO) + gcc -o striptool/banner striptool/banner.c + ./striptool/banner -b striptool/copyright.gpl -s DPO/ -d DPO_GPL -R + ./striptool/banner -b striptool/copyright.frm -s DPO_GPL/include/firmware.h +endif + +prerelease: +ifeq ($(MODULE), 2880) + $(MAKE) -C $(RT28xx_DIR)/os/linux -f Makefile.release.2880 prerelease +else + $(MAKE) -C $(RT28xx_DIR)/os/linux -f Makefile.release prerelease +endif + cp $(RT28xx_DIR)/os/linux/Makefile.DPB $(RTMP_SRC_DIR)/os/linux/. + cp $(RT28xx_DIR)/os/linux/Makefile.DPA $(RTMP_SRC_DIR)/os/linux/. + cp $(RT28xx_DIR)/os/linux/Makefile.DPC $(RTMP_SRC_DIR)/os/linux/. +ifeq ($(RT28xx_MODE),STA) + cp $(RT28xx_DIR)/os/linux/Makefile.DPD $(RTMP_SRC_DIR)/os/linux/. + cp $(RT28xx_DIR)/os/linux/Makefile.DPO $(RTMP_SRC_DIR)/os/linux/. +endif + +clean: +ifeq ($(TARGET), LINUX) + cp -f os/linux/Makefile.clean os/linux/Makefile + $(MAKE) -C os/linux clean + rm -rf os/linux/Makefile +endif +ifeq ($(TARGET), UCOS) + $(MAKE) -C os/ucos clean MODE=$(RT28xx_MODE) +endif +ifeq ($(TARGET), ECOS) + $(MAKE) -C os/ecos clean MODE=$(RT28xx_MODE) +endif + +uninstall: +ifeq ($(TARGET), LINUX) +ifneq (,$(findstring 2.4,$(LINUX_SRC))) + $(MAKE) -C $(RT28xx_DIR)/os/linux -f Makefile.4 uninstall +else + $(MAKE) -C $(RT28xx_DIR)/os/linux -f Makefile.6 uninstall +endif +endif + +install: +ifeq ($(TARGET), LINUX) +ifneq (,$(findstring 2.4,$(LINUX_SRC))) + $(MAKE) -C $(RT28xx_DIR)/os/linux -f Makefile.4 install +else + $(MAKE) -C $(RT28xx_DIR)/os/linux -f Makefile.6 install +endif +endif + +libwapi: +ifneq (,$(findstring 2.4,$(LINUX_SRC))) + cp -f os/linux/Makefile.libwapi.4 $(RT28xx_DIR)/os/linux/Makefile + $(MAKE) -C $(RT28xx_DIR)/os/linux/ +else + cp -f os/linux/Makefile.libwapi.6 $(RT28xx_DIR)/os/linux/Makefile + $(MAKE) -C $(LINUX_SRC) SUBDIRS=$(RT28xx_DIR)/os/linux modules +endif + +osutil: +ifeq ($(OSABL),YES) +ifneq (,$(findstring 2.4,$(LINUX_SRC))) + cp -f os/linux/Makefile.4.util $(RT28xx_DIR)/os/linux/Makefile + $(MAKE) -C $(RT28xx_DIR)/os/linux/ +else + cp -f os/linux/Makefile.6.util $(RT28xx_DIR)/os/linux/Makefile + $(MAKE) -C $(LINUX_SRC) SUBDIRS=$(RT28xx_DIR)/os/linux modules +endif +endif + +osnet: +ifeq ($(OSABL),YES) +ifneq (,$(findstring 2.4,$(LINUX_SRC))) + cp -f os/linux/Makefile.4.netif $(RT28xx_DIR)/os/linux/Makefile + $(MAKE) -C $(RT28xx_DIR)/os/linux/ +else + cp -f os/linux/Makefile.6.netif $(RT28xx_DIR)/os/linux/Makefile + $(MAKE) -C $(LINUX_SRC) SUBDIRS=$(RT28xx_DIR)/os/linux modules +endif +endif + +osdrv: +ifneq (,$(findstring 2.4,$(LINUX_SRC))) + cp -f os/linux/Makefile.4 $(RT28xx_DIR)/os/linux/Makefile + $(MAKE) -C $(RT28xx_DIR)/os/linux/ +else + cp -f os/linux/Makefile.6 $(RT28xx_DIR)/os/linux/Makefile + $(MAKE) -C $(LINUX_SRC) SUBDIRS=$(RT28xx_DIR)/os/linux modules +endif + +# Declare the contents of the .PHONY variable as phony. We keep that information in a variable +.PHONY: $(PHONY) + + + diff --git a/mt7620/src/Makefile.OSABL b/mt7620/src/Makefile.OSABL new file mode 100755 index 0000000..90f9b98 --- /dev/null +++ b/mt7620/src/Makefile.OSABL @@ -0,0 +1,23 @@ + +all: + make -C UTIL/ osutil + $(SHELL) cp_util.sh + make -C MODULE/ build_tools + make -C MODULE/ osdrv + $(SHELL) cp_module.sh + make -C NETIF/ osnet + +clean: + make -C UTIL/ clean + make -C MODULE/ clean + make -C NETIF/ clean + +install: + make -C UTIL/ install + make -C MODULE/ install + make -C NETIF/ install + +uninstall: + make -C UTIL/ uninstall + make -C MODULE/ uninstall + make -C NETIF/ uninstall diff --git a/mt7620/src/README b/mt7620/src/README new file mode 100755 index 0000000..55eab64 --- /dev/null +++ b/mt7620/src/README @@ -0,0 +1,68 @@ +How to make? +1. If you want to buid the Linux AP code, set the "MODE = AP" in Makefile + and chose the TARGET to Linux by set "TARGET = LINUX" + +2. If you want to build the Linux STA code, set the "MODE = STA" in Makefile + and chose the TARGET to Linux by set "TARGET = LINUX" + +3. If you want to buid the uCOS AP code, set the "MODE = AP" in Makefile + and chose the TARGET to UCOS by set "TARGET = UCOS" + +4. If you want to build the uCOS STA code, set the "MODE = STA" in Makefile + and chose the TARGET to uCOS by set "TARGET = UCOS" + +5. If you wnat to clean the tree, just "make clean" it will clean the target and mode you set + +6. In os/linux/config.mk + define the GCC and LD of the target machine + define the compiler flags CFLAGS + define the linux kernel source include file path LINUX_SRC + modify to meet your need. + +7. For the Linux port , please read /include/rt_linux.h os/linux/rt_linux.c and os/linux/rt_main_dev.c + +8. For the uCOS port , please read /include/rt_ucos.h os/linux/rt_ucos.c and os/ucos/rt_main_dev.c + +9. For the Linux Station port, please add the Makefile section in os/linux/Makefile. + +10. Currently you can build and run on your 2.4.x Linux kernel, 2.6.x not sure and not try yet. + +11. In tools/bin2h.c will convert the 8051 firmware from common/rt2860.bin into include/firmware.h. + Which will be used by rtmp_init.c to include in the firmware image in an array. + + +Branch:B20070129 + +Support: + 1. Support MBSS + 2. Support LoadFirmware + 3. Access BBP by way of 8051 Firmware + 4. Temperature conpensation for Tx Power + 5. Using Management ring by Mac Version + 6. BBP setting by Mac Version + +Branch: B20070202 +Support: + 1. Add Ralink proprietary Aggregation/PiggyBack support + 2. Modify some Big-Endian swap code for Action frame + 3. Add WDS support + 4. Remove unused variables and modify wrong statments to reduce compiler warning msg. + 5. Add STA encryption/decryption code by Albert + +Branch: B20070209 +Support: + 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] + +Branch: not define yet +Support: + 1. merge code from Plugfest #6 + 2. add "iwpriv ra0 show driverinfo" to show the driver version + 3. fix rt_config.h tag of Support station with tab + 4. merge ATE code request by Gemtek diff --git a/mt7620/src/README_STA_pci b/mt7620/src/README_STA_pci new file mode 100755 index 0000000..fc8020d --- /dev/null +++ b/mt7620/src/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/mt7620/src/README_STA_usb b/mt7620/src/README_STA_usb new file mode 100755 index 0000000..9d15d69 --- /dev/null +++ b/mt7620/src/README_STA_usb @@ -0,0 +1,534 @@ +* README +* +* Ralink Tech Inc. +* +* http://www.ralinktech.com +* + +======================================================================= +ModelName: +=========== +RT2870 Wireless Lan Linux Driver + + +======================================================================= +Driver lName: +=========== +rt2870.o/rt2870.ko + + +======================================================================= +Supporting Kernel: +=================== +linux kernel 2.4 and 2.6 series. +Tested in Redhat 7.3 or later. + + +======================================================================= +Ralink Hardware: +=================== +Ralink 802.11n Wireless LAN Card. + + +======================================================================= +Description: +============= +This is a linux device driver for Ralink RT2870 USB 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_RT2870_Linux_STA_x.x.x.x.tgz + go to "./DPB_RT2870_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 RT2870STA.dat /etc/Wireless/RT2870STA/RT2870STA.dat + +6> load driver, go to "os/linux/" directory. + #[kernel 2.4] + # $/sbin/insmod rt2870sta.o + # $/sbin/ifconfig ra0 inet YOUR_IP up + + #[kernel 2.6] + # $/sbin/insmod rt2870sta.ko + # $/sbin/ifconfig ra0 inet YOUR_IP up + +7> unload driver + $/sbin/ifconfig ra0 down + $/sbin/rmmod rt2870sta + +======================================================================= +CONFIGURATION: +==================== +RT2870 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 "RT2870STA.dat" in /etc/Wireless/RT2870STA/RT2870STA.dat. + +Configuration File : RT2870STA.dat +--------------------------------------- +# Copy this file to /etc/Wireless/RT2870STA/RT2870STA.dat +# This file is a binary file and will be read on loading rt.o module. +# +# Use "vi RT2870STA.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 RT2870STA.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 rt2870 driver to auto-load at boot time: +A) choose ra0 for first RT2870 WLAN card, ra1 for second RT2870 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 rt2870sta + +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/mt7620/src/RT2860AP.dat b/mt7620/src/RT2860AP.dat new file mode 100755 index 0000000..de55f7a --- /dev/null +++ b/mt7620/src/RT2860AP.dat @@ -0,0 +1,136 @@ +#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_MCS=33 +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 diff --git a/mt7620/src/RT2860APCard.dat b/mt7620/src/RT2860APCard.dat new file mode 100755 index 0000000..4532b4b --- /dev/null +++ b/mt7620/src/RT2860APCard.dat @@ -0,0 +1,19 @@ +#The word of "Default" must not be removed, maximum 32 cards, 00 ~ 31 +Default + +#CARDID, MAC, CARDTYPE +SELECT=CARDTYPE + +00CARDID=/etc/Wireless/RT2860AP/RT2860AP1.dat +01CARDID=/etc/Wireless/RT2860AP/RT2860AP2.dat +02CARDID=/etc/Wireless/RT2860AP/RT2860AP3.dat + +00MAC00:0E:2E:C3:D0:48=/etc/Wireless/RT2860AP/RT2860AP1.dat +01MAC00:40:F4:FF:AA:40=/etc/Wireless/RT2860AP/RT2860AP2.dat +02MAC00:0C:43:10:11:5C=/etc/Wireless/RT2860AP/RT2860AP3.dat + +00CARDTYPEbgn=/etc/Wireless/RT2860AP/RT2860AP1.dat +01CARDTYPEbgn=/etc/Wireless/RT2860AP/RT2860AP2.dat +02CARDTYPEabgn=/etc/Wireless/RT2860AP/RT2860AP3.dat + + diff --git a/mt7620/src/RT2860STA.dat b/mt7620/src/RT2860STA.dat new file mode 100755 index 0000000..7d9cada --- /dev/null +++ b/mt7620/src/RT2860STA.dat @@ -0,0 +1,86 @@ +#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_STBC=0 +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 \ No newline at end of file diff --git a/mt7620/src/RT2860STACard.dat b/mt7620/src/RT2860STACard.dat new file mode 100755 index 0000000..c3f9d74 --- /dev/null +++ b/mt7620/src/RT2860STACard.dat @@ -0,0 +1,19 @@ +#The word of "Default" must not be removed, maximum 32 cards, 00 ~ 31 +Default + +#CARDID, MAC, CARDTYPE +SELECT=CARDTYPE + +00CARDID=/etc/Wireless/RT2860STA/RT2860STA1.dat +01CARDID=/etc/Wireless/RT2860STA/RT2860STA2.dat +02CARDID=/etc/Wireless/RT2860STA/RT2860STA3.dat + +00MAC00:0E:2E:C3:D0:48=/etc/Wireless/RT2860STA/RT2860STA1.dat +01MAC00:40:F4:FF:AA:40=/etc/Wireless/RT2860STA/RT2860STA2.dat +02MAC00:0C:43:10:11:5C=/etc/Wireless/RT2860STA/RT2860STA3.dat + +00CARDTYPEbgn=/etc/Wireless/RT2860STA/RT2860STA1.dat +01CARDTYPEbgn=/etc/Wireless/RT2860STA/RT2860STA2.dat +02CARDTYPEabgn=/etc/Wireless/RT2860STA/RT2860STA3.dat + + diff --git a/mt7620/src/RT2860card.readme b/mt7620/src/RT2860card.readme new file mode 100755 index 0000000..b774bb7 --- /dev/null +++ b/mt7620/src/RT2860card.readme @@ -0,0 +1,84 @@ +KeyWord: + RT28xxCard.dat means RT2860APcard.dat or RT2870APcard.dat or RT2860STAcard.dat or RT2870STAcard.dat + + +Introduction: + We provide three usages in RT28xxCard.dat, CARDTYPE, CARDID, or MAC + + <<<<<<<<<< CARDTYPE >>>>>>>>>> + The only thing you need to know is that you have "how many 11ABGN cards and how many 11BGN cards". + + If you have 3 USB/PCMCIA cards, we name them: card00 (bgn), card01 (abgn), card02 (abgn). + So we can write their profile path in RT28xxCard.dat as below: + + 00CARDTYPEbgn=/etc/Wireless/RT2860AP/RT2860AP0.dat + 01CARDTYPEabgn=/etc/Wireless/RT2860AP/RT2860AP1.dat + 02CARDTYPEabgn=/etc/Wireless/RT2860AP/RT2860AP2.dat + + (1) After you plug-in the card01, it will find RT2860AP1.dat; + After you plug-in the card00, it will find RT2860AP0.dat; + After you plug-in the card02, it will find RT2860AP2.dat; + + Then you plug-out card01 and card02. + Then you plug-in card02, card02 will find RT2860AP2.dat because it has ever pluged-in before. + + (2) If no any card is pluged in before, then you plug-in card02, card02 will find RT2860AP1.dat. + + If it can not find its CARDTYPE in RT28xxCard.dat, it will use default path (/etc/Wireless/RT2860AP/RT2860AP.dat or + /etc/Wireless/RT2870AP/RT2870AP.dat or /etc/Wireless/RT2860AP/RT2860STA.dat or /etc/Wireless/RT2860AP/RT2870STA.dat) + + Note: The CARDTYPE is NOT the WirelessMode of the DATA file. CARDTYPE means the RF type, ABGN or BGN. EX: if you have a RALINK card with 11abgn, but you want to use 11bg only, you need to assign CARDTYPE to CARDTYPEabgn, not CARDTYPEbg. And you need to assign WirelessMode to 0 (bg mode) in your DAT file, i.e. CARDTYPE (hardware view) != WirelessMode (user view) + + + <<<<<<<<<< CARDID >>>>>>>>>> + The 1st plug-in card will match 1st profile except it is plug-in before when driver is not removed. + + If you have 3 USB/PCMCIA cards, we name them: card00 (bgn), card01 (abgn), card02 (abgn). + So we can write their profile path in RT28xxCard.dat as below: + + 00CARDID=/etc/Wireless/RT2860AP/RT2860AP0.dat + 01CARDID=/etc/Wireless/RT2860AP/RT2860AP1.dat + 02CARDID=/etc/Wireless/RT2860AP/RT2860AP2.dat + + (1) After you plug-in the card01, it will find RT2860AP0.dat; + After you plug-in the card00, it will find RT2860AP1.dat; + After you plug-in the card02, it will find RT2860AP2.dat; + + Then you plug-out card01 and card02. + Then you plug-in card02, card02 will be still find RT2860AP2.dat because it has ever pluged-in before. + + (2) If no any card is pluged in before, then you plug-in card02, card02 will find RT2860AP0.dat, not RT2860AP2.dat. + If you want to use RT2860AP2.dat profile for card02, you must swap row 00CARDID and row 02CARDID or + plug-in card00 and card01 before card02 is pluged-in. + + If CARDIDxx list are not enough, it will use default path (/etc/Wireless/RT2860AP/RT2860AP.dat or + /etc/Wireless/RT2870AP/RT2870AP.dat or /etc/Wireless/RT2860AP/RT2860STA.dat or /etc/Wireless/RT2860AP/RT2870STA.dat) + + + <<<<<<<<<< MAC >>>>>>>>>> + Every card will find its MAC address and get its profile path. (1 vs. 1 absolute mapping) + + 00MAC00:01:02:03:04:05=/etc/Wireless/RT2860AP/RT2860AP0.dat + 01MAC00:01:02:03:04:06=/etc/Wireless/RT2860AP/RT2860AP1.dat + 02MAC00:01:02:03:04:07=/etc/Wireless/RT2860AP/RT2860AP2.dat + + If it can not find its MAC address, it will use default path (/etc/Wireless/RT2860AP/RT2860AP.dat or + /etc/Wireless/RT2870AP/RT2870AP.dat or /etc/Wireless/RT2860AP/RT2860STA.dat or /etc/Wireless/RT2860AP/RT2870STA.dat) + + + +Note: + 1. When you have more than 1 RT2860 or RT2870 cards, you need to use RT28xxCard.dat + to determine which profile is used by which card. + + 2. The first item in RT28xxCard.dat must be from 00CARDID, 00MAC, 00CARDTYPE, not 01CARDID, 01MAC, 01CARDTYPE + 3. You can not modify RT28xxCard.dat when you yet remove RT28xx module. + + 4. Multiple RT2860 cards configured as AP use "/etc/Wireless/RT2860AP/RT2860APCard.dat" + 5. Multiple RT2860 cards configured as STA use "/etc/Wireless/RT2860AP/RT2860STACard.dat" + 6. Multiple RT2870 cards configured as AP use "/etc/Wireless/RT2860AP/RT2870APCard.dat" + 7. Multiple RT2870 cards configured as STA use "/etc/Wireless/RT2860AP/RT2870STACard.dat" + + 8. Ex: When you have 2 RT2860 cards and 2 RT2870 cards, you need two + RT28xxCard.dat for RT2860 and RT2870. + Same RT28xxCard.dat can not be shared for AP and STATION or RT2860 and RT2870. diff --git a/mt7620/src/RT2870AP.dat b/mt7620/src/RT2870AP.dat new file mode 100755 index 0000000..c5f4951 --- /dev/null +++ b/mt7620/src/RT2870AP.dat @@ -0,0 +1,119 @@ +#The word of "Default" must not be removed +Default +CountryRegion=5 +CountryRegionABand=7 +CountryCode=TW +BssidNum=1 +SSID=RT2860AP +WirelessMode=9 +TxRate=0 +Channel=11 +BasicRate=15 +BeaconPeriod=100 +DtimPeriod=1 +TxPower=100 +DisableOLBC=0 +BGProtection=0 +TxAntenna= +RxAntenna= +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 +WPAPSK= +DefaultKeyID=1 +Key1Type=0 +Key1Str= +Key2Type=0 +Key2Str= +Key3Type=0 +Key3Str= +Key4Type=0 +Key4Str= +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 +PMFMFPC=0 +PMFMFPR=0 +PMFSHA256=0 \ No newline at end of file diff --git a/mt7620/src/RT2870APCard.dat b/mt7620/src/RT2870APCard.dat new file mode 100755 index 0000000..3d1a1a8 --- /dev/null +++ b/mt7620/src/RT2870APCard.dat @@ -0,0 +1,19 @@ +#The word of "Default" must not be removed, maximum 32 cards, 00 ~ 31 +Default + +#CARDID, MAC, CARDTYPE +SELECT=CARDTYPE + +00CARDID=/etc/Wireless/RT2870AP/RT2870AP1.dat +01CARDID=/etc/Wireless/RT2870AP/RT2870AP2.dat +02CARDID=/etc/Wireless/RT2870AP/RT2870AP3.dat + +00MAC00:0E:2E:C3:D0:48=/etc/Wireless/RT2870AP/RT2870AP1.dat +01MAC00:40:F4:FF:AA:40=/etc/Wireless/RT2870AP/RT2870AP2.dat +02MAC00:0C:43:10:11:5C=/etc/Wireless/RT2870AP/RT2870AP3.dat + +00CARDTYPEbgn=/etc/Wireless/RT2870AP/RT2870AP1.dat +01CARDTYPEbgn=/etc/Wireless/RT2870AP/RT2870AP2.dat +02CARDTYPEabgn=/etc/Wireless/RT2870AP/RT2870AP3.dat + + diff --git a/mt7620/src/RT2870STA.dat b/mt7620/src/RT2870STA.dat new file mode 100755 index 0000000..eacddc8 --- /dev/null +++ b/mt7620/src/RT2870STA.dat @@ -0,0 +1,86 @@ +#The word of "Default" must not be removed +Default +CountryRegion=5 +CountryRegionABand=7 +CountryCode= +ChannelGeography=1 +SSID=11n-AP +NetworkType=Infra +WirelessMode=5 +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_BADecline=0 +HT_AutoBA=1 +HT_AMSDU=0 +HT_BAWinSize=64 +HT_GI=1 +HT_MCS=33 +HT_MIMOPSMode=3 +HT_DisallowTKIP=1 +HT_STBC=0 +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 \ No newline at end of file diff --git a/mt7620/src/RT2870STACard.dat b/mt7620/src/RT2870STACard.dat new file mode 100755 index 0000000..1df6a49 --- /dev/null +++ b/mt7620/src/RT2870STACard.dat @@ -0,0 +1,19 @@ +#The word of "Default" must not be removed, maximum 32 cards, 00 ~ 31 +Default + +#CARDID, MAC, CARDTYPE +SELECT=CARDTYPE + +00CARDID=/etc/Wireless/RT2870STA/RT2870STA1.dat +01CARDID=/etc/Wireless/RT2870STA/RT2870STA2.dat +02CARDID=/etc/Wireless/RT2870STA/RT2870STA3.dat + +00MAC00:0E:2E:C3:D0:48=/etc/Wireless/RT2870STA/RT2870STA1.dat +01MAC00:40:F4:FF:AA:40=/etc/Wireless/RT2870STA/RT2870STA2.dat +02MAC00:0C:43:10:11:5C=/etc/Wireless/RT2870STA/RT2870STA3.dat + +00CARDTYPEbgn=/etc/Wireless/RT2870STA/RT2870STA1.dat +01CARDTYPEbgn=/etc/Wireless/RT2870STA/RT2870STA2.dat +02CARDTYPEabgn=/etc/Wireless/RT2870STA/RT2870STA3.dat + + diff --git a/mt7620/src/RT_WIFI_Revision_History_2010_April.xls b/mt7620/src/RT_WIFI_Revision_History_2010_April.xls new file mode 100755 index 0000000..53c6da4 Binary files /dev/null and b/mt7620/src/RT_WIFI_Revision_History_2010_April.xls differ diff --git a/mt7620/src/VxWorks.README b/mt7620/src/VxWorks.README new file mode 100755 index 0000000..33b3621 --- /dev/null +++ b/mt7620/src/VxWorks.README @@ -0,0 +1,4 @@ + +ADDED_CFLAGS = -DVXWORKS -DCONFIG_AP_SUPPORT -DRT2860 -DRT2880 -DCONFIG_RALINK_RT2880_MP -DUAPSD_AP_SUPPORT -DMBSS_SUPPORT -DIAPP_SUPPORT -DDBG -DAPCLI_SUPPORT -DMLME_EX -DMAT_SUPPORT -DWDS_SUPPORT -DIGMP_SNOOP_SUPPORT -DMCAST_RATE_SPECIFIC -DQOS_DLS_SUPPORT -DIDS_SUPPORT -DMESH_SUPPORT -DWSC_AP_SUPPORT -DBLOCK_NET_IF + + diff --git a/mt7620/src/ap/ap.c b/mt7620/src/ap/ap.c new file mode 100644 index 0000000..6c26a74 --- /dev/null +++ b/mt7620/src/ap/ap.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: + 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"}; + +/* + ========================================================================== + Description: + Initialize AP specific data especially the NDIS packet pool that's + used for wireless client bridging. + ========================================================================== + */ +NDIS_STATUS APInitialize( + IN PRTMP_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 + APWdsInitialize(pAd); +#endif /* WDS_SUPPORT */ + +#ifdef IGMP_SNOOP_SUPPORT + MulticastFilterTableInit(pAd, &pAd->pMulticastFilterTable); +#endif /* IGMP_SNOOP_SUPPORT */ + + +#ifdef WDS_SUPPORT + NdisAllocateSpinLock(pAd, &pAd->WdsTabLock); +#endif /* WDS_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("<--- APInitialize\n")); + return Status; +} + +/* + ========================================================================== + Description: + Shutdown AP and free AP specific resources + ========================================================================== + */ +VOID APShutdown( + IN PRTMP_ADAPTER pAd) +{ + DBGPRINT(RT_DEBUG_TRACE, ("---> APShutdown\n")); +/* if (pAd->OpMode == OPMODE_AP) */ +#ifdef RTMP_MAC_PCI + APStop(pAd); +#endif /* RTMP_MAC_PCI */ + + MlmeRadioOff(pAd); + +#ifdef IGMP_SNOOP_SUPPORT + MultiCastFilterTableReset(&pAd->pMulticastFilterTable); +#endif /* IGMP_SNOOP_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( + IN PRTMP_ADAPTER pAd) +{ + ULONG offset, i; + UINT32 Value = 0; + BOOLEAN bWmmCapable = FALSE; + UCHAR apidx; + BOOLEAN TxPreamble, SpectrumMgmt = FALSE; + UCHAR BBPR1 = 0, BBPR3 = 0; /*byteValue = 0; */ + UCHAR phy_mode = pAd->CommonCfg.DesiredPhyMode; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; +#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 (apidx=0; apidxApCfg.BssidNum; apidx++) + { + PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[apidx]; + + if ((pMbss->SsidLen <= 0) || (pMbss->SsidLen > MAX_LEN_OF_SSID)) + { + NdisMoveMemory(pMbss->Ssid, "HT_AP", 5); + pMbss->Ssid[5] = '0'+apidx; + pMbss->SsidLen = 6; + } + + /* 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(pMbss->Bssid, 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; +#ifdef SPECIFIC_BCN_BUF_SUPPORT + else if ((pAd->ApCfg.BssidNum + MAX_APCLI_NUM + MAX_MESH_NUM) <= 16) + MacMask = 0xF0; +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ + + if (apidx > 0) + { + 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. + */ +#ifdef ENHANCE_NEW_MBSSID_MODE + pMbss->Bssid[0] &= (MacMask << 2); +#endif /* ENHANCE_NEW_MBSSID_MODE */ + pMbss->Bssid[0] |= 0x2; + pMbss->Bssid[0] += ((apidx - 1) << 2); + } +#ifdef ENHANCE_NEW_MBSSID_MODE + else + { + pMbss->Bssid[0] |= 0x2; + pMbss->Bssid[pAd->chipCap.MBSSIDMode - 1] &= (MacMask); + pMbss->Bssid[pAd->chipCap.MBSSIDMode - 1] += (apidx - 1); + } +#endif /* ENHANCE_NEW_MBSSID_MODE */ + } + } + else + pMbss->Bssid[5] += apidx; + + if (pMbss->MSSIDDev != NULL) + { + NdisMoveMemory(RTMP_OS_NETDEV_GET_PHYADDR(pMbss->MSSIDDev), + pMbss->Bssid, + MAC_ADDR_LEN); + } + + if (pMbss->bWmmCapable) + { + bWmmCapable = TRUE; + } + + pMbss->CapabilityInfo = + CAP_GENERATE(1, 0, (pMbss->WepStatus != Ndis802_11EncryptionDisabled), TxPreamble, pAd->CommonCfg.bUseShortSlotTime, SpectrumMgmt); + + + 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; */ + } /* End of if */ + +#ifdef UAPSD_SUPPORT +/* if (pAd->CommonCfg.bAPSDCapable == TRUE) */ + 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; + } /* End of if */ +#endif /* UAPSD_SUPPORT */ + + + /* decide the mixed WPA cipher combination */ + if (pMbss->WepStatus == Ndis802_11Encryption4Enabled) + { + switch ((UCHAR)pMbss->AuthMode) + { + /* WPA mode */ + case Ndis802_11AuthModeWPA: + case Ndis802_11AuthModeWPAPSK: + pMbss->WpaMixPairCipher = WPA_TKIPAES_WPA2_NONE; + break; + + /* WPA2 mode */ + case Ndis802_11AuthModeWPA2: + case Ndis802_11AuthModeWPA2PSK: + pMbss->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 (pMbss->WpaMixPairCipher == MIX_CIPHER_NOTUSE || + pMbss->WpaMixPairCipher == WPA_TKIPAES_WPA2_NONE || + pMbss->WpaMixPairCipher == WPA_NONE_WPA2_TKIPAES) + pMbss->WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIPAES; + break; + } + + } + else + pMbss->WpaMixPairCipher = MIX_CIPHER_NOTUSE; + + /* Generate the corresponding RSNIE */ + RTMPMakeRSNIE(pAd, pMbss->AuthMode, pMbss->WepStatus, apidx); + +#ifdef WSC_V2_SUPPORT + if (pMbss->WscControl.WscV2Info.bEnableWpsV2) + { + /* + WPS V2 doesn't support WEP and WPA/WPAPSK-TKIP. + */ + if ((pMbss->WepStatus == Ndis802_11WEPEnabled) || + (pMbss->WepStatus == Ndis802_11Encryption2Enabled) || + (pMbss->bHideSsid)) + WscOnOff(pAd, apidx, TRUE); + else + WscOnOff(pAd, apidx, FALSE); + } +#endif /* WSC_V2_SUPPORT */ +#ifdef BAND_STEERING + if (pAd->ApCfg.BandSteering && apidx == 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. */ +#if defined(RT2883) || defined(RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + { + /* reset Tx beamforming bit */ + /* TODO: add bbpr1 tunning for eeprom value. */ + } + else +#endif /* defined(RT2883) || defined(RT3883) */ + { +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->Antenna.field.TxPath == 2)) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1); + BBPR1 &= (~0x18); + BBPR1 |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1); + } + else +#endif /* DOT11_N_SUPPORT */ + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1); + BBPR1 &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1); + } + } + + /* Receiver Antenna selection, write to BBP R3(bit4:3) */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); + BBPR3 &= (~0x18); + if(pAd->Antenna.field.RxPath == 3) + { + BBPR3 |= (0x10); + } + else if(pAd->Antenna.field.RxPath == 2) + { + BBPR3 |= (0x8); + } + else if(pAd->Antenna.field.RxPath == 1) + { + BBPR3 |= (0x0); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); + + if ((pAd->CommonCfg.PhyMode > PHY_11G) || bWmmCapable) + { + /* EDCA parameters used for AP's own transmission */ + 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] = 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; /*96; */ + pAd->CommonCfg.APEdcaParm.Txop[3] = 47; /*48; */ + } + AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); + + /* EDCA parameters to be annouced in outgoing BEACON, used by WMM STA */ + if (pAd->ApCfg.BssEdcaParm.bValid == FALSE) + { + 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; */ + } + } + else + AsicSetEdcaParm(pAd, NULL); + +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED) + { + /* Patch UI */ + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = BW_20; + } + + /* init */ + if (pAd->CommonCfg.bRdg) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); + AsicEnableRDG(pAd); + } + else + { + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); + AsicDisableRDG(pAd); + } + + if (pAd->CommonCfg.bRalinkBurstMode) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE); + AsicEnableRalinkBurstMode(pAd); + } + else + { + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE); + AsicDisableRalinkBurstMode(pAd); + } +#endif /* DOT11_N_SUPPORT */ + + COPY_MAC_ADDR(pAd->ApCfg.MBSSID[BSS0].Bssid, pAd->CurrentAddress); + AsicSetBssid(pAd, pAd->CurrentAddress); + AsicSetMcastWC(pAd); + /* 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. */ + RTMP_IO_WRITE32(pAd, MAC_WCID_BASE, 0x00); + RTMP_IO_WRITE32(pAd, MAC_WCID_BASE+4, 0x0); + +#ifdef FIFO_EXT_SUPPORT + AsicFifoExtSet(pAd); +#endif /* FIFO_EXT_SUPPORT */ + + /* reset WCID table */ + for (i=1; i<255; i++) + { + offset = MAC_WCID_BASE + (i * HW_WCID_ENTRY_SIZE); + RTMP_IO_WRITE32(pAd, offset, 0x0); + RTMP_IO_WRITE32(pAd, offset+4, 0x0); + } + + 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); + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + +#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 (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + MlmeUpdateTxRates(pAd, FALSE, apidx); +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.PhyMode > PHY_11G) + MlmeUpdateHtTxRates(pAd, apidx); +#endif /* DOT11_N_SUPPORT */ + } + + /* Set the RadarDetect Mode as Normal, bc the APUpdateAllBeaconFram() will refer this parameter. */ + pAd->Dot11_H.RDMode = RD_NORMAL_MODE; + + + /* 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 */ + + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn == TRUE) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + /* Initialize security variable per entry, + 1. pairwise key table, re-set all WCID entry as NO-security mode. + 2. access control port status + */ + for (i=0; iMacTab.Content[i].PortSecured = WPA_802_1X_PORT_NOT_SECURED; + AsicRemovePairwiseKeyEntry(pAd, (UCHAR)i); + } + + /* Init Security variables */ + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + USHORT Wcid = 0; + PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[apidx]; + + pMbss->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + if (IS_WPA_CAPABILITY(pMbss->AuthMode)) + { + pMbss->DefaultKeyId = 1; + } + + /* Get a specific WCID to record this MBSS key attribute */ + GET_GroupKey_WCID(pAd, Wcid, apidx); + + /* When WEP, TKIP or AES is enabled, set group key info to Asic */ + if (pMbss->WepStatus == Ndis802_11WEPEnabled) + { + UCHAR CipherAlg; + UCHAR idx; + + for (idx=0; idx < SHARE_KEY_NUM; idx++) + { + CipherAlg = pAd->SharedKey[apidx][idx].CipherAlg; + + if (pAd->SharedKey[apidx][idx].KeyLen > 0) + { + /* Set key material to Asic */ + RTMP_ASIC_SHARED_KEY_TABLE(pAd, + apidx, + idx, + &pAd->SharedKey[apidx][idx]); + + if (idx == pMbss->DefaultKeyId) + { + /* Generate 3-bytes IV randomly for software encryption using */ + for(i = 0; i < LEN_WEP_TSC; i++) + pAd->SharedKey[apidx][idx].TxTsc[i] = RandomByte(pAd); + + /* Update WCID attribute table and IVEIV table */ + RTMPSetWcidSecurityInfo(pAd, + apidx, + idx, + CipherAlg, + Wcid, + SHAREDKEYTABLE); + } + } + } + } + else if ((pMbss->WepStatus == Ndis802_11Encryption2Enabled) || + (pMbss->WepStatus == Ndis802_11Encryption3Enabled) || + (pMbss->WepStatus == Ndis802_11Encryption4Enabled)) + { + /* Generate GMK and GNonce randomly per MBSS */ + GenRandom(pAd, pMbss->Bssid, pMbss->GMK); + GenRandom(pAd, pMbss->Bssid, pMbss->GNonce); + + /* Derive GTK per BSSID */ + WpaDeriveGTK(pMbss->GMK, + (UCHAR*)pMbss->GNonce, + pMbss->Bssid, + pMbss->GTK, + LEN_TKIP_GTK); + + /* Install Shared key */ + WPAInstallSharedKey(pAd, + pMbss->GroupKeyWepStatus, + apidx, + pMbss->DefaultKeyId, + Wcid, + TRUE, + pMbss->GTK, + LEN_TKIP_GTK); + + } +#ifdef WAPI_SUPPORT + else if (pMbss->WepStatus == Ndis802_11EncryptionSMS4Enabled) + { + INT cnt; + + /* Initial the related variables */ + pMbss->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, + pMbss->GroupKeyWepStatus, + apidx, + pMbss->DefaultKeyId, + Wcid, + pMbss->GTK); + + } +#endif /* WAPI_SUPPORT */ + +#ifdef DOT1X_SUPPORT + /* Send singal to daemon to indicate driver had restarted */ + if ((pMbss->AuthMode == Ndis802_11AuthModeWPA) || (pMbss->AuthMode == Ndis802_11AuthModeWPA2) + || (pMbss->AuthMode == Ndis802_11AuthModeWPA1WPA2) || (pMbss->IEEE8021X == TRUE)) + { + ;/*bDot1xReload = TRUE; */ + } +#endif /* DOT1X_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("### BSS(%d) AuthMode(%d)=%s, WepStatus(%d)=%s , AccessControlList.Policy=%ld\n", apidx, pMbss->AuthMode, GetAuthMode(pMbss->AuthMode), + pMbss->WepStatus, GetEncryptType(pMbss->WepStatus), pMbss->AccessControlList.Policy)); + } + + + /* Disable Protection first. */ + /*AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT|CCKSETPROTECT|OFDMSETPROTECT), TRUE, FALSE); */ +#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); + +#ifdef NINTENDO_AP + InitNINTENDO_TABLE(pAd); +#endif /* NINTENDO_AP */ + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + + /* start sending BEACON out */ + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); + +#ifdef A_BAND_SUPPORT + 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; +#ifdef DFS_SUPPORT + NewRadarDetectionStart(pAd); +#endif /* DFS_SUPPORT */ + } + else +#endif /* A_BAND_SUPPORT */ + { + pAd->Dot11_H.RDMode = RD_NORMAL_MODE; + AsicEnableBssSync(pAd); + +#ifdef CONFIG_AP_SUPPORT +#ifdef CARRIER_DETECTION_SUPPORT +#ifdef A_BAND_SUPPORT + if (pAd->CommonCfg.Channel > 14) + { + if ((pAd->CommonCfg.CarrierDetect.Enable == FALSE) + && ((pAd->CommonCfg.RDDurRegion == JAP) + || (pAd->CommonCfg.RDDurRegion == JAP_W53) + || (pAd->CommonCfg.RDDurRegion == JAP_W56))) + { + pAd->CommonCfg.CarrierDetect.Enable = 1; + } + } + else +#endif /* A_BAND_SUPPORT */ + { + if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) + { + if ((pAd->CommonCfg.CarrierDetect.Enable == FALSE) + && ((pAd->CommonCfg.RDDurRegion == JAP) + || (pAd->CommonCfg.RDDurRegion == JAP_W53) + || (pAd->CommonCfg.RDDurRegion == JAP_W56))) + { + pAd->CommonCfg.CarrierDetect.Enable = TRUE; + } + } + } + + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + { + CarrierDetectionStart(pAd); + } +#endif /* CARRIER_DETECTION_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + } + + /* Pre-tbtt interrupt setting. */ + RTMP_IO_READ32(pAd, INT_TIMER_CFG, &Value); + Value &= 0xffff0000; + Value |= 6 << 4; /* Pre-TBTT is 6ms before TBTT interrupt. 1~10 ms is reasonable. */ + RTMP_IO_WRITE32(pAd, INT_TIMER_CFG, Value); + /* Enable pre-tbtt interrupt */ + RTMP_IO_READ32(pAd, INT_TIMER_EN, &Value); + Value |=0x1; + RTMP_IO_WRITE32(pAd, INT_TIMER_EN, Value); + +#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 MESH_SUPPORT + if (MESH_ON(pAd)) + MeshUp(pAd); +#endif /* MESH_SUPPORT */ + + + + 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 apidx; + + DBGPRINT(RT_DEBUG_TRACE, ("!!! APStop !!!\n")); + +#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 MESH_SUPPORT + if (MESH_ON(pAd)) + MeshDown(pAd, TRUE); +#endif /* MESH_SUPPORT */ + +#ifdef WDS_SUPPORT + WdsDown(pAd); +#endif /* WDS_SUPPORT */ + +#ifdef APCLI_SUPPORT + ApCliIfDown(pAd); +#endif /* APCLI_SUPPORT */ + + 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 */ + } + + +#ifdef NINTENDO_AP + NdisFreeSpinLock(&pAd->nindo_ctrl_block.NINTENDO_TABLE_Lock); +#endif /* NINTENDO_AP */ + + for (apidx = 0; apidx < MAX_MBSSID_NUM(pAd); apidx++) + { + if (pAd->ApCfg.MBSSID[apidx].REKEYTimerRunning == TRUE) + { + RTMPCancelTimer(&pAd->ApCfg.MBSSID[apidx].REKEYTimer, &Cancelled); + pAd->ApCfg.MBSSID[apidx].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 */ + + + +} + +/* + ========================================================================== + 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, ("APCleanupPsQueue (0x%08lx)...\n", (ULONG)pQueue)); + + while (pQueue->Head) + { + DBGPRINT(RT_DEBUG_TRACE, + ("APCleanupPsQueue %ld...\n",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); + } +} + +/* + ========================================================================== + 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( + IN PRTMP_ADAPTER pAd) +{ + int i; +#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) */ + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + + for (bss_index = BSS0; bss_index < MAX_MBSSID_NUM(pAd); bss_index++) + fAnyStationPortSecured[bss_index] = 0; + + 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 */ + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn == TRUE) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + for (i = 1; i < MaxWcidNum; i++) + { + MAC_TABLE_ENTRY *pEntry = &pMacTable->Content[i]; + BOOLEAN bDisconnectSta = FALSE; +#ifdef APCLI_SUPPORT + if(IS_ENTRY_APCLI(pEntry) && (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + { +#ifdef MAC_REPEATER_SUPPORT + if (pEntry->bReptCli) + pEntry->ReptCliIdleCount++; + + if((pEntry->bReptCli) && (pEntry->bReptEthCli) && (pEntry->ReptCliIdleCount >= MAC_TABLE_AGEOUT_TIME)) + { + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, + (64 + (MAX_EXT_MAC_ADDR_SIZE * pEntry->MatchAPCLITabIdx) + pEntry->MatchReptCliIdx)); + RTMP_MLME_HANDLER(pAd); + RTMPRemoveRepeaterEntry(pAd, pEntry->MatchAPCLITabIdx, 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); + + continue; + } + } +#endif /* APCLI_SUPPORT */ + + if (!IS_ENTRY_CLIENT(pEntry)) + continue; + + if (pEntry->NoDataIdleCount == 0) + pEntry->StationKeepAliveCount = 0; + + pEntry->NoDataIdleCount ++; + pEntry->StaConnectTime ++; + + /* 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", + pEntry->Addr[0],pEntry->Addr[1],pEntry->Addr[2],pEntry->Addr[3], + pEntry->Addr[4],pEntry->Addr[5],MAC_TABLE_ASSOC_TIMEOUT)); +#ifdef WSC_AP_SUPPORT + if (NdisEqualMemory(pEntry->Addr, pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EntryAddr, MAC_ADDR_LEN)) + NdisZeroMemory(pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EntryAddr, MAC_ADDR_LEN); +#endif /* WSC_AP_SUPPORT */ + MacTableDeleteEntry(pAd, pEntry->Aid, 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 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 ((pAd->ApCfg.MBSSID[pEntry->apidx].StationKeepAliveTime > 0) && + (pEntry->NoDataIdleCount >= pAd->ApCfg.MBSSID[pEntry->apidx].StationKeepAliveTime)) + { + MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[pEntry->apidx]; + + /* + 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; + + ApEnqueueNullFrame(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) + { + bDisconnectSta = TRUE; + DBGPRINT(RT_DEBUG_WARN, ("ageout %02x:%02x:%02x:%02x:%02x:%02x after %d-sec silence\n", + pEntry->Addr[0],pEntry->Addr[1],pEntry->Addr[2],pEntry->Addr[3], + pEntry->Addr[4],pEntry->Addr[5],pEntry->StaIdleTimeout)); + ApLogEvent(pAd, pEntry->Addr, EVENT_AGED_OUT); + } + 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; + DBGPRINT(RT_DEBUG_WARN, ("STA-%02x:%02x:%02x:%02x:%02x:%02x had left (%d %lu)\n", + pEntry->Addr[0],pEntry->Addr[1],pEntry->Addr[2],pEntry->Addr[3], + pEntry->Addr[4],pEntry->Addr[5], + pEntry->ContinueTxFailCnt, pAd->ApCfg.EntryLifeCheck)); + } + } + + 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,pEntry->Addr[0], + pEntry->Addr[1],pEntry->Addr[2],pEntry->Addr[3],pEntry->Addr[4],pEntry->Addr[5])); + MgtMacHeaderInit(pAd, &DeAuthHdr, SUBTYPE_DEAUTH, 0, pEntry->Addr, +#ifdef P2P_SUPPORT + pAd->ApCfg.MBSSID[pEntry->apidx].Bssid, +#endif /* P2P_SUPPORT */ + pAd->ApCfg.MBSSID[pEntry->apidx].Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DeAuthHdr, + 2, &Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + +#ifdef MAC_REPEATER_SUPPORT + if ((pAd->ApCfg.bMACRepeaterEn == TRUE) && IS_ENTRY_CLIENT(pEntry)) + { + UCHAR apCliIdx, CliIdx; + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; + + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, TRUE, pEntry->Addr); + if (pReptEntry && (pReptEntry->CliConnectState != 0)) + { + 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); + RTMPRemoveRepeaterEntry(pAd, apCliIdx, CliIdx); + } + } +#endif /* MAC_REPEATER_SUPPORT */ + } + + MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr); + continue; + } + + /* 3. garbage collect the PsQueue if the STA has being idle for a while */ + if (pEntry->PsQueue.Head) + { + pEntry->PsQIdleCount ++; + if (pEntry->PsQIdleCount > 2) + { +#ifdef RTMP_MAC_PCI + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); +#endif /* RTMP_MAC_PCI */ + APCleanupPsQueue(pAd, &pEntry->PsQueue); +#ifdef RTMP_MAC_PCI + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); +#endif /* RTMP_MAC_PCI */ + 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->Aid, 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 PRE_ANT_SWITCH +#if defined (RT2883) || defined (RT3883) + /* + Use antenna with best RSSI for packet detection. If PreAntSwitch==0 then don't + modify BBP R3 in case it was set manually + */ + if (IS_RT3883(pAd) || IS_RT2883(pAd)) + { + if (pAd->CommonCfg.PreAntSwitch!=0 && pAd->Antenna.field.RxPath>1) + { + UCHAR antValue=0, r3Value; + + if (pMacTable->Size==1 && + (lastClient >= 1 && lastClient < MAX_LEN_OF_MAC_TABLE) + ) + { + MAC_TABLE_ENTRY *pEntry = &pMacTable->Content[lastClient]; + + // Last RSSI is negative number. Find largest value + if (pEntry->RssiSample.LastRssi0 > pAd->CommonCfg.PreAntSwitchRSSI) + antValue = 0; + else if (pEntry->RssiSample.LastRssi1 > pEntry->RssiSample.LastRssi0) + antValue = (pAd->Antenna.field.RxPath==3 && pEntry->RssiSample.LastRssi2>pEntry->RssiSample.LastRssi1)? 2: 1; + else + antValue = (pAd->Antenna.field.RxPath==3 && pEntry->RssiSample.LastRssi2>pEntry->RssiSample.LastRssi0)? 2: 0; + } + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &r3Value); + if ((r3Value & 0x03) != antValue) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, (r3Value & ~0x03) | antValue); + } + } +#endif /* defined (RT2883) || defined (RT3883) */ +#endif /* PRE_ANT_SWITCH */ + +#ifdef CFO_TRACK +#ifdef RT3883 + /* CFO Tracking */ + if (IS_RT3883(pAd)) + { + if (pMacTable->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 && + pMacTable->Content[lastClient].freqOffsetValid) + { + /* Track CFO */ + SHORT foValue; + SHORT offset = pMacTable->Content[lastClient].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++; + + pMacTable->Content[lastClient].freqOffsetValid = FALSE; + } + } +#endif /* RT3883 */ +#endif /* CFO_TRACK */ + + /* Update the state of port per MBSS */ + for (bss_index = BSS0; bss_index < MAX_MBSSID_NUM(pAd); bss_index++) + { + if (fAnyStationPortSecured[bss_index] > 0) + pAd->ApCfg.MBSSID[bss_index].PortSecured = WPA_802_1X_PORT_SECURED; + else + pAd->ApCfg.MBSSID[bss_index].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) + { + bRdgActive = TRUE; + } + else + { + bRdgActive = FALSE; + } + + if (pAd->CommonCfg.bRalinkBurstMode && pMacTable->fAllStationGainGoodMCS) + { + bRalinkBurstMode = TRUE; + } + else + { + bRalinkBurstMode = FALSE; + } +#ifdef DOT11_N_SUPPORT +#ifdef GREENAP_SUPPORT + if (pAd->CommonCfg.PhyMode>=PHY_11ABGN_MIXED) + { + 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)) + { + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + 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) + { + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + 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)) + { + if (bRdgActive) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); + AsicEnableRDG(pAd); + } + else + { + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); + AsicDisableRDG(pAd); + } + } + + if (bRalinkBurstMode != RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE)) + { + if (bRalinkBurstMode) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE); + AsicEnableRalinkBurstMode(pAd); + } + else + { + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE); + AsicDisableRalinkBurstMode(pAd); + } + } +#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 ++; + if (pMacTable->PsQIdleCount > 1) + { + + /*NdisAcquireSpinLock(&pAd->MacTabLock); */ + APCleanupPsQueue(pAd, &pMacTable->McastPsQueue); + /*NdisReleaseSpinLock(&pAd->MacTabLock); */ + pMacTable->PsQIdleCount = 0; + + /* sanity check */ + if (pAd->ApCfg.BssidNum > MAX_MBSSID_NUM(pAd)) + pAd->ApCfg.BssidNum = MAX_MBSSID_NUM(pAd); + /* End of if */ + + /* clear MCAST/BCAST backlog bit for all BSS */ + for(bss_index=BSS0; bss_indexApCfg.BssidNum; bss_index++) + WLAN_MR_TIM_BCMC_CLEAR(bss_index); + /* End of for */ + } + } + 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 PRTMP_ADAPTER pAd, + IN PUCHAR 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; +} + +/* + ========================================================================== + 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 APPsIndicate( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN ULONG Wcid, + IN 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; +/* if (pEntry) */ + { + /* + Change power save mode first because we will call + RTMPDeQueuePacket() in APHandleRxPsPoll(). + + Or when Psm = PWR_ACTIVE, we will not do Aggregation in + RTMPDeQueuePacket(). + */ + pEntry->NoDataIdleCount = 0; + pEntry->PsMode = Psm; + + if ((old_psmode == PWR_SAVE) && (Psm == PWR_ACTIVE)) + { + /* TODO: For RT2870, how to handle about the BA when STA in PS mode???? */ +#ifdef RTMP_MAC_PCI +#ifdef DOT11_N_SUPPORT + /* When sta wake up, we send BAR to refresh the BA sequence. */ + SendRefreshBAR(pAd, pEntry); +#endif /* DOT11_N_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + DBGPRINT(RT_DEBUG_INFO, ("APPsIndicate - %02x:%02x:%02x:%02x:%02x:%02x wakes up, act like rx PS-POLL\n", pAddr[0],pAddr[1],pAddr[2],pAddr[3],pAddr[4],pAddr[5])); + /* sleep station awakes, move all pending frames from PSQ to TXQ if any */ + APHandleRxPsPoll(pAd, pAddr, pEntry->Aid, TRUE); + } + + /* move to above section */ +/* pEntry->NoDataIdleCount = 0; */ +/* pEntry->PsMode = Psm; */ + } +/* else */ +/* { */ + /* not in table, try to learn it ???? why bother? */ +/* } */ + return old_psmode; +} + +#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) +{ + 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; + AsicUpdateProtect(pAd, pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, 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; + AsicUpdateProtect(pAd, pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode, (ALLN_SETPROTECT), TRUE, pAd->MacTab.fAnyStationNonGF); + } + + if (pAd->MacTab.fAnyStationIsLegacy) + { + pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 3; + AsicUpdateProtect(pAd, pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode, (ALLN_SETPROTECT), TRUE, pAd->MacTab.fAnyStationNonGF); + } + + 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 (pAd->CommonCfg.PhyMode == PHY_11B) + 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; + else + ; + + 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; + + 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; + } + } + } + + if (Result == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("%02x:%02x:%02x:%02x:%02x:%02x failed in ACL checking\n", + 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( + IN PRTMP_ADAPTER pAd, + IN UCHAR Apidx) +{ + USHORT AclIdx, MacIdx; + BOOLEAN Matched; + + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + HEADER_802_11 DisassocHdr; + USHORT Reason; + + + /*Apidx = pObj->ioctl_if; */ + 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. */ + if (pAd->ApCfg.MBSSID[Apidx].AccessControlList.Policy == 0) + return; + + for (MacIdx=0; MacIdx < MAX_LEN_OF_MAC_TABLE; MacIdx++) + { + if (!IS_ENTRY_CLIENT(&pAd->MacTab.Content[MacIdx])) + continue; + + /* We only need to update associations related to ACL of MBSSID[Apidx]. */ + if (pAd->MacTab.Content[MacIdx].apidx != Apidx) + continue; + + Matched = FALSE; + for (AclIdx = 0; AclIdx < pAd->ApCfg.MBSSID[Apidx].AccessControlList.Num; AclIdx++) + { + if (MAC_ADDR_EQUAL(&pAd->MacTab.Content[MacIdx].Addr, pAd->ApCfg.MBSSID[Apidx].AccessControlList.Entry[AclIdx].Addr)) + { + Matched = TRUE; + break; + } + } + + if ((Matched == FALSE) && (pAd->ApCfg.MBSSID[Apidx].AccessControlList.Policy == 1)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Apidx = %d\n", Apidx)); + DBGPRINT(RT_DEBUG_TRACE, ("pAd->ApCfg.MBSSID[%d].AccessControlList.Policy = %ld\n", Apidx, + pAd->ApCfg.MBSSID[Apidx].AccessControlList.Policy)); + DBGPRINT(RT_DEBUG_TRACE, ("STA not on positive ACL. remove it...\n")); + + /* Before delete the entry from MacTable, send disassociation packet to client. */ + if (pAd->MacTab.Content[MacIdx].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,pAd->MacTab.Content[MacIdx].Addr[0], + pAd->MacTab.Content[MacIdx].Addr[1],pAd->MacTab.Content[MacIdx].Addr[2],pAd->MacTab.Content[MacIdx].Addr[3],pAd->MacTab.Content[MacIdx].Addr[4],pAd->MacTab.Content[MacIdx].Addr[5])); + MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pAd->MacTab.Content[MacIdx].Addr, +#ifdef P2P_SUPPORT + pAd->ApCfg.MBSSID[pAd->MacTab.Content[MacIdx].apidx].Bssid, +#endif /* P2P_SUPPORT */ + pAd->ApCfg.MBSSID[pAd->MacTab.Content[MacIdx].apidx].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, pAd->MacTab.Content[MacIdx].Aid, pAd->MacTab.Content[MacIdx].Addr); + } + else if ((Matched == TRUE) && (pAd->ApCfg.MBSSID[Apidx].AccessControlList.Policy == 2)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Apidx = %d\n", Apidx)); + DBGPRINT(RT_DEBUG_TRACE, ("pAd->ApCfg.MBSSID[%d].AccessControlList.Policy = %ld\n", Apidx, + pAd->ApCfg.MBSSID[Apidx].AccessControlList.Policy)); + DBGPRINT(RT_DEBUG_TRACE, ("STA on negative ACL. remove it...\n")); + + /* Before delete the entry from MacTable, send disassociation packet to client. */ + if (pAd->MacTab.Content[MacIdx].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,pAd->MacTab.Content[MacIdx].Addr[0], + pAd->MacTab.Content[MacIdx].Addr[1],pAd->MacTab.Content[MacIdx].Addr[2],pAd->MacTab.Content[MacIdx].Addr[3],pAd->MacTab.Content[MacIdx].Addr[4],pAd->MacTab.Content[MacIdx].Addr[5])); + MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pAd->MacTab.Content[MacIdx].Addr, +#ifdef P2P_SUPPORT + pAd->ApCfg.MBSSID[pAd->MacTab.Content[MacIdx].apidx].Bssid, +#endif /* P2P_SUPPORT */ + pAd->ApCfg.MBSSID[pAd->MacTab.Content[MacIdx].apidx].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, pAd->MacTab.Content[MacIdx].Aid, pAd->MacTab.Content[MacIdx].Addr); + } + } +} + +/* + ========================================================================== + 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 ApEnqueueNullFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR TxRate, + IN UCHAR PID, + IN UCHAR apidx, + IN BOOLEAN bQosNull, + IN BOOLEAN bEOSP, + IN UCHAR OldUP) +{ + NDIS_STATUS NState; + PHEADER_802_11 pNullFr; + PUCHAR pFrame; + ULONG Length; + + + /* since TxRate may change, we have to change Duration each time */ + NState = MlmeAllocateMemory(pAd, (PUCHAR *)&pFrame); + pNullFr = (PHEADER_802_11) pFrame; + Length = sizeof(HEADER_802_11); + + if (NState == NDIS_STATUS_SUCCESS) + { +/* if ((PID & 0x3f) < WDS_PAIRWISE_KEY_OFFSET) // send to client */ + { + MgtMacHeaderInit(pAd, pNullFr, SUBTYPE_NULL_FUNC, 0, pAddr, +#ifdef P2P_SUPPORT + pAd->ApCfg.MBSSID[apidx].Bssid, +#endif /* P2P_SUPPORT */ + pAd->ApCfg.MBSSID[apidx].Bssid); + pNullFr->FC.Type = BTYPE_DATA; + pNullFr->FC.FrDs = 1; + pNullFr->Duration = RTMPCalcDuration(pAd, TxRate, 14); + +#ifdef UAPSD_SUPPORT + 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; + } /* End of if */ +#endif /* UAPSD_SUPPORT */ + + DBGPRINT(RT_DEBUG_INFO, ("send NULL Frame @%d Mbps to AID#%d...\n", RateIdToMbps[TxRate], PID & 0x3f)); + MiniportMMRequest(pAd, MapUserPriorityToAccessCategory[7], (PUCHAR)pNullFr, Length); + } + + MlmeFreeMemory(pAd, pFrame); + } +} + + + +#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( + IN RTMP_ADAPTER *pAd) +{ + BOOLEAN needFallBack = FALSE; + UCHAR Channel = pAd->CommonCfg.Channel; + UINT8 BBPValue = 0; + INT chStartIdx, chEndIdx, index,curPriChIdx, curSecChIdx; + + + /* We just care BSS who operating in 40MHz N Mode. */ + if ((pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED) || + (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_20) + || (pAd->CommonCfg.Channel > 14) + ) + { + DBGPRINT(RT_DEBUG_TRACE, ("The pAd->PhyMode=%d, BW=%d, didn't need channel adjustment!\n", + pAd->CommonCfg.PhyMode, pAd->CommonCfg.RegTransmitSetting.field.BW)); + 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) + { +#ifdef RTMP_MAC_PCI + unsigned long irqFlags=0; +#endif // RTMP_MAC_PCI // + + DBGPRINT(RT_DEBUG_TRACE, ("Card still not enable Tx/Rx, enable it now!\n")); +#ifdef RTMP_MAC_PCI + /* Enable Interrupt */ + RTMP_INT_LOCK(&pAd->irq_lock, irqFlags); + pAd->int_enable_reg = ((DELAYINTMASK) | (RxINT|TxDataInt|TxMgmtInt)) & ~(0x03); + pAd->int_disable_mask = 0; + pAd->int_pending = 0; + RTMP_INT_UNLOCK(&pAd->irq_lock, irqFlags); + + RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, 0xffffffff); /* clear garbage interrupts */ + RTMP_ASIC_INTERRUPT_ENABLE(pAd); +#endif /* RTMP_MAC_PCI */ + + + /* Now Enable RxTx */ + RTMPEnableRxTx(pAd); + + /* APRxDoneInterruptHandle 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; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPValue); + BBPValue &= (~0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPValue); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + + /* Let BBP register at 20MHz to do scan */ + AsicSwitchChannel(pAd, Channel, TRUE); + AsicLockChannel(pAd, Channel); + + 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; + } + + 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].Bssid, MAC_ADDR_LENGTH); + 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].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]; + UINT8 offset = 0; + + if((pEntry->AuthMode == Ndis802_11AuthModeWPA) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pAd->ApCfg.MBSSID[apidx].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].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)); + + /* 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/mt7620/src/ap/ap_apcli.c b/mt7620/src/ap/ap_apcli.c new file mode 100644 index 0000000..e37d8a4 --- /dev/null +++ b/mt7620/src/ap/ap_apcli.c @@ -0,0 +1,3043 @@ +/* + *************************************************************************** + * 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 + MBSS_VirtualIF_PacketSend() by using RTMP_SET_PACKET_NET_DEVICE_MBSSID() + 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" + + + +/* --------------------------------- Public -------------------------------- */ +/* +======================================================================== +Routine Description: + Close ApCli network interface. + +Arguments: + ad_p points to our adapter + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RT28xx_ApCli_Close( + IN PRTMP_ADAPTER ad_p) +{ + UINT index; + + + for(index = 0; index < MAX_APCLI_NUM; index++) + { + if (ad_p->ApCfg.ApCliTab[index].dev) + RtmpOSNetDevClose(ad_p->ApCfg.ApCliTab[index].dev); + } + +} + + + + +/* --------------------------------- Private -------------------------------- */ +INT ApCliIfLookUp( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr) +{ + SHORT i; + SHORT ifIndex = -1; + + do + { + for(i = 0; i < MAX_APCLI_NUM; i++) + { + if( MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[i].CurrentAddress, pAddr)) + { + ifIndex = i; + DBGPRINT(RT_DEBUG_TRACE, ("(%s) ApCliIfIndex = %d\n", __FUNCTION__, ifIndex)); + break; + } + } + } while (FALSE); + + return ifIndex; +} + +BOOLEAN isValidApCliIf( + SHORT ifIndex) +{ + if((ifIndex >= 0) && (ifIndex < MAX_APCLI_NUM)) + return TRUE; + else + return 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 PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN PUCHAR pDA, + IN PUCHAR pBssid, + IN USHORT ifIndex) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + pHdr80211->FC.Type = BTYPE_MGMT; + pHdr80211->FC.SubType = SubType; + pHdr80211->FC.ToDs = ToDs; + COPY_MAC_ADDR(pHdr80211->Addr1, pDA); + COPY_MAC_ADDR(pHdr80211->Addr2, pAd->ApCfg.ApCliTab[ifIndex].CurrentAddress); + 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 PRTMP_ADAPTER pAd, + IN USHORT IfIndex, + IN OUT HT_CAPABILITY_IE *pHtCapability, + IN OUT ADD_HT_INFO_IE *pAddHtInfo) +{ + PAPCLI_STRUCT pApCliEntry = NULL; + + if (IfIndex >= MAX_APCLI_NUM) + return FALSE; + + pApCliEntry = &pAd->ApCfg.ApCliTab[IfIndex]; + + /* If use AMSDU, set flag. */ + if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE)) + CLIENT_STATUS_SET_FLAG(pApCliEntry, fCLIENT_STATUS_AMSDU_INUSED); + /* Save Peer Capability */ + if (pHtCapability->HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(pApCliEntry, fCLIENT_STATUS_SGI20_CAPABLE); + if (pHtCapability->HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(pApCliEntry, fCLIENT_STATUS_SGI40_CAPABLE); + if (pHtCapability->HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(pApCliEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); + if (pHtCapability->HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(pApCliEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); + if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) + CLIENT_STATUS_SET_FLAG(pApCliEntry, fCLIENT_STATUS_RDG_CAPABLE); + pApCliEntry->MpduDensity = pHtCapability->HtCapParm.MpduDensity; + + if ((pAd->OpMode == OPMODE_STA)) + { + } + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[0] = 0xff; + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[4] = 0x1; + switch (pAd->CommonCfg.RxStream) + { + case 1: + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[0] = 0xff; + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[1] = 0x00; + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[2] = 0x00; + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[3] = 0x00; + break; + case 2: + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[0] = 0xff; + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[1] = 0xff; + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[2] = 0x00; + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[3] = 0x00; + break; + case 3: + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[0] = 0xff; + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[1] = 0xff; + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[2] = 0xff; + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[3] = 0x00; + break; + } + + /* Record the RxMcs of AP */ + NdisMoveMemory(pApCliEntry->RxMcsSet, pHtCapability->MCSSet, 16); + + + + /* choose smaller setting */ + pApCliEntry->ApCliMlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth; + pApCliEntry->ApCliMlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF; + + /* Send Assoc Req with my HT capability. */ + pApCliEntry->ApCliMlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize; + pApCliEntry->ApCliMlmeAux.HtCapability.HtCapInfo.MimoPs = pHtCapability->HtCapInfo.MimoPs; + pApCliEntry->ApCliMlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20); + pApCliEntry->ApCliMlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40); + pApCliEntry->ApCliMlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC); + pApCliEntry->ApCliMlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC); + pApCliEntry->ApCliMlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = (pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor) & (pHtCapability->HtCapParm.MaxRAmpduFactor); + pApCliEntry->ApCliMlmeAux.HtCapability.HtCapParm.MpduDensity = pHtCapability->HtCapParm.MpduDensity; + pApCliEntry->ApCliMlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC; + if (pAd->CommonCfg.bRdg) + { + pApCliEntry->ApCliMlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport; + } + + /*COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability); */ + return TRUE; +} +#endif /* DOT11_N_SUPPORT */ + +/* + ========================================================================== + + 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( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex) +{ + BOOLEAN result = FALSE; + PAPCLI_STRUCT pApCliEntry = NULL; + PMAC_TABLE_ENTRY pMacEntry = NULL; +#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 */ + + do + { + if ((ifIndex < MAX_APCLI_NUM) +#ifdef MAC_REPEATER_SUPPORT + || (ifIndex >= 64) +#endif /* MAC_REPEATER_SUPPORT */ + ) + { +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + { + if (ifIndex < MAX_APCLI_NUM) + { + 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 Address = %02X:%02X:%02X:%02X:%02X:%02X. !!!\n", + PRINT_MAC(pAd->ApCfg.BridgeAddress))); + + } + DBGPRINT(RT_DEBUG_ERROR, (" Interface Name (%s) !!!\n", pNetDev->name)); + pSkipEntry = RepeaterInvaildMacLookup(pAd, pNetDev->dev_addr); + if (pSkipEntry == NULL) + RTMPRepeaterInsertInvaildMacEntry(pAd, pNetDev->dev_addr); + } + } + + 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(apcli%d) AuthMode(%d)=%s, WepStatus(%d)=%s !!!\n", + ifIndex, + pAd->ApCfg.ApCliTab[ifIndex].AuthMode, GetAuthMode(pAd->ApCfg.ApCliTab[ifIndex].AuthMode), + pAd->ApCfg.ApCliTab[ifIndex].WepStatus, GetEncryptType(pAd->ApCfg.ApCliTab[ifIndex].WepStatus))); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("!!! ERROR : APCLI LINK UP - IF(apcli%d)!!!\n", ifIndex)); + result = FALSE; + break; + } + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + DBGPRINT(RT_DEBUG_ERROR, ("(%s) ifIndex = %d, CliIdx = %d !!!\n", __FUNCTION__, ifIndex, CliIdx)); +#endif /* MAC_REPEATER_SUPPORT */ + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + /* Sanity check: This link had existed. */ + if ((pApCliEntry->Valid) +#ifdef MAC_REPEATER_SUPPORT + && (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + ) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!! ERROR : This link had existed - IF(apcli%d)!!!\n", ifIndex)); + result = FALSE; + break; + } + + /* Insert the Remote AP to our MacTable. */ + /*pMacEntry = MacTableInsertApCliEntry(pAd, (PUCHAR)(pAd->ApCliMlmeAux.Bssid)); */ +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + pMacEntry = RTMPInsertRepeaterMacEntry(pAd, (PUCHAR)(pApCliEntry->ApCliMlmeAux.Bssid), (ifIndex + MIN_NET_DEVICE_FOR_APCLI), CliIdx, TRUE); + else +#endif /* MAC_REPEATER_SUPPORT */ + pMacEntry = MacTableInsertEntry(pAd, (PUCHAR)(pApCliEntry->ApCliMlmeAux.Bssid), (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; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + 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->Aid; +#ifdef MAC_REPEATER_SUPPORT + pMacEntry->bReptCli = FALSE; +#endif /* MAC_REPEATER_SUPPORT */ + + COPY_MAC_ADDR(APCLI_ROOT_BSSID_GET(pAd, pApCliEntry->MacTabWCID), pApCliEntry->ApCliMlmeAux.Bssid); + pApCliEntry->SsidLen = pApCliEntry->ApCliMlmeAux.SsidLen; + NdisMoveMemory(pApCliEntry->Ssid, pApCliEntry->ApCliMlmeAux.Ssid, pApCliEntry->SsidLen); + } + +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + /* + If ApCli connects to different AP, ApCli couldn't send EAPOL_Start for WpaSupplicant. + */ + if ((pApCliEntry->AuthMode == Ndis802_11AuthModeWPA2) && + (NdisEqualMemory(pAd->MlmeAux.Bssid, pApCliEntry->LastBssid, MAC_ADDR_LEN) == FALSE) && + (pApCliEntry->bLostAp == TRUE)) + { + pApCliEntry->bLostAp = FALSE; + } + + COPY_MAC_ADDR(pApCliEntry->LastBssid, pAd->MlmeAux.Bssid); +#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ + + + if (pMacEntry->AuthMode >= Ndis802_11AuthModeWPA) + pMacEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + else + { + +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + if (pApCliEntry->WpaSupplicantUP && + (pMacEntry->WepStatus == Ndis802_11WEPEnabled) && + (pApCliEntry->IEEE8021X == TRUE)) + pMacEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + else +#endif /*APCLI_WPA_SUPPLICANT_SUPPORT*/ + + pMacEntry->PortSecured = WPA_802_1X_PORT_SECURED; +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + pAd->ApCfg.ApCliTab[ifIndex].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->ApCliMlmeAux.VarIELen != 0)) + { + PUCHAR pVIE; + UCHAR len; + PEID_STRUCT pEid; + + pVIE = pApCliEntry->ApCliMlmeAux.VarIEs; + len = pApCliEntry->ApCliMlmeAux.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->ApCliMlmeAux.SupRate, + pApCliEntry->ApCliMlmeAux.SupRateLen, + pApCliEntry->ApCliMlmeAux.ExtRate, + pApCliEntry->ApCliMlmeAux.ExtRateLen, + &pRates, + &RatesLen, + &MaxSupportedRate); + + pMacEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); + pMacEntry->RateLen = RatesLen; + if (pMacEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE) + { + pMacEntry->MaxHTPhyMode.field.MODE = MODE_CCK; + pMacEntry->MaxHTPhyMode.field.MCS = pMacEntry->MaxSupportedRate; + pMacEntry->MinHTPhyMode.field.MODE = MODE_CCK; + pMacEntry->MinHTPhyMode.field.MCS = pMacEntry->MaxSupportedRate; + pMacEntry->HTPhyMode.field.MODE = MODE_CCK; + pMacEntry->HTPhyMode.field.MCS = pMacEntry->MaxSupportedRate; + } + else + { + pMacEntry->MaxHTPhyMode.field.MODE = MODE_OFDM; + pMacEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pMacEntry->MaxSupportedRate]; + pMacEntry->MinHTPhyMode.field.MODE = MODE_OFDM; + pMacEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pMacEntry->MaxSupportedRate]; + pMacEntry->HTPhyMode.field.MODE = MODE_OFDM; + pMacEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pMacEntry->MaxSupportedRate]; + } + pMacEntry->CapabilityInfo = pApCliEntry->ApCliMlmeAux.CapabilityInfo; + + if ((pApCliEntry->WepStatus == Ndis802_11WEPEnabled) +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + && (pApCliEntry->WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) +#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ + ) + { + PCIPHER_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 == pApCliEntry->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->Aid, + SHAREDKEYTABLE); + } + } + } + } + +#ifdef DOT11_N_SUPPORT + /* If this Entry supports 802.11n, upgrade to HT rate. */ + if (pApCliEntry->ApCliMlmeAux.HtCapabilityLen != 0) + { + UCHAR j, bitmask; /*k,bitmask; */ + CHAR i; + PHT_CAPABILITY_IE pHtCapability = (PHT_CAPABILITY_IE)&(pApCliEntry->ApCliMlmeAux.HtCapability); + + if ((pApCliEntry->ApCliMlmeAux.HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) + { + pMacEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD; + } + else + { + pMacEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pAd->MacTab.fAnyStationNonGF = TRUE; + pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1; + } + + if ((pHtCapability->HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth)) + { + pMacEntry->MaxHTPhyMode.field.BW= BW_40; + pMacEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(pHtCapability->HtCapInfo.ShortGIfor40)); + } + else + { + pMacEntry->MaxHTPhyMode.field.BW = BW_20; + pMacEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(pHtCapability->HtCapInfo.ShortGIfor20)); + pAd->MacTab.fAnyStation20Only = TRUE; + } + + /* find max fixed rate */ + + /*for (i=15; i>=0; i--) */ + for (i=23; i>=0; i--) /*3*3 */ + { + j = i/8; + bitmask = (1<<(i-(j*8))); + if ((pAd->ApCfg.ApCliTab[ifIndex].DesiredHtPhyInfo.MCSSet[j] & bitmask) && (pHtCapability->MCSSet[j] & bitmask)) + { + pMacEntry->MaxHTPhyMode.field.MCS = i; + break; + } + if (i==0) + break; + } + + + if (pAd->ApCfg.ApCliTab[ifIndex].DesiredTransmitSetting.field.MCS != MCS_AUTO) + { + DBGPRINT(RT_DEBUG_TRACE, ("IF-apcli%d : Desired MCS = %d\n", ifIndex, + pAd->ApCfg.ApCliTab[ifIndex].DesiredTransmitSetting.field.MCS)); + + if (pAd->ApCfg.ApCliTab[ifIndex].DesiredTransmitSetting.field.MCS == 32) + { + /* Fix MCS as HT Duplicated Mode */ + pMacEntry->MaxHTPhyMode.field.BW = 1; + pMacEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pMacEntry->MaxHTPhyMode.field.STBC = 0; + pMacEntry->MaxHTPhyMode.field.ShortGI = 0; + pMacEntry->MaxHTPhyMode.field.MCS = 32; + } + else if (pMacEntry->MaxHTPhyMode.field.MCS > pAd->ApCfg.ApCliTab[ifIndex].HTPhyMode.field.MCS) + { + /* STA supports fixed MCS */ + pMacEntry->MaxHTPhyMode.field.MCS = pAd->ApCfg.ApCliTab[ifIndex].HTPhyMode.field.MCS; + } + } + + pMacEntry->MaxHTPhyMode.field.STBC = (pHtCapability->HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); + 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->ApCliMlmeAux.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 */ + + pMacEntry->HTPhyMode.word = pMacEntry->MaxHTPhyMode.word; + pMacEntry->CurrTxRate = pMacEntry->MaxSupportedRate; + + if (pAd->ApCfg.ApCliTab[ifIndex].bAutoTxRateSwitch == FALSE) + { + pMacEntry->bAutoTxRateSwitch = FALSE; + /* If the legacy mode is set, overwrite the transmit setting of this entry. */ + RTMPUpdateLegacyTxSetting((UCHAR)pAd->ApCfg.ApCliTab[ifIndex].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; + + } + + /* It had been set in APStartUp. Don't set again. */ + /*AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); */ + + /* set this entry WMM capable or not */ + if ((pApCliEntry->ApCliMlmeAux.APEdcaParm.bValid) +#ifdef DOT11_N_SUPPORT + || IS_HT_STA(pMacEntry) +#endif /* DOT11_N_SUPPORT */ + ) + { +#ifdef APCLI_CERT_SUPPORT + if (pAd->bApCliCertTest == TRUE) + { + AsicSetEdcaParm(pAd, &pApCliEntry->ApCliMlmeAux.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); + } + +#ifdef APCLI_CERT_SUPPORT + if (pAd->bApCliCertTest == TRUE) + { + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + Data &= 0xFFFFFF00; + Data |= 0x60; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + + RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3FBF9F); + } +#endif /* APCLI_CERT_SUPPORT */ + + if (pAd->CommonCfg.bAggregationCapable) + { + if ((pAd->CommonCfg.bPiggyBackCapable) && (pApCliEntry->ApCliMlmeAux.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->ApCliMlmeAux.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->ApCliMlmeAux.APRalinkIe != 0x0) + CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET); + else + CLIENT_STATUS_CLEAR_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET); + + /* set the apcli interface be valid. */ +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + pApCliEntry->Valid = TRUE; + result = TRUE; + +#ifdef MAC_APCLI_SUPPORT +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + AsicSetApCliBssid(pAd, pApCliEntry->ApCliMlmeAux.Bssid, ifIndex); +#endif /* MAC_APCLI_SUPPORT */ + + + 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 APCLI_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].bLostAp == TRUE)) + { + ApcliWpaSendEapolStart(pAd, pAd->MlmeAux.Bssid,pMacEntry,&pAd->ApCfg.ApCliTab[ifIndex]); + pAd->ApCfg.ApCliTab[ifIndex].bLostAp = FALSE; + } +#endif /*APCLI_WPA_SUPPLICANT_SUPPORT */ + + RTMPSetSupportMCS(pAd, + OPMODE_AP, + pMacEntry, + pApCliEntry->ApCliMlmeAux.SupRate, + pApCliEntry->ApCliMlmeAux.SupRateLen, + pApCliEntry->ApCliMlmeAux.ExtRate, + pApCliEntry->ApCliMlmeAux.ExtRateLen, + &pApCliEntry->ApCliMlmeAux.HtCapability, + pApCliEntry->ApCliMlmeAux.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_ENROLLEE) && + (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->ApCliMlmeAux.Bssid, MAC_ADDR_LEN); + WscSendEapolStart(pAd, pMacEntry->Addr, AP_MODE); + } + else + { + WscStop(pAd, TRUE, &pAd->ApCfg.ApCliTab[ifIndex].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->DesiredHtPhyInfo.bHtEnable == TRUE) + && (pApCliEntry->ApCliMlmeAux.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->DesiredHtPhyInfo.bHtEnable)); + DBGPRINT(RT_DEBUG_TRACE, + ("pAd->ApCliMlmeAux.ExtCapInfo.BssCoexstSup %d !!! \n", + pApCliEntry->ApCliMlmeAux.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 */ + return result; +} + +/* + ========================================================================== + + Routine Description: + Disconnect current BSSID + + Arguments: + pAd - Pointer to our adapter + ApCliIdx - Which ApCli interface + Return Value: + None + + Note: + + ========================================================================== +*/ +VOID ApCliLinkDown( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex) +{ + PAPCLI_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); + DBGPRINT(RT_DEBUG_ERROR, ("!!! REPEATER CLI LINK DOWN - IF(apcli%d) Cli %d !!!\n", ifIndex, CliIdx)); + } + else +#endif /* MAC_REPEATER_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("!!! APCLI LINK DOWN - IF(apcli%d)!!!\n", ifIndex)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! ERROR : APCLI LINK DOWN - IF(apcli%d)!!!\n", ifIndex)); + return; + } + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + if ((pApCliEntry->Valid == FALSE) +#ifdef MAC_REPEATER_SUPPORT + && (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + ) + return; + +#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; + + 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 */ + +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + if (pApCliEntry->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 /* APCLI_WPA_SUPPLICANT_SUPPORT */ +#ifdef APCLI_CERT_SUPPORT + if (pAd->bApCliCertTest == TRUE) + { + AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); /* Restore AP's EDCA parameters. */ + pAd->ApCfg.BssEdcaParm.EdcaUpdateCount++; + } +#endif /* APCLI_CERT_SUPPORT */ +} + +/* + ========================================================================== + Description: + APCLI Interface Up. + ========================================================================== + */ +VOID ApCliIfUp( + IN PRTMP_ADAPTER pAd) +{ + UCHAR ifIndex; + PAPCLI_STRUCT pApCliEntry; + + /* 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(ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + if (APCLI_IF_UP_CHECK(pAd, ifIndex) + && (pApCliEntry->Enable == TRUE) + && (pApCliEntry->Valid == FALSE)) + { + 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); + } + } + + return; +} + + +/* + ========================================================================== + Description: + APCLI Interface Down. + ========================================================================== + */ +VOID ApCliIfDown( + IN PRTMP_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]; + 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) + { + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, + (64 + MAX_EXT_MAC_ADDR_SIZE*ifIndex + CliIdx)); + RTMP_MLME_HANDLER(pAd); + 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( + IN PRTMP_ADAPTER pAd) +{ + UCHAR index; + PAPCLI_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++) + { + 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) && (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)))) + { + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, (64 + MAX_EXT_MAC_ADDR_SIZE*index + CliIdx)); + RTMP_MLME_HANDLER(pAd); + 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]; + + 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 + (4 * OS_HZ)))) + bForceBrocken = TRUE; + } + else + continue; + + if (bForceBrocken == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("ApCliIfMonitor: IF(apcli%d) - no Beancon is received from root-AP.\n", index)); + 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) + { + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, (64 + MAX_EXT_MAC_ADDR_SIZE*index + CliIdx)); + RTMP_MLME_HANDLER(pAd); + 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 == BTYPE_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_ENROLLEE) + { + *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 == BTYPE_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 == BTYPE_MGMT) + { + switch (pFrame->Hdr.FC.SubType) + { + /* Beacon must be processed be 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) +{ + CHAR IeType, *Ptr; + 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); + 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, ("PeerAssocRspSanity fail - wrong SupportedRates IE\n")); + 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, ("PeerAssocRspSanity - wrong IE_HT_CAP. \n")); + } + + 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, ("PeerAssocRspSanity - wrong IE_ADD_HT. \n")); + } + break; + case IE_SECONDARY_CH_OFFSET: + if (pEid->Len == 1) + { + *pNewExtChannelOffset = pEid->Octet[0]; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n")); + } + break; +#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, ("PeerAssocRspSanity - ignore unrecognized EID = %d\n", pEid->Eid)); + break; + } + + Length = Length + 2 + pEid->Len; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + return TRUE; +} + + +MAC_TABLE_ENTRY *ApCliTableLookUpByWcid( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid, + IN PUCHAR pAddrs) +{ + ULONG ApCliIndex; + PMAC_TABLE_ENTRY pCurEntry = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + + if (wcid <=0 || wcid >= MAX_LEN_OF_MAC_TABLE ) + return NULL; + + NdisAcquireSpinLock(&pAd->MacTabLock); + + do + { + pCurEntry = &pAd->MacTab.Content[wcid]; + + ApCliIndex = 0xff; + if ((pCurEntry) && IS_ENTRY_APCLI(pCurEntry)) + { + ApCliIndex = pCurEntry->MatchAPCLITabIdx; + } + + 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( + IN PRTMP_ADAPTER pAd, + IN INT apCliIdx) +{ + BOOLEAN result; + PMAC_TABLE_ENTRY pMacEntry; + APCLI_STRUCT *pApCliEntry; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + + 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; + } + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + if ((pApCliEntry->MacTabWCID <= 0) + || (pApCliEntry->MacTabWCID >= MaxWcidNum)) + { + result = FALSE; + break; + } + + pMacEntry = &pAd->MacTab.Content[pApCliEntry->MacTabWCID]; + if (!IS_ENTRY_APCLI(pMacEntry)) + { + result = FALSE; + break; + } + + result = TRUE; + } while(FALSE); + + return result; +} + +BOOLEAN ApCliAllowToSendPacket( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + OUT UCHAR *pWcid) +{ + UCHAR apCliIdx; + BOOLEAN allowed; + + /*DBGPRINT(RT_DEBUG_TRACE, ("ApCliAllowToSendPacket():Packet to ApCli interface!\n")); */ + apCliIdx = RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_APCLI; + if (ValidApCliEntry(pAd, apCliIdx)) + { +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn == TRUE) + { + PUCHAR pSrcBufVA = NULL; + PACKET_INFO PacketInfo; + UINT SrcBufLen; + PMAC_TABLE_ENTRY pEntry = NULL; + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, TRUE, (pSrcBufVA + MAC_ADDR_LEN)); + + if (pReptEntry) + { + *pWcid = pReptEntry->MacTabWCID; + return TRUE; + } + else + { + if (RTMPRepeaterVaildMacEntry(pAd, pSrcBufVA + MAC_ADDR_LEN)) + { + pEntry = &pAd->MacTab.Content[pAd->ApCfg.ApCliTab[apCliIdx].MacTabWCID]; + + if ((pEntry) && (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + RTMPInsertRepeaterEntry(pAd, apCliIdx, (pSrcBufVA + ETH_LENGTH_OF_ADDRESS)); + DBGPRINT(RT_DEBUG_ERROR, (" Receive trigger packet !!!\n")); + return FALSE; + } + } + } + + *pWcid = pAd->ApCfg.ApCliTab[apCliIdx].MacTabWCID; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + *pWcid = pAd->ApCfg.ApCliTab[apCliIdx].MacTabWCID; + + allowed = TRUE; + } + else + { + allowed = FALSE; + } + + 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 PRTMP_ADAPTER pAd, + IN PEID_STRUCT pEid_ptr, + IN USHORT eid_len, + IN USHORT idx) +{ + PUCHAR pVIE; + PUCHAR 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; + + 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_11Encryption1Enabled; + break; + case 2: + WPA.GroupCipher = Ndis802_11Encryption2Enabled; + break; + case 4: + WPA.GroupCipher = Ndis802_11Encryption3Enabled; + 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_11Encryption1Enabled; + break; + case 2: + TmpCipher = Ndis802_11Encryption2Enabled; + break; + case 4: + TmpCipher = Ndis802_11Encryption3Enabled; + 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_11Encryption1Enabled; + break; + case 2: + WPA2.GroupCipher = Ndis802_11Encryption2Enabled; + break; + case 4: + WPA2.GroupCipher = Ndis802_11Encryption3Enabled; + 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_11Encryption1Enabled; + break; + case 2: + TmpCipher = Ndis802_11Encryption2Enabled; + break; + case 4: + TmpCipher = Ndis802_11Encryption3Enabled; + 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]; + + /* Peer AP doesn't include WPA/WPA2 capable */ + if (Sanity == 0) + { + /* Check the authenticaton mode */ + if (pApCliEntry->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 (pApCliEntry->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 = pApCliEntry->WepStatus; + pApCliEntry->GroupCipher = pApCliEntry->WepStatus; + pApCliEntry->bMixCipher = FALSE; + + Sanity = 0; + + /* Check AuthMode and WPA_AuthModeAux for matching, in case AP support dual-AuthMode */ + /* WPAPSK */ + if ((WPA_AuthMode == pApCliEntry->AuthMode) || + ((WPA_AuthModeAux != Ndis802_11AuthModeOpen) && (WPA_AuthModeAux == pApCliEntry->AuthMode))) + { + /* Check cipher suite, AP must have more secured cipher than station setting */ + if (WPA.bMixMode == FALSE) + { + if (pApCliEntry->WepStatus != WPA.GroupCipher) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA validate cipher suite error \n")); + return FALSE; + } + } + + /* check group cipher */ + if (pApCliEntry->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 ((pApCliEntry->WepStatus == Ndis802_11Encryption2Enabled) && + (pApCliEntry->WepStatus != WPA.PairCipher) && + (pApCliEntry->WepStatus != WPA.PairCipherAux)) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA validate pairwise cipher error \n")); + return FALSE; + } + + Sanity |= 0x1; + } + /* WPA2PSK */ + else if ((WPA2_AuthMode == pApCliEntry->AuthMode) || + ((WPA2_AuthModeAux != Ndis802_11AuthModeOpen) && (WPA2_AuthModeAux == pApCliEntry->AuthMode))) + { + /* Check cipher suite, AP must have more secured cipher than station setting */ + if (WPA2.bMixMode == FALSE) + { + if (pApCliEntry->WepStatus != WPA2.GroupCipher) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA2 validate cipher suite error \n")); + return FALSE; + } + } + + /* check group cipher */ + if (pApCliEntry->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 ((pApCliEntry->WepStatus == Ndis802_11Encryption2Enabled) && + (pApCliEntry->WepStatus != WPA2.PairCipher) && + (pApCliEntry->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 ((pApCliEntry->AuthMode == Ndis802_11AuthModeWPA) || (pApCliEntry->AuthMode == Ndis802_11AuthModeWPAPSK)) + { + pApCliEntry->GroupCipher = WPA.GroupCipher; + + if (pApCliEntry->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_11Encryption2Enabled; + } + else if ((pApCliEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pApCliEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + pApCliEntry->GroupCipher = WPA2.GroupCipher; + + if (pApCliEntry->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_11Encryption2Enabled; + } + + /* 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, pApCliEntry->AuthMode, pApCliEntry->WepStatus, (idx + MIN_NET_DEVICE_FOR_APCLI)); + + return TRUE; +} + +/* + =================================================== + + Description: + Check the validation of Authentication mode and Security type between + entries in the Apcli table and the inputs. + + Arguments: + pApcliTabEntry: + WPA_AuthMode + WPA_AuthModeAux + WPA: WPA cipher suite + + Return Value: + TRUE: valid + FALSE: invalid + + Note: + =================================================== +*/ +BOOLEAN ApCliValidateAuthEncryp( + IN PAPCLI_STRUCT pApCliEntry, + IN NDIS_802_11_AUTHENTICATION_MODE WPA_AuthMode, + IN NDIS_802_11_AUTHENTICATION_MODE WPA_AuthModeAux, + IN CIPHER_SUITE WPA) +{ + CIPHER_SUITE tempWPA; + tempWPA.PairCipher = pApCliEntry->PairCipher; + tempWPA.GroupCipher = pApCliEntry->GroupCipher; + tempWPA.bMixMode = pApCliEntry->bMixCipher; + + // Recovery user-defined cipher suite + pApCliEntry->PairCipher = pApCliEntry->WepStatus; + pApCliEntry->GroupCipher = pApCliEntry->WepStatus; + pApCliEntry->bMixCipher = FALSE; + + // Check AuthMode and WPA_AuthModeAux for matching, in case AP support dual-AuthMode + // WPAPSK + if (WPA_AuthMode == pApCliEntry->AuthMode || WPA_AuthModeAux == pApCliEntry->AuthMode) + { + // Check cipher suite, AP must have more secured cipher than station setting + if (WPA.bMixMode == FALSE) + { + if (pApCliEntry->WepStatus != WPA.GroupCipher) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA validate cipher suite error \n")); + return FALSE; + } + } + + // check group cipher + if (pApCliEntry->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 ((pApCliEntry->WepStatus == Ndis802_11Encryption2Enabled) && + (pApCliEntry->WepStatus != WPA.PairCipher) && + (pApCliEntry->WepStatus != WPA.PairCipherAux)) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA validate pairwise cipher error \n")); + return FALSE; + } + } + + /* + restore previous cipher suite + */ + pApCliEntry->PairCipher = tempWPA.PairCipher; + pApCliEntry->GroupCipher = tempWPA.GroupCipher; + pApCliEntry->bMixCipher = tempWPA.bMixMode; + return TRUE; +} + +BOOLEAN ApCliHandleRxBroadcastFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR FromWhichBSSID) +{ + PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); + PHEADER_802_11 pHeader = pRxBlk->pHeader; +#ifndef MAC_APCLI_SUPPORT + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; +#endif + PAPCLI_STRUCT pApCliEntry = NULL; +#ifdef MAC_REPEATER_SUPPORT + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; +#endif /* MAC_REPEATER_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->MatchAPCLITabIdx]; + + /* 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 */ + if (MAC_ADDR_EQUAL(pHeader->Addr3, pApCliEntry->CurrentAddress)) + return FALSE; /* give up this frame */ + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + { + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, FALSE, pHeader->Addr3); + if (pReptEntry) + return FALSE; /* give up this frame */ + } +#endif /* MAC_REPEATER_SUPPORT */ + + if (pEntry->PrivacyFilter != Ndis802_11PrivFilterAcceptAll) + return FALSE; /* give up this frame */ + + + /* skip the 802.11 header */ + pRxBlk->pData += LENGTH_802_11; + pRxBlk->DataSize -= LENGTH_802_11; + +#ifndef MAC_APCLI_SUPPORT + /* 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 ((pRxD->MyBss == 0) && (pRxD->Decrypted == 0) && (pHeader->FC.Wep == 1)) + { + if (RTMPSoftDecryptionAction(pAd, + (PUCHAR)pHeader, 0, + &pApCliEntry->SharedKey[pRxWI->KeyIndex], + pRxBlk->pData, + &(pRxBlk->DataSize)) == NDIS_STATUS_FAILURE) + { + ApCliRTMPReportMicError( pAd,&pApCliEntry->SharedKey[pRxWI->KeyIndex], pEntry->MatchAPCLITabIdx); + return FALSE; /* give up this frame */ + } + } +#endif /* MAC_APCLI_SUPPORT */ + pRxD->MyBss = 1; + 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->MatchAPCLITabIdx; + 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; + + if (!pEntry || !IS_ENTRY_APCLI(pEntry)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : This Entry doesn't exist!!! \n", __FUNCTION__)); + return FALSE; + } + + IfIdx = pEntry->MatchAPCLITabIdx; + + if (pAd->ApCfg.ApCliTab[IfIdx].GroupCipher == Ndis802_11Encryption2Enabled && KeyLen >= LEN_TKIP_GTK) + { + GTK_len = LEN_TKIP_GTK; + } + else if (pAd->ApCfg.ApCliTab[IfIdx].GroupCipher == Ndis802_11Encryption3Enabled && + KeyLen >= LEN_AES_GTK) + { + GTK_len = LEN_AES_GTK; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : GTK is invalid (GroupCipher=%d, DataLen=%d) !!! \n", + __FUNCTION__, pAd->ApCfg.ApCliTab[IfIdx].GroupCipher, KeyLen)); + return FALSE; + } + + /* Update GTK */ + /* set key material, TxMic and RxMic for WPAPSK */ + NdisMoveMemory(pAd->ApCfg.ApCliTab[IfIdx].GTK, pKey, GTK_len); + pAd->ApCfg.ApCliTab[IfIdx].DefaultKeyId = DefaultKeyIdx; + + /* Update shared key table */ + NdisZeroMemory(&pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx], sizeof(CIPHER_KEY)); + pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx].KeyLen = GTK_len; + NdisMoveMemory(pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx].Key, pKey, LEN_TK); + if (GTK_len == LEN_TKIP_GTK) + { + NdisMoveMemory(pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx].RxMic, pKey + 16, LEN_TKIP_MIC); + NdisMoveMemory(pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx].TxMic, pKey + 24, LEN_TKIP_MIC); + } + + /* Update Shared Key CipherAlg */ + pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx].CipherAlg = CIPHER_NONE; + if (pAd->ApCfg.ApCliTab[IfIdx].GroupCipher == Ndis802_11Encryption2Enabled) + pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx].CipherAlg = CIPHER_TKIP; + else if (pAd->ApCfg.ApCliTab[IfIdx].GroupCipher == Ndis802_11Encryption3Enabled) + pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx].CipherAlg = CIPHER_AES; + + +#ifdef MAC_APCLI_SUPPORT + RTMP_ASIC_SHARED_KEY_TABLE(pAd, + APCLI_BSS_BASE + IfIdx, + DefaultKeyIdx, + &pAd->ApCfg.ApCliTab[IfIdx].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 + + ======================================================================== +*/ +VOID ApCliUpdateMlmeRate( + IN PRTMP_ADAPTER pAd, + IN 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; + + PAPCLI_STRUCT pApCliEntry = NULL; + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + + switch (pAd->CommonCfg.PhyMode) + { + case PHY_11B: + ProperMlmeRate = RATE_11; + MinimumRate = RATE_1; + break; + case PHY_11BG_MIXED: +#ifdef DOT11_N_SUPPORT + case PHY_11ABGN_MIXED: + case PHY_11BGN_MIXED: +#endif /* DOT11_N_SUPPORT */ + if ((pApCliEntry->ApCliMlmeAux.SupRateLen == 4) && + (pApCliEntry->ApCliMlmeAux.ExtRateLen == 0)) + /* B only AP */ + ProperMlmeRate = RATE_11; + else + ProperMlmeRate = RATE_24; + + if (pApCliEntry->ApCliMlmeAux.Channel <= 14) + MinimumRate = RATE_1; + else + MinimumRate = RATE_6; + break; + case PHY_11A: +#ifdef DOT11_N_SUPPORT + case PHY_11N_2_4G: /* rt2860 need to check mlmerate for 802.11n */ + case PHY_11GN_MIXED: + case PHY_11AGN_MIXED: + case PHY_11AN_MIXED: + case PHY_11N_5G: +#endif /* DOT11_N_SUPPORT */ + ProperMlmeRate = RATE_24; + MinimumRate = RATE_6; + break; + case PHY_11ABG_MIXED: + ProperMlmeRate = RATE_24; + if (pApCliEntry->ApCliMlmeAux.Channel <= 14) + MinimumRate = RATE_1; + else + MinimumRate = RATE_6; + break; + default: /* error */ + ProperMlmeRate = RATE_1; + MinimumRate = RATE_1; + break; + } + + for (i = 0; i < pApCliEntry->ApCliMlmeAux.SupRateLen; i++) + { + for (j = 0; j < RateIdx; j++) + { + if ((pApCliEntry->ApCliMlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j]) + { + if (j == ProperMlmeRate) + { + bMatch = TRUE; + break; + } + } + } + + if (bMatch) + break; + } + + if (bMatch == FALSE) + { + for (i = 0; i < pApCliEntry->ApCliMlmeAux.ExtRateLen; i++) + { + for (j = 0; j < RateIdx; j++) + { + if ((pApCliEntry->ApCliMlmeAux.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, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word)); +} + +VOID APCli_Init( + IN PRTMP_ADAPTER pAd, + IN RTMP_OS_NETDEV_OP_HOOK *pNetDevOps) +{ +#define APCLI_MAX_DEV_NUM 32 + PNET_DEV new_dev_p; +/* VIRTUAL_ADAPTER *apcli_pAd; */ + INT apcli_index; +/* RTMP_OS_NETDEV_OP_HOOK netDevOpHook; */ + APCLI_STRUCT *pApCliEntry; + + /* sanity check to avoid redundant virtual interfaces are created */ + if (pAd->flg_apcli_init != FALSE) + return; + + + /* init */ + for(apcli_index = 0; apcli_index < MAX_APCLI_NUM; apcli_index++) + pAd->ApCfg.ApCliTab[apcli_index].dev = NULL; + + /* create virtual network interface */ + for(apcli_index = 0; apcli_index < MAX_APCLI_NUM; apcli_index++) + { + UINT32 MC_RowID = 0, IoctlIF = 0; +#ifdef MULTIPLE_CARD_SUPPORT + MC_RowID = pAd->MC_RowID; +#endif /* MULTIPLE_CARD_SUPPORT */ +#ifdef HOSTAPD_SUPPORT + IoctlIF = pAd->IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + new_dev_p = RtmpOSNetDevCreate(MC_RowID, &IoctlIF, INT_APCLI, apcli_index, sizeof(PRTMP_ADAPTER), INF_APCLI_DEV_NAME); +#ifdef HOSTAPD_SUPPORT + pAd->IoctlIF = IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + RTMP_OS_NETDEV_SET_PRIV(new_dev_p, pAd); + + pApCliEntry = &pAd->ApCfg.ApCliTab[apcli_index]; + /* init MAC address of virtual network interface */ + COPY_MAC_ADDR(pApCliEntry->CurrentAddress, 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 */ + + 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. + */ +#ifdef ENHANCE_NEW_MBSSID_MODE + pApCliEntry->CurrentAddress[0] &= (MacMask << 2); +#endif /* ENHANCE_NEW_MBSSID_MODE */ + pApCliEntry->CurrentAddress[0] |= 0x2; + pApCliEntry->CurrentAddress[0] += (((pAd->ApCfg.BssidNum + MAX_MESH_NUM) - 1) << 2); + } +#ifdef ENHANCE_NEW_MBSSID_MODE + else + { + pApCliEntry->CurrentAddress[0] |= 0x2; + pApCliEntry->CurrentAddress[pAd->chipCap.MBSSIDMode - 1] &= (MacMask); + pApCliEntry->CurrentAddress[pAd->chipCap.MBSSIDMode - 1] += ((pAd->ApCfg.BssidNum + MAX_MESH_NUM) - 1); + } +#endif /* ENHANCE_NEW_MBSSID_MODE */ + } + } + else + { + pApCliEntry->CurrentAddress[ETH_LENGTH_OF_ADDRESS - 1] = + (pApCliEntry->CurrentAddress[ETH_LENGTH_OF_ADDRESS - 1] + pAd->ApCfg.BssidNum + MAX_MESH_NUM) & 0xFF; + } + + + pNetDevOps->priv_flags = INT_APCLI; /* we are virtual interface */ + pNetDevOps->needProtcted = TRUE; + NdisMoveMemory(pNetDevOps->devAddr, &pApCliEntry->CurrentAddress[0], MAC_ADDR_LEN); + + /* register this device to OS */ + RtmpOSNetDevAttach(pAd->OpMode, new_dev_p, pNetDevOps); + + /* backup our virtual network interface */ + pApCliEntry->dev = new_dev_p; + } /* End of for */ + + pAd->flg_apcli_init = TRUE; + +} + + +VOID ApCli_Remove( + IN PRTMP_ADAPTER pAd) +{ + UINT index; + + for(index = 0; index < MAX_APCLI_NUM; index++) + { + if (pAd->ApCfg.ApCliTab[index].dev) + { + RtmpOSNetDevDetach(pAd->ApCfg.ApCliTab[index].dev); + + RtmpOSNetDevFree(pAd->ApCfg.ApCliTab[index].dev); + + /* Clear it as NULL to prevent latter access error. */ + pAd->flg_apcli_init = FALSE; + pAd->ApCfg.ApCliTab[index].dev = NULL; + } + } +} + + +BOOLEAN ApCli_Open( + IN PRTMP_ADAPTER pAd, + IN PNET_DEV dev_p) +{ + UCHAR ifIndex; + + + for (ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) + { + if (pAd->ApCfg.ApCliTab[ifIndex].dev == dev_p) + { + RTMP_OS_NETDEV_START_QUEUE(dev_p); + ApCliIfUp(pAd); +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, RT_INTERFACE_UP, NULL, NULL, 0); +#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ + return TRUE; + } + } + + return FALSE; +} /* End of ApCli_Open */ + + +BOOLEAN ApCli_Close( + IN PRTMP_ADAPTER pAd, + IN PNET_DEV dev_p) +{ + UCHAR ifIndex; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx; +#endif /* MAC_REPEATER_SUPPORT */ + + for (ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) + { + if (pAd->ApCfg.ApCliTab[ifIndex].dev == dev_p) + { + +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, RT_INTERFACE_DOWN, NULL, NULL, 0); + + if (pAd->ApCfg.ApCliTab[ifIndex].pWpaAssocIe) + { + os_free_mem(NULL, pAd->ApCfg.ApCliTab[ifIndex].pWpaAssocIe); + pAd->ApCfg.ApCliTab[ifIndex].pWpaAssocIe = NULL; + pAd->ApCfg.ApCliTab[ifIndex].WpaAssocIeLen = 0; + } +#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ + + RTMP_OS_NETDEV_STOP_QUEUE(dev_p); + + /* send disconnect-req to sta State Machine. */ + if (pAd->ApCfg.ApCliTab[ifIndex].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) + { + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, (64 + MAX_EXT_MAC_ADDR_SIZE*ifIndex + CliIdx)); + RTMP_MLME_HANDLER(pAd); + RTMPRemoveRepeaterEntry(pAd, ifIndex, CliIdx); + } + } + } +#endif /* MAC_REPEATER_SUPPORT */ + + 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; +} /* End of ApCli_Close */ + + +int APC_PacketSend( + IN PNDIS_PACKET skb_p, + IN PNET_DEV dev_p, + IN RTMP_NET_PACKET_TRANSMIT Func) +{ + RTMP_ADAPTER *pAd; + PAPCLI_STRUCT pApCli; + INT apcliIndex; + + + + pAd = RTMP_OS_NETDEV_GET_PRIV(dev_p); + ASSERT(pAd); + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + RELEASE_NDIS_PACKET(pAd, skb_p, NDIS_STATUS_FAILURE); + return 0; + } +#endif /* RALINK_ATE */ + + if ((RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))) + { + /* wlan is scanning/disabled/reset */ + RELEASE_NDIS_PACKET(pAd, skb_p, NDIS_STATUS_FAILURE); + return 0; + } + + + pApCli = (PAPCLI_STRUCT)&pAd->ApCfg.ApCliTab; + + for(apcliIndex = 0; apcliIndex < MAX_APCLI_NUM; apcliIndex++) + { + if (pApCli[apcliIndex].Valid != TRUE) + continue; + + /* find the device in our ApCli list */ + if (pApCli[apcliIndex].dev == dev_p) + { + /* ya! find it */ + pAd->RalinkCounters.PendingNdisPacketCount ++; + RTMP_SET_PACKET_SOURCE(skb_p, PKTSRC_NDIS); + RTMP_SET_PACKET_MOREDATA(skb_p, FALSE); + RTMP_SET_PACKET_NET_DEVICE_APCLI(skb_p, apcliIndex); + SET_OS_PKT_NETDEV(skb_p, pAd->net_dev); + + + /* transmit the packet */ + return Func(skb_p); + } + } + + RELEASE_NDIS_PACKET(pAd, skb_p, NDIS_STATUS_FAILURE); + + return 0; +} + +#ifdef APCLI_AUTO_CONNECT_SUPPORT +/* + =================================================== + + 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; + + DBGPRINT(RT_DEBUG_TRACE, ("---> ApCliAutoConnectExec()\n")); + + ifIdx = pObj->ioctl_if; + CfgSsidLen = pAd->ApCfg.ApCliTab[ifIdx].CfgSsidLen; + pCfgSsid = pAd->ApCfg.ApCliTab[ifIdx].CfgSsid; + pScanTab = &pAd->ScanTab; + pSsidBssTab = &pAd->MlmeAux.SsidBssTab; + pSsidBssTab->BssNr = 0; + + /* + Find out APs with the desired SSID. + */ + for (entryIdx=0; entryIdxBssNr;entryIdx++) + { + PBSS_ENTRY pBssEntry = &pScanTab->BssEntry[entryIdx]; + + if ( pBssEntry->Channel == 0) + break; + + if (NdisEqualMemory(pCfgSsid, pBssEntry->Ssid, CfgSsidLen) && + (pBssEntry->SsidLen) && + (pSsidBssTab->BssNr < MAX_LEN_OF_BSS_TABLE)) + { + 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(apcli%d) ApCliAutoConnectExec:(Len=%d,Ssid=%s, Channel=%d, Rssi=%d)\n", + ifIdx, pBssEntry->SsidLen, pBssEntry->Ssid, + pBssEntry->Channel, pBssEntry->Rssi)); + DBGPRINT(RT_DEBUG_TRACE, + ("I/F(apcli%d) ApCliAutoConnectExec::(AuthMode=%s, EncrypType=%s)\n", ifIdx, + GetAuthMode(pBssEntry->AuthMode), + GetEncryptType(pBssEntry->WepStatus)) ); + 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 tempBuf[20]; + if (pAd->CommonCfg.Channel != pSsidBssTab->BssEntry[pSsidBssTab->BssNr -1].Channel) + { + sprintf(tempBuf, "%d", pSsidBssTab->BssEntry[pSsidBssTab->BssNr -1].Channel); + DBGPRINT(RT_DEBUG_TRACE, ("Switch to channel :%s\n", tempBuf)); + Set_Channel_Proc(pAd, tempBuf); + } + sprintf(tempBuf, "%02X:%02X:%02X:%02X:%02X:%02X", + pSsidBssTab->BssEntry[pSsidBssTab->BssNr -1].Bssid[0], + pSsidBssTab->BssEntry[pSsidBssTab->BssNr -1].Bssid[1], + pSsidBssTab->BssEntry[pSsidBssTab->BssNr -1].Bssid[2], + pSsidBssTab->BssEntry[pSsidBssTab->BssNr -1].Bssid[3], + pSsidBssTab->BssEntry[pSsidBssTab->BssNr -1].Bssid[4], + pSsidBssTab->BssEntry[pSsidBssTab->BssNr -1].Bssid[5]); + Set_ApCli_Bssid_Proc(pAd, tempBuf); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Error! Out of table range: (BssNr=%d).\n", pSsidBssTab->BssNr) ); + Set_ApCli_Enable_Proc(pAd, "1"); + pAd->ApCfg.ApCliAutoConnectRunning = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("<--- ApCliAutoConnectExec()\n")); + return FALSE; + } + + Set_ApCli_Enable_Proc(pAd, "1"); + 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) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + BSS_TABLE *pSsidBssTab; + PAPCLI_STRUCT pApCliEntry; + UCHAR lastEntryIdx, ifIdx = pObj->ioctl_if; + + + DBGPRINT(RT_DEBUG_TRACE, ("---> ApCliSwitchCandidateAP()\n")); + pSsidBssTab = &pAd->MlmeAux.SsidBssTab; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIdx]; + + /* + 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 tempBuf[20]; + + sprintf(tempBuf, "%02X:%02X:%02X:%02X:%02X:%02X", + pSsidBssTab->BssEntry[lastEntryIdx].Bssid[0], + pSsidBssTab->BssEntry[lastEntryIdx].Bssid[1], + pSsidBssTab->BssEntry[lastEntryIdx].Bssid[2], + pSsidBssTab->BssEntry[lastEntryIdx].Bssid[3], + pSsidBssTab->BssEntry[lastEntryIdx].Bssid[4], + pSsidBssTab->BssEntry[lastEntryIdx].Bssid[5]); + Set_ApCli_Bssid_Proc(pAd, tempBuf); + if (pAd->CommonCfg.Channel != pSsidBssTab->BssEntry[lastEntryIdx].Channel) + { + Set_ApCli_Enable_Proc(pAd, "0"); + sprintf(tempBuf, "%d", pSsidBssTab->BssEntry[lastEntryIdx].Channel); + DBGPRINT(RT_DEBUG_TRACE, ("Switch to channel :%s\n", tempBuf)); + Set_Channel_Proc(pAd, tempBuf); + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("No candidate AP, the process is about to stop.\n")); + pAd->ApCfg.ApCliAutoConnectRunning = FALSE; + } + + Set_ApCli_Enable_Proc(pAd, "1"); + 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->AuthMode; + NDIS_802_11_WEP_STATUS tempWEPstatus = pApCliEntry->WepStatus; + + DBGPRINT(RT_DEBUG_TRACE, ("ApcliAuthMode=%s, AuthMode=%s, AuthModeAux=%s, ApcliWepStatus=%s, WepStatus=%s, GroupCipher=%s, PairCipher=%s, \n", + GetAuthMode(pApCliEntry->AuthMode), + GetAuthMode(AuthMode), + GetAuthMode(AuthModeAux), + GetEncryptType(pApCliEntry->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; + } + +} +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + diff --git a/mt7620/src/ap/ap_apcli_inf.c b/mt7620/src/ap/ap_apcli_inf.c new file mode 100644 index 0000000..75f27e8 --- /dev/null +++ b/mt7620/src/ap/ap_apcli_inf.c @@ -0,0 +1,266 @@ +/* + *************************************************************************** + * 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 + MBSS_VirtualIF_PacketSend() by using RTMP_SET_PACKET_NET_DEVICE_MBSSID() + 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" + + +/* +======================================================================== +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( + IN VOID *pAd, + IN 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 = ApCli_VirtualIF_PacketSend; + netDevOpHook.ioctl = ApCli_VirtualIF_Ioctl; + 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( + IN PNET_DEV dev_p) +{ +/* UCHAR ifIndex; */ + 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; +} /* End of ApCli_VirtualIF_Open */ + + +/* +======================================================================== +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( + IN PNET_DEV dev_p) +{ +/* UCHAR ifIndex; */ + 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; +} /* End of ApCli_VirtualIF_Close */ + + +/* +======================================================================== +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 ApCli_VirtualIF_PacketSend( + IN PNDIS_PACKET pPktSrc, + IN PNET_DEV pDev) +{ + + MEM_DBG_PKT_ALLOC_INC(pPktSrc); + + if(!(RTMP_OS_NETDEV_STATE_RUNNING(pDev))) + { + /* the interface is down */ + RELEASE_NDIS_PACKET(NULL, pPktSrc, NDIS_STATUS_FAILURE); + return 0; + } /* End of if */ + + return APC_PacketSend(pPktSrc, pDev, rt28xx_packet_xmit); +} /* End of ApCli_VirtualIF_PacketSend */ + + +/* +======================================================================== +Routine Description: + IOCTL to WLAN. + +Arguments: + dev_p which WLAN network interface + rq_p command information + cmd command ID + +Return Value: + 0: IOCTL successfully + otherwise: IOCTL fail + +Note: + SIOCETHTOOL 8946 New drivers use this ETHTOOL interface to + report link failure activity. +======================================================================== +*/ +INT ApCli_VirtualIF_Ioctl( + IN PNET_DEV dev_p, + IN OUT VOID *rq_p, + IN INT cmd) +{ + VOID *pAd; + + pAd = RTMP_OS_NETDEV_GET_PRIV(dev_p); + ASSERT(pAd); + +/* if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + return -ENETDOWN; + + /* do real IOCTL */ + return (rt28xx_ioctl(dev_p, rq_p, cmd)); +} /* End of ApCli_VirtualIF_Ioctl */ + + +/* +======================================================================== +Routine Description: + Remove ApCli-BSS network interface. + +Arguments: + pAd points to our adapter + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RT28xx_ApCli_Remove( + IN VOID *pAd) +{ +/* UINT index; */ + + + RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_APC_REMOVE, 0, NULL, 0); + + +} + +#endif /* APCLI_SUPPORT */ diff --git a/mt7620/src/ap/ap_assoc.c b/mt7620/src/ap/ap_assoc.c new file mode 100644 index 0000000..dc9345b --- /dev/null +++ b/mt7620/src/ap/ap_assoc.c @@ -0,0 +1,1862 @@ +/**************************************************************************** + * 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" + +static void ap_assoc_info_debugshow( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN isReassoc, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR HTCapability_Len, + IN HT_CAPABILITY_IE *pHTCapability); + + +/* + ========================================================================== + 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 PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + 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); */ +} + +/* 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; + + +#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( + IN PRTMP_ADAPTER pAd, + IN UINT8 *mac_p, + IN INT bssid) +{ + + NDIS_PACKET *pNetBuf; + + pNetBuf = RtmpOsPktIappMakeUp(get_netdev_from_bssid(pAd, bssid), mac_p); + 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_p, 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) +{ + UCHAR ApAddr[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; + HEADER_802_11 AssocRspHdr; + USHORT ListenInterval; + USHORT CapabilityInfo; + USHORT CapabilityInfoForAssocResp; + USHORT StatusCode = MLME_SUCCESS; + USHORT Aid; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + char Ssid[MAX_LEN_OF_SSID]; + UCHAR SsidLen;/*, HtLen, AddHtLen; */ + UCHAR SupportedRatesLen; + UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR MaxSupportedRate = 0; + UCHAR i; + MAC_TABLE_ENTRY *pEntry; + UCHAR RSNIE_Len; +/* UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; */ + UCHAR *RSN_IE = NULL; + BOOLEAN bWmmCapable; + ULONG RalinkIe; + HT_CAPABILITY_IE HTCapability; + UCHAR HTCapability_Len; +#ifdef DBG + UCHAR *sAssoc = isReassoc ? (PUCHAR)"ReASSOC" : (PUCHAR)"ASSOC"; +#endif /* DBG */ + UCHAR SubType; +#ifdef WSC_AP_SUPPORT + BOOLEAN bWscCapable = FALSE; +#endif /* WSC_AP_SUPPORT */ + BOOLEAN bACLReject = FALSE; +#ifdef DOT1X_SUPPORT + PUINT8 pPmkid = NULL; + UINT8 pmkid_count = 0; +#endif /* DOT1X_SUPPORT */ +#ifdef P2P_SUPPORT + ULONG P2PSubelementLen = 0; + UCHAR *P2pSubelement; +#endif /* P2P_SUPPORT */ + EXT_CAP_INFO_ELEMENT ExtCapInfo; + UCHAR SupRateLen, PhyMode, FlgIs11bSta; + + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&RSN_IE, MAX_LEN_OF_RSNIE); + if (RSN_IE == NULL) + return; + + NdisZeroMemory(&ExtCapInfo, sizeof(EXT_CAP_INFO_ELEMENT)); + RTMPZeroMemory(&HTCapability, sizeof(HT_CAPABILITY_IE)); + +#ifdef P2P_SUPPORT + os_alloc_mem(NULL, (UCHAR **)&P2pSubelement, MAX_VIE_LEN); +#endif /* P2P_SUPPORT */ + /* 1. frame sanity check */ +#ifdef WSC_AP_SUPPORT + if (! PeerAssocReqCmmSanity(pAd, isReassoc, Elem->Msg, Elem->MsgLen, Addr2, + &CapabilityInfo, &ListenInterval, ApAddr, &SsidLen, &Ssid[0], + &SupportedRatesLen, &SupportedRates[0],RSN_IE, + &RSNIE_Len, &bWmmCapable, &bWscCapable, &RalinkIe, + &ExtCapInfo, +#ifdef P2P_SUPPORT + &P2PSubelementLen, + P2pSubelement, +#endif /* P2P_SUPPORT */ + &HTCapability_Len, &HTCapability)) +#else /* WSC_AP_SUPPORT */ + if (! PeerAssocReqCmmSanity(pAd, isReassoc, Elem->Msg, Elem->MsgLen, Addr2, + &CapabilityInfo, &ListenInterval, ApAddr, &SsidLen, &Ssid[0], + &SupportedRatesLen, &SupportedRates[0],RSN_IE, + &RSNIE_Len, &bWmmCapable, &RalinkIe, + &ExtCapInfo, +#ifdef P2P_SUPPORT + &P2PSubelementLen, + P2pSubelement, +#endif /* P2P_SUPPORT */ + &HTCapability_Len, &HTCapability)) +#endif /* WSC_AP_SUPPORT */ + goto LabelOK; + + /* check if AP address is same as us */ + /* TODO */ + /* goto label_err; */ + + pEntry = MacTableLookup(pAd, Addr2); + if (!pEntry) { + DBGPRINT(RT_DEBUG_ERROR, ("NoAuth MAC - %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(Addr2))); + goto LabelOK; + } + + PhyMode = pAd->ApCfg.MBSSID[pEntry->apidx].PhyMode; + + FlgIs11bSta = 1; + for(i=0; iAid != 0 && + (pEntry->WepStatus >= Ndis802_11Encryption2Enabled +#ifdef DOT1X_SUPPORT + || pAd->ApCfg.MBSSID[pEntry->apidx].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->Aid); + +#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].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 = bWscCapable; +#ifdef WSC_V2_SUPPORT + if ((pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscV2Info.bEnableWpsV2) && + (pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscV2Info.bWpsEnable == FALSE)) + ; + else +#endif /* WSC_V2_SUPPORT */ + { + if (pEntry->apidx < pAd->ApCfg.BssidNum) + { + if (MAC_ADDR_EQUAL(pEntry->Addr, pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EntryAddr)) + { + BOOLEAN Cancelled; + RTMPZeroMemory(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; + } + } + + if ((RSNIE_Len == 0) && + (pAd->ApCfg.MBSSID[pEntry->apidx].AuthMode >= Ndis802_11AuthModeWPA) && + (pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscConfMode != WSC_DISABLE)) + pEntry->bWscCapable = TRUE; + } +#endif /* WSC_AP_SUPPORT */ + +#ifdef EASY_CONFIG_SETUP + if (pEntry->bRaAutoWpsCapable) + ; + else +#endif /* EASY_CONFIG_SETUP */ + /* for hidden SSID sake, SSID in AssociateRequest should be fully verified */ + if ((SsidLen != pAd->ApCfg.MBSSID[pEntry->apidx].SsidLen) || + (NdisEqualMemory(Ssid, pAd->ApCfg.MBSSID[pEntry->apidx].Ssid, 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) && + (pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscConfMode != WSC_DISABLE) && + (pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscV2Info.bEnableWpsV2) && + (pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscV2Info.bWpsEnable) && + (MAC_ADDR_EQUAL(pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EntryAddr, ZERO_MAC_ADDR))) + ; + else +#endif /* WSC_V2_SUPPORT */ + /* set a flag for sending Assoc-Fail response to unwanted STA later. */ + if (! ApCheckAccessControlList(pAd, 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(Addr2))); + + /* supported rates array may not be sorted. sort it and find the maximum rate */ + for (i=0; iRateLen = SupportedRatesLen; + + RTMPSetSupportMCS(pAd, + OPMODE_AP, + pEntry, + SupportedRates, + SupportedRatesLen, + NULL, + 0, + &HTCapability, + HTCapability_Len); + + /* 2. qualify this STA's auth_asoc status in the MAC table, decide StatusCode */ + StatusCode = APBuildAssociation(pAd, pEntry, CapabilityInfo, MaxSupportedRate, + RSN_IE, &RSNIE_Len, bWmmCapable, RalinkIe, + ExtCapInfo, + &HTCapability, &HTCapability_Len, &Aid); + + + + + if (StatusCode == MLME_ASSOC_REJ_DATA_RATE) + RTMPSendWirelessEvent(pAd, IW_STA_MODE_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); + + + /* 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 = pAd->ApCfg.MBSSID[pEntry->apidx].CapabilityInfo; /*use AP's cability */ +#ifdef WSC_AP_SUPPORT +#ifdef WSC_V2_SUPPORT + if ((pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscV2Info.bEnableWpsV2) && + (pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscV2Info.bWpsEnable == FALSE)) + ; + else +#endif /* WSC_V2_SUPPORT */ + { + if ((pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscConfMode != WSC_DISABLE) && + (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; + + if (bACLReject == TRUE) + { + MgtMacHeaderInit(pAd, &AssocRspHdr, SubType, 0, Addr2, +#ifdef P2P_SUPPORT + pAd->ApCfg.MBSSID[pEntry->apidx].Bssid, +#endif /* P2P_SUPPORT */ + pAd->ApCfg.MBSSID[pEntry->apidx].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); + MlmeFreeMemory(pAd, (PVOID) pOutBuffer); + + RTMPSendWirelessEvent(pAd, IW_MAC_FILTER_LIST_EVENT_FLAG, Addr2, pEntry->apidx, 0); + +#ifdef WSC_V2_SUPPORT + /* If this STA exists, delete it. */ + if (pEntry) + MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr); +#endif /* WSC_V2_SUPPORT */ + + goto LabelOK; + } + + MgtMacHeaderInit(pAd, &AssocRspHdr, SubType, 0, Addr2, +#ifdef P2P_SUPPORT + pAd->ApCfg.MBSSID[pEntry->apidx].Bssid, +#endif /* P2P_SUPPORT */ + pAd->ApCfg.MBSSID[pEntry->apidx].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 != PHY_11B) && (FlgIs11bSta == 0)) + { + /* The ERPIE should not be included in association response, so remove it. */ +/* UCHAR ErpIeLen = 1; */ + ULONG TmpLen; + 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; + } /* add WMM IE here */ + + + + /* add WMM IE here */ + if (pAd->ApCfg.MBSSID[pEntry->apidx].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], &pAd->ApCfg.MBSSID[pEntry->apidx].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 DOT11_N_SUPPORT + /* HT capability in AssocRsp frame. */ + if ((HTCapability_Len > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + ULONG TmpLen; + UCHAR HtLen1; + /*UCHAR SupportedMCSSet[16]; */ + /*UCHAR mode, bitmask; */ + HT_CAPABILITY_IE HtCapabilityRsp; + + + NdisMoveMemory(&HtCapabilityRsp, &pAd->CommonCfg.HtCapability, HTCapability_Len); + /*NdisMoveMemory(&HtCapabilityRsp.MCSSet[0], &SupportedMCSSet[0], sizeof(SupportedMCSSet)); */ + +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; + ADD_HT_INFO_IE addHTInfoTmp; +#endif + /* add HT Capability IE */ + HtLen1 = sizeof(pAd->CommonCfg.AddHTInfo); + +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &HTCapability_Len, + HTCapability_Len, &HtCapabilityRsp, + 1, &AddHtInfoIe, + 1, &HtLen1, + HtLen1, &pAd->CommonCfg.AddHTInfo, + END_OF_ARGS); +#else + NdisMoveMemory(&HtCapabilityTmp, &HtCapabilityRsp, HTCapability_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, &HTCapability_Len, + HTCapability_Len, &HtCapabilityTmp, + 1, &AddHtInfoIe, + 1, &HtLen1, + HtLen1, &addHTInfoTmp, + END_OF_ARGS); +#endif + FrameLen += TmpLen; + + if ((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 = HTCapability_Len + 4; +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_HTC[0], + HTCapability_Len, &HtCapabilityRsp, + END_OF_ARGS); +#else + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_HTC[0], + HTCapability_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 ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && + (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 */ + } +#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 ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->CommonCfg.Channel <= 14) + && (pAd->CommonCfg.bBssCoexEnable == TRUE) + ) + { + extCapInfo.BssCoexistMgmtSupport = 1; + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + + pInfo = (PUCHAR)(&extCapInfo); + for (infoPos = 0; infoPos < extInfoLen; infoPos++) + { + if (pInfo[infoPos] != 0) + { + bNeedAppendExtIE = TRUE; + break; + } + } + + if (bNeedAppendExtIE == TRUE) + { + 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 */ + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkSpecificIe, + END_OF_ARGS); + FrameLen += TmpLen; + +#ifdef RT3883 + if (IS_RT3883(pAd)) + FrameLen += RT3883_ext_pkt_len(pOutBuffer, FrameLen, RalinkSpecificIe, 9); +#endif // RT3883 // +} + +#ifdef EASY_CONFIG_SETUP + if (pEntry->bRaAutoWpsCapable) + AutoProvisionBuildAssocRspIE(pAd, Elem, pEntry, pOutBuffer, &FrameLen); +#endif /* EASY_CONFIG_SETUP */ +#ifdef WSC_AP_SUPPORT + if (pEntry->bWscCapable) + { + UCHAR *pWscBuf = NULL, WscIeLen = 0; + ULONG WscTmpLen = 0; + + 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 */ + +#ifdef P2P_SUPPORT + if (P2PSubelementLen > 0) + { + ULONG TmpLen; + UCHAR P2pIdx = P2P_NOT_FOUND; + UCHAR GroupCap = 0xff, DeviceCap = 0xff, DevAddr[6] = {0}, DeviceType[8], DeviceName[32], DeviceNameLen = 0; + PUCHAR pData; + USHORT Dpid, ConfigMethod; + + pEntry->bP2pClient = TRUE; + pEntry->P2pInfo.P2pClientState = P2PSTATE_CLIENT_ASSOC; + P2pParseSubElmt(pAd, (PVOID)P2pSubelement, P2PSubelementLen, FALSE, &Dpid, &GroupCap, + &DeviceCap, DeviceName, &DeviceNameLen, DevAddr, NULL, NULL, NULL, NULL, &ConfigMethod, + &ConfigMethod, DeviceType, NULL, NULL, NULL, NULL, &StatusCode, NULL); + + P2pIdx = P2pGroupTabSearch(pAd, DevAddr); + if (P2pIdx == P2P_NOT_FOUND) + P2pIdx = P2pGroupTabInsert(pAd, DevAddr, P2PSTATE_DISCOVERY_CLIENT, NULL, 0, 0, 0); + + if (P2pIdx != P2P_NOT_FOUND) + { + pEntry->P2pInfo.p2pIndex = P2pIdx; + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC RSP - Insert P2P IE to %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pEntry->Addr))); + DBGPRINT(RT_DEBUG_TRACE, (" %d. DevAddr = %02x:%02x:%02x:%02x:%02x:%02x\n", P2pIdx, PRINT_MAC(DevAddr))); + DBGPRINT(RT_DEBUG_TRACE, ("DeviceNameLen = %d, DeviceName = %c %c %c %c %c %c %c %c\n", DeviceNameLen , + DeviceName[0], DeviceName[1], DeviceName[2], DeviceName[3], + DeviceName[4], DeviceName[5], DeviceName[6], DeviceName[7])); + + /* update P2P Interface Address */ + RTMPMoveMemory(pAd->P2pTable.Client[P2pIdx].InterfaceAddr, pEntry->Addr, MAC_ADDR_LEN); + + pData = pOutBuffer + FrameLen; + P2pMakeP2pIE(pAd, SUBTYPE_ASSOC_RSP, pData, &TmpLen); + FrameLen += TmpLen; + } + } + else + pEntry->bP2pClient = FALSE; +#endif /* P2P_SUPPORT */ + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, (PVOID) pOutBuffer); + + + /* set up BA session */ + if (StatusCode == MLME_SUCCESS) + { + pEntry->PsMode = PWR_ACTIVE; + +#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", + pEntry->Addr[0], + pEntry->Addr[1], + pEntry->Addr[2], + pEntry->Addr[3], + pEntry->Addr[4], + pEntry->Addr[5])); + +/* SendSingalToDaemon(SIGUSR2, pObj->IappPid); */ + + +#endif /* IAPP_SUPPORT */ + + ap_assoc_info_debugshow(pAd, isReassoc, pEntry, HTCapability_Len, &HTCapability); + + /* send wireless event - for association */ + RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, pEntry->Addr, 0, 0); + + /* 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 && (HTCapability.HtCapInfo.ChannelWidth==BW_40)) + { + SendBeaconRequest(pAd, pEntry->Aid); + } + /*BAOriSessionSetUp(pAd, pEntry, 0, 0, 3000, FALSE); */ + } +#endif /* DOT11_N_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 || (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(pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.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 + && pAd->ApCfg.MBSSID[pEntry->apidx].Hostapd == FALSE +#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(RSN_IE, RSNIE_Len, PMKID_LIST, &pmkid_count)) != NULL)) + { /* Key cache */ + INT CacheIdx; + + if (((CacheIdx = RTMPSearchPMKIDCache(pAd, pEntry->apidx, pEntry->Addr)) != -1) + && (RTMPEqualMemory(pPmkid, &pAd->ApCfg.MBSSID[pEntry->apidx].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 + && pAd->ApCfg.MBSSID[pEntry->apidx].Hostapd == FALSE +#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) || + ( +#ifdef WSC_AP_SUPPORT + (!pEntry->bWscCapable) && +#endif /* WSC_AP_SUPPORT */ + (pAd->ApCfg.MBSSID[pEntry->apidx].IEEE8021X))) + { + /* Enqueue a EAPOL-start message to trigger EAP SM */ + if (pEntry->EnqueueEapolStartTimerRunning == EAPOL_START_DISABLE +#ifdef HOSTAPD_SUPPORT + && pAd->ApCfg.MBSSID[pEntry->apidx].Hostapd == FALSE +#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 = pAd->ApCfg.MBSSID[pEntry->apidx].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->Aid, + SHAREDKEYTABLE); + } + } + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + /* Usually we don't need to send this action frame out */ +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + } + +LabelOK: + if (RSN_IE != NULL) + os_free_mem(NULL, RSN_IE); +#ifdef P2P_SUPPORT + if (P2pSubelement != NULL) + os_free_mem(NULL, P2pSubelement); +#endif /* P2P_SUPPORT */ + + return; + +/*label_err: */ +/* 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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + USHORT Reason; + UINT16 SeqNum; + MAC_TABLE_ENTRY *pEntry; + + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - 1 receive DIS-ASSOC request \n")); + if (! PeerDisassocReqSanity(pAd, Elem->Msg, Elem->MsgLen, 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, Addr2[0],Addr2[1],Addr2[2],Addr2[3],Addr2[4],Addr2[5],Reason)); + + pEntry = MacTableLookup(pAd, Addr2); + + if (pEntry == NULL) + return; + + if (Elem->Wcid < MAX_LEN_OF_MAC_TABLE) + { +#ifdef DPA_S +#ifdef P2P_SUPPORT + UCHAR p2pIndex = P2P_NOT_FOUND; +#endif /* P2P_SUPPORT */ +#endif /* DPA_S */ + +#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].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); + +#ifdef DPA_S +#ifdef P2P_SUPPORT + p2pIndex = P2pGroupTabSearch(pAd, Addr2); + if (p2pIndex != P2P_NOT_FOUND) + { + PRT_P2P_CLIENT_ENTRY pP2pEntry = &pAd->P2pTable.Client[p2pIndex]; + P2pSendSamsungEvent(pAd, P2P_NOTIF_SOFTAP_STA_DISASSOC, Addr2, pP2pEntry->DeviceName, pP2pEntry->DeviceNameLen); + } + else + P2pSendSamsungEvent(pAd, P2P_NOTIF_SOFTAP_STA_DISASSOC, Addr2, NULL, 0); +#endif /* P2P_SUPPORT */ +#endif /* DPA_S */ + MacTableDeleteEntry(pAd, Elem->Wcid, Addr2); + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn == TRUE) + { + UCHAR apCliIdx, CliIdx; + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; + + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, TRUE, Addr2); + if (pReptEntry && (pReptEntry->CliConnectState != 0)) + { + 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); + RTMPRemoveRepeaterEntry(pAd, apCliIdx, CliIdx); + } + } +#endif /* MAC_REPEATER_SUPPORT */ + } +} + +/* + ========================================================================== + Description: + delete it from STA and disassoc s STA + Parameters: + Elem - + ========================================================================== + */ +VOID MbssKickOutStas( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN 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->Aid, Reason); + } + + return; +} + +/* + ========================================================================== + Description: + delete it from STA and disassoc s STA + Parameters: + Elem - + ========================================================================== + */ +VOID APMlmeKickOutSta( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pStaAddr, + IN UCHAR Wcid, + IN 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", + pStaAddr[0],pStaAddr[1],pStaAddr[2], pStaAddr[3],pStaAddr[4],pStaAddr[5])); + MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pStaAddr, +#ifdef P2P_SUPPORT + pAd->ApCfg.MBSSID[ApIdx].Bssid, +#endif /* P2P_SUPPORT */ + pAd->ApCfg.MBSSID[ApIdx].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); + } +} + + + + +/* + ========================================================================== + Description: + Upper layer orders to disassoc s STA + Parameters: + Elem - + ========================================================================== + */ +VOID APMlmeDisassocReqAction( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN PHEADER_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->Aid, 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, +#ifdef P2P_SUPPORT + pHeader->Addr1, +#endif /* P2P_SUPPORT */ + pHeader->Addr1); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DisassocHdr, + 2, &Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +} + +/* + ========================================================================== + 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 + ========================================================================== + */ +USHORT APBuildAssociation( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN USHORT CapabilityInfo, + IN UCHAR MaxSupportedRateIn500Kbps, + IN UCHAR *RSN, + IN UCHAR *pRSNLen, + IN BOOLEAN bWmmCapable, + IN ULONG ClientRalinkIe, + IN EXT_CAP_INFO_ELEMENT ExtCapInfo, + IN HT_CAPABILITY_IE *pHtCapability, + OUT UCHAR *pHtCapabilityLen, + OUT USHORT *pAid) +{ + USHORT StatusCode = MLME_SUCCESS; + UCHAR MaxSupportedRate = RATE_11; +#ifdef TXBF_SUPPORT + BOOLEAN supportsETxBF = FALSE; +#endif // TXBF_SUPPORT // + +/* UCHAR CipherAlg; */ +/* UCHAR KeyIdx; */ +#ifdef HOSTAPD_SUPPORT + UCHAR Addr[6]; + NdisMoveMemory(Addr,pEntry->Addr,MAC_ADDR_LENGTH); +#endif /*HOSTAPD_SUPPORT*/ + 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; + } + + if (((pAd->CommonCfg.PhyMode == PHY_11G) +#ifdef DOT11_N_SUPPORT + || (pAd->CommonCfg.PhyMode == PHY_11GN_MIXED) +#endif /* DOT11_N_SUPPORT */ + ) + && (MaxSupportedRate < RATE_FIRST_OFDM_RATE)) + return MLME_ASSOC_REJ_DATA_RATE; + +#ifdef DOT11_N_SUPPORT + /* 11n only */ + if (((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G))&& (*pHtCapabilityLen == 0)) + return MLME_ASSOC_REJ_DATA_RATE; +#endif /* DOT11_N_SUPPORT */ + + 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 = APAssignAid(pAd, pEntry); */ + /*pEntry->Aid = *pAid; */ + *pAid = pEntry->Aid; + pEntry->NoDataIdleCount = 0; + pEntry->StaConnectTime = 0; + +#ifdef WSC_AP_SUPPORT + if (pEntry->bWscCapable == FALSE) +#endif /* WSC_AP_SUPPORT */ + { + /* check the validity of the received RSNIE */ + if ((StatusCode = APValidateRSNIE(pAd, pEntry, RSN, *pRSNLen)) != MLME_SUCCESS) + return StatusCode; + } + + NdisMoveMemory(pEntry->RSN_IE, RSN, *pRSNLen); + pEntry->RSNIE_Len = *pRSNLen; + + + if (*pAid == 0) + StatusCode = MLME_ASSOC_REJ_UNABLE_HANDLE_STA; + else if ((pEntry->RSNIE_Len == 0) && (pAd->ApCfg.MBSSID[pEntry->apidx].AuthMode >= Ndis802_11AuthModeWPA) +#ifdef HOSTAPD_SUPPORT + && pAd->ApCfg.MBSSID[pEntry->apidx].Hostapd == TRUE +#endif + ) + { +#ifdef WSC_AP_SUPPORT + if (((pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscConfMode != WSC_DISABLE) && + pEntry->bWscCapable +#ifdef WSC_V2_SUPPORT + && (pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscV2Info.bWpsEnable || + (pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscV2Info.bEnableWpsV2 == FALSE)) +#endif /* WSC_V2_SUPPORT */ + ) +#ifdef HOSTAPD_SUPPORT + || pAd->ApCfg.MBSSID[pEntry->apidx].Hostapd == TRUE +#endif /*HOSTAPD_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 + || (pAd->ApCfg.MBSSID[pEntry->apidx].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) + || (pAd->ApCfg.MBSSID[pEntry->apidx].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", + pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscConfMode, + pEntry->apidx)); + StatusCode = MLME_ASSOC_DENY_OUT_SCOPE; + } +#else /* WSC_AP_SUPPORT */ + StatusCode = MLME_ASSOC_DENY_OUT_SCOPE; +#endif /* WSC_AP_SUPPORT */ + +#ifdef HOSTAPD_SUPPORT + if(pAd->ApCfg.MBSSID[pEntry->apidx].Hostapd == TRUE + && (pAd->ApCfg.MBSSID[pEntry->apidx].AuthMode >= Ndis802_11AuthModeWPA + || pAd->ApCfg.MBSSID[pEntry->apidx].IEEE8021X)) + { + + RtmpOSWrielessEventSendExt(pAd->net_dev, RT_WLAN_EVENT_EXPIRED, -1, Addr, + NULL, 0, + ((pEntry->CapabilityInfo & 0x0010) == 0 ? 0xFFFD : 0xFFFC)); + } +#endif /*HOSTAPD_SUPPORT*/ + + } + else + { + /* Update auth, wep, legacy transmit rate setting . */ + pEntry->Sst = SST_ASSOC; + pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, 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->CapabilityInfo = 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) + || (pAd->ApCfg.MBSSID[pEntry->apidx].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 (ClientRalinkIe != 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) && (ClientRalinkIe & 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) && (ClientRalinkIe & 0x00000002)) + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE); + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC -PiggyBack= 1\n")); + } +#endif /* PIGGYBACK_SUPPORT */ + + /* In WPA or 802.1x mode, the port is not secured, otherwise is secued. */ + if ((pEntry->AuthMode >= Ndis802_11AuthModeWPA) +#ifdef DOT1X_SUPPORT + || (pAd->ApCfg.MBSSID[pEntry->apidx].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 */ + +#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 */ + *pHtCapabilityLen = 0; + DBGPRINT(RT_DEBUG_TRACE, ("%s : Force the STA as legacy mode(None-HT)\n", __FUNCTION__)); + } + + /* If this Entry supports 802.11n, upgrade to HT rate. */ + if ((*pHtCapabilityLen != 0) && + (pAd->ApCfg.MBSSID[pEntry->apidx].DesiredHtPhyInfo.bHtEnable) && + (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + UCHAR j, bitmask; /*k,bitmask; */ + CHAR i; + + if ((pHtCapability->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; + } +#ifdef DOT11N_DRAFT3 + if (ExtCapInfo.BssCoexistMgmtSupport) + pEntry->BSS2040CoexistenceMgmtSupport = 1; +#endif /* DOT11N_DRAFT3 */ + + /* 40Mhz BSS Width Trigger events */ + if (pHtCapability->HtCapInfo.Forty_Mhz_Intolerant) + { +#ifdef DOT11N_DRAFT3 + 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")); +#endif /* DOT11N_DRAFT3 */ + Handle_BSS_Width_Trigger_Events(pAd); + } + + 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; + } + +#ifdef TXBF_SUPPORT + supportsETxBF = clientSupportsETxBF(pAd, &pHtCapability->TxBFCap); +#endif /* TXBF_SUPPORT */ + + /* find max fixed rate */ +/* for (i=15; i>=0; i--) */ + for (i=23; i>=0; i--) /* 3*3 */ + { + j = i/8; + bitmask = (1<<(i-(j*8))); + if ((pAd->ApCfg.MBSSID[pEntry->apidx].DesiredHtPhyInfo.MCSSet[j] & bitmask) && (pHtCapability->MCSSet[j] & bitmask)) + { + pEntry->MaxHTPhyMode.field.MCS = i; + break; + } + if (i==0) + break; + } + + + if (pAd->ApCfg.MBSSID[pEntry->apidx].DesiredTransmitSetting.field.MCS != MCS_AUTO) + { + + DBGPRINT(RT_DEBUG_TRACE, ("@@@ IF-ra%d DesiredTransmitSetting.field.MCS = %d\n", pEntry->apidx, + pAd->ApCfg.MBSSID[pEntry->apidx].DesiredTransmitSetting.field.MCS)); + if (pAd->ApCfg.MBSSID[pEntry->apidx].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->ApCfg.MBSSID[pEntry->apidx].HTPhyMode.field.MCS) + { + /* STA supports fixed MCS */ + pEntry->MaxHTPhyMode.field.MCS = pAd->ApCfg.MBSSID[pEntry->apidx].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 (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); + if (pHtCapability->ExtHtCapInfo.MCSFeedback == 0x03) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); + + /* Record the received capability from association request */ + NdisMoveMemory(&pEntry->HTCapability, pHtCapability, sizeof(HT_CAPABILITY_IE)); + } + else + { + pAd->MacTab.fAnyStationIsLegacy = TRUE; + NdisZeroMemory(&pEntry->HTCapability, sizeof(HT_CAPABILITY_IE)); + } +#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); +#endif // TXBF_SUPPORT // + + // Initialize Rate Adaptation + MlmeRAInit(pAd, pEntry); + + /* Set asic auto fall back */ + if (pAd->ApCfg.MBSSID[pEntry->apidx].bAutoTxRateSwitch == TRUE) + { + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, pEntry, &pEntry->pTable, &TableSize, &pEntry->CurrTxRateIndex); + MlmeNewTxRate(pAd, pEntry); + + /* don't need to update these register */ + /*AsicUpdateAutoFallBackTable(pAd, pTable); */ + + 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.MODE = pAd->ApCfg.MBSSID[pEntry->apidx].HTPhyMode.field.MODE; */ + pEntry->HTPhyMode.field.MCS = pAd->ApCfg.MBSSID[pEntry->apidx].HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + + /* If the legacy mode is set, overwrite the transmit setting of this entry. */ + RTMPUpdateLegacyTxSetting((UCHAR)pAd->ApCfg.MBSSID[pEntry->apidx].DesiredTransmitSetting.field.FixedTxMode, pEntry); + + /* Use STA Capability */ +#ifdef MCS_LUT_SUPPORT + MlmeSetHwTxRateTable(pAd, pEntry); +#endif /* MCS_LUT_SUPPORT */ + + } + + 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; + + StatusCode = MLME_SUCCESS; + +#ifdef HOSTAPD_SUPPORT + if(pAd->ApCfg.MBSSID[pEntry->apidx].Hostapd == TRUE + && (pAd->ApCfg.MBSSID[pEntry->apidx].AuthMode >= Ndis802_11AuthModeWPA + || pAd->ApCfg.MBSSID[pEntry->apidx].IEEE8021X)) + { + + RtmpOSWrielessEventSendExt(pAd->net_dev, RT_WLAN_EVENT_EXPIRED, -1, Addr, + NULL, 0, + ((pEntry->CapabilityInfo & 0x0010) == 0 ? 0xFFFD : 0xFFFC)); + } +#endif /*HOSTAPD_SUPPORT*/ + } + } + 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) + { +#ifdef DPA_S +#ifdef P2P_SUPPORT + UCHAR p2pIndex = P2P_NOT_FOUND; +#endif /* P2P_SUPPORT */ +#endif /* DPA_S */ + if (bWmmCapable) + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + } + else + { + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + } +#ifdef DPA_S +#ifdef P2P_SUPPORT + p2pIndex = P2pGroupTabSearch(pAd, pEntry->Addr); + if (p2pIndex != P2P_NOT_FOUND) + { + PRT_P2P_CLIENT_ENTRY pP2pEntry = &pAd->P2pTable.Client[p2pIndex]; + P2pSendSamsungEvent(pAd, P2P_NOTIF_SOFTAP_STA_ASSOC, pEntry->Addr, pP2pEntry->DeviceName, pP2pEntry->DeviceNameLen); + } + else + P2pSendSamsungEvent(pAd, P2P_NOTIF_SOFTAP_STA_ASSOC, pEntry->Addr, NULL, 0); +#endif /* P2P_SUPPORT */ +#endif /* DPA_S */ + } + + return StatusCode; +} + +static void ap_assoc_info_debugshow( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN isReassoc, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR HTCapability_Len, + IN HT_CAPABILITY_IE *pHTCapability) +{ +#ifdef DBG + PUCHAR sAssoc = isReassoc ? (PUCHAR)"ReASSOC" : (PUCHAR)"ASSOC"; +#endif /* DBG */ + + + 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))); + + /*DBGPRINT(RT_DEBUG_TRACE, (HTCapability_Len ? "%s - 11n HT STA\n" : "%s - legacy STA\n", sAssoc)); */ +#ifdef DOT11_N_SUPPORT + if (HTCapability_Len && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + assoc_ht_info_debugshow(pAd, pEntry, HTCapability_Len, pHTCapability); + + 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 DOT11N_DRAFT3 + DBGPRINT(RT_DEBUG_TRACE, ("\tExt Cap Info: \n")); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tBss2040CoexistMgmt=%d\n", pEntry->BSS2040CoexistenceMgmtSupport)); +#endif /* DOT11N_DRAFT3 */ + } + 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, pAd->ApCfg.MBSSID[pEntry->apidx].GroupKeyWepStatus)); + + DBGPRINT(RT_DEBUG_TRACE, ("\tWMMCapable=%d, Legacy AGGRE=%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)); + +} + + diff --git a/mt7620/src/ap/ap_auth.c b/mt7620/src/ap/ap_auth.c new file mode 100644 index 0000000..4f7273e --- /dev/null +++ b/mt7620/src/ap/ap_auth.c @@ -0,0 +1,689 @@ +/**************************************************************************** + * 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" + +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); + +/* + ========================================================================== + 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", + pInfo->Addr[0], pInfo->Addr[1], pInfo->Addr[2], + pInfo->Addr[3], pInfo->Addr[4], pInfo->Addr[5])); + + MgtMacHeaderInit(pAd, &Hdr, SUBTYPE_DEAUTH, 0, pInfo->Addr, +#ifdef P2P_SUPPORT + pAd->ApCfg.MBSSID[apidx].Bssid, +#endif /* P2P_SUPPORT */ + pAd->ApCfg.MBSSID[apidx].Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr, + 2, &pInfo->Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + } +} + + +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]; + +#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].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; + } + + MacTableDeleteEntry(pAd, Elem->Wcid, Addr2); + + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - receive DE-AUTH(seq-%d) from " + "%02x:%02x:%02x:%02x:%02x:%02x, reason=%d\n", SeqNum, + Addr2[0], Addr2[1], Addr2[2], Addr2[3], Addr2[4], Addr2[5], Reason)); + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn == TRUE) + { + UCHAR apCliIdx, CliIdx; + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; + + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, TRUE, Addr2); + if (pReptEntry && (pReptEntry->CliConnectState != 0)) + { + 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); + RTMPRemoveRepeaterEntry(pAd, apCliIdx, CliIdx); + } + } +#endif /* MAC_REPEATER_SUPPORT */ + } +} + + +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 BAND_STEERING + BOOLEAN bAuthCheck = TRUE; +#endif /* BAND_STEERING */ + + + if (! APPeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr1, + Addr2, &Alg, &Seq, &Status, Chtxt + )) + return; + +#ifdef P2P_SUPPORT + if (P2P_GO_ON(pAd) && (pAd->P2pCfg.bStopAuthRsp == TRUE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s:: GO update not complete, stop Auth Rsp.\n", __FUNCTION__)); + return; + } +#endif /* P2P_SUPPORT */ + + /* Find which MBSSID to be authenticate */ + for (apidx=0; apidxApCfg.BssidNum; apidx++) + { + if (RTMPEqualMemory(Addr1, pAd->ApCfg.MBSSID[apidx].Bssid, MAC_ADDR_LEN)) + break; + } + + if (apidx >= pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Bssid not found\n")); + return; + } + + if ((pAd->ApCfg.MBSSID[apidx].MSSIDDev != NULL) && + !(RTMP_OS_NETDEV_STATE_RUNNING(pAd->ApCfg.MBSSID[apidx].MSSIDDev))) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Bssid IF didn't up yet.\n")); + return; + } /* End of if */ + + + pEntry = MacTableLookup(pAd, Addr2); + if (pEntry && IS_ENTRY_CLIENT(pEntry)) + { + + if (!RTMPEqualMemory(Addr1, pAd->ApCfg.MBSSID[pEntry->apidx].Bssid, MAC_ADDR_LEN)) + { + MacTableDeleteEntry(pAd, pEntry->Aid, 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->Aid); +#endif /* DOT11_N_SUPPORT */ + ASSERT(pEntry->Aid == Elem->Wcid); + } + } + + + 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))); + + +#ifdef WSC_V2_SUPPORT + /* Do not check ACL when WPS V2 is enabled and ACL policy is positive. */ + if ((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode != WSC_DISABLE) && + (pAd->ApCfg.MBSSID[apidx].WscControl.WscV2Info.bEnableWpsV2) && + (pAd->ApCfg.MBSSID[apidx].WscControl.WscV2Info.bWpsEnable) && + (pAd->ApCfg.MBSSID[apidx].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); + APPeerAuthSimpleRspGenAndSend(pAd, pRcvHdr, Alg, Seq + 1, MLME_UNSPECIFY_FAIL); + + /* 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); + + DBGPRINT(RT_DEBUG_TRACE, + ("Failed in ACL checking => send an AUTH seq#2 with " + "Status code = %d\n", MLME_UNSPECIFY_FAIL)); + return; + } + + +#ifdef BAND_STEERING + BND_STRG_CHECK_CONNECTION_REQ( pAd, + NULL, + Addr2, + Elem->MsgType, + Elem->Rssi0, + Elem->Rssi1, + Elem->Rssi2, + &bAuthCheck); + if (bAuthCheck == FALSE) + return; +#endif /* BAND_STEERING */ + + if ((Alg == AUTH_MODE_OPEN) && + (pAd->ApCfg.MBSSID[apidx].AuthMode != Ndis802_11AuthModeShared)) + { + if (!pEntry) + pEntry = MacTableInsertEntry(pAd, Addr2, apidx, OPMODE_AP, TRUE); + + if (pEntry) + { + { + pEntry->AuthState = AS_AUTH_OPEN; + pEntry->Sst = SST_AUTH; /* what if it already in SST_ASSOC ??????? */ + } + APPeerAuthSimpleRspGenAndSend(pAd, pRcvHdr, Alg, Seq + 1, MLME_SUCCESS); + +#ifdef WAC_SUPPORT + WAC_CheckWACEntry(pAd, pEntry); +#endif /* WAC_SUPPORT */ + } + else + ; /* MAC table full, what should we respond ????? */ + } + else if ((Alg == AUTH_MODE_KEY) && + ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeShared) + || (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeAutoSwitch))) + { + if (!pEntry) + pEntry = MacTableInsertEntry(pAd, Addr2, 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, +#ifdef P2P_SUPPORT + pAd->ApCfg.MBSSID[apidx].Bssid, +#endif /* P2P_SUPPORT */ + pAd->ApCfg.MBSSID[apidx].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); + 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); + + /* If this STA exists, delete it. */ + if (pEntry) + MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr); + + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Alg=%d, Seq=%d, AuthMode=%d\n", + Alg, Seq, pAd->ApCfg.MBSSID[apidx].AuthMode)); + } +} + + +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; + + + + + if (! APPeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr1, + Addr2, &Alg, &Seq, &Status, Chtxt + )) + return; + + for (apidx=0; apidxApCfg.BssidNum; apidx++) + { + if (RTMPEqualMemory(Addr1, pAd->ApCfg.MBSSID[apidx].Bssid, MAC_ADDR_LEN)) + break; + } + + if (apidx >= pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Bssid not found\n")); + return; + } + + if ((pAd->ApCfg.MBSSID[apidx].MSSIDDev != NULL) && + !(RTMP_OS_NETDEV_STATE_RUNNING(pAd->ApCfg.MBSSID[apidx].MSSIDDev))) + { + 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].Bssid, MAC_ADDR_LEN)) + { + MacTableDeleteEntry(pAd, pEntry->Aid, 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->Aid); +#endif /* DOT11_N_SUPPORT */ + ASSERT(pEntry->Aid == Elem->Wcid); + } + } + + 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)) + { + if ((pRcvHdr->FC.Wep == 1) && + NdisEqualMemory(Chtxt, pAd->ApMlmeAux.Challenge, CIPHER_TEXT_LEN)) + { + /* Successful */ + APPeerAuthSimpleRspGenAndSend(pAd, pRcvHdr, Alg, Seq + 1, MLME_SUCCESS); + 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); + MacTableDeleteEntry(pAd, pEntry->Aid, 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); + + /* If this STA exists, delete it. */ + if (pEntry) + MacTableDeleteEntry(pAd, pEntry->Aid, 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 PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN PHEADER_802_11 pHeader) +{ + HEADER_802_11 Hdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + USHORT Reason = REASON_CLS2ERR; + MAC_TABLE_ENTRY *pEntry = NULL; + + + 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->Aid, pHeader->Addr2); + } + else + { + UCHAR idx; + + for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++) + { + PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[idx]; + + if (NdisEqualMemory(pMbss->Bssid, pHeader->Addr1, MAC_ADDR_LEN)) + break; + } + + if (idx == pAd->ApCfg.BssidNum) + return; + } + + /* send out DEAUTH request 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, +#ifdef P2P_SUPPORT + pHeader->Addr1, +#endif /* P2P_SUPPORT */ + 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) +{ + 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, +#ifdef P2P_SUPPORT + pHdr->Addr1, +#endif /* P2P_SUPPORT */ + pHdr->Addr1); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &AuthHdr, + 2, &Alg, + 2, &Seq, + 2, &StatusCode, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +} + +/* End of ap_auth.c */ diff --git a/mt7620/src/ap/ap_autoChSel.c b/mt7620/src/ap/ap_autoChSel.c new file mode 100644 index 0000000..ef2aad7 --- /dev/null +++ b/mt7620/src/ap/ap_autoChSel.c @@ -0,0 +1,1136 @@ +/**************************************************************************** + * 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 INT Channel) +{ +#ifdef A_BAND_SUPPORT + 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; +} + +VOID UpdateChannelInfo( + IN PRTMP_ADAPTER pAd, + IN int ch_index, + IN ChannelSel_Alg Alg) +{ + if(pAd->pChannelInfo != NULL) + { + UINT32 BusyTime; + + if ( Alg == ChannelAlgCCA ) + { + 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; + } + + + /* + 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 */ + } + 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 && + !(pAd->ChannelList[i].Flags & CHANNEL_40M_CAP)) + continue; +#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 = FirstChannel(pAd); + } + + } + else + { + ch = pAd->ChannelList[RandomByte2(pAd)%pAd->ChannelListNum].Channel; + if (ch == 0) + ch = FirstChannel(pAd); + } + DBGPRINT(RT_DEBUG_TRACE,("%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 >= RSSI_TO_DBM_OFFSET-50) + { + /* high signal >= -50 dbm */ + pChannelInfo->dirtyness[channel_idx] += 50; + } + else if (pBss->Rssi <= RSSI_TO_DBM_OFFSET-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); + } + } + + DBGPRINT(RT_DEBUG_TRACE,(" 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); + + DBGPRINT(RT_DEBUG_TRACE, ("=====================================================\n")); + for (channel_idx = 0; channel_idx < pAd->ChannelListNum; channel_idx++) + { + DBGPRINT(RT_DEBUG_TRACE, ("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")); + } + DBGPRINT(RT_DEBUG_TRACE, ("=====================================================\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) + && (pChannelInfo->IsABand && (GetABandChOffset(ch) == 0))) + continue; + + /* + Need to Consider the dirtyness of extending channel + in 40 MHz bandwidth channel. + */ + if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + { + if (pAd->pChannelInfo->IsABand) + { + if (((channel_idx + GetABandChOffset(ch)) >=0) + && ((channel_idx + GetABandChOffset(ch)) < pAd->ChannelListNum)) + { + INT ChOffsetIdx = channel_idx + GetABandChOffset(ch); + dirtyness += pChannelInfo->dirtyness[ChOffsetIdx]; + } + } + else + { + 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; + DBGPRINT(RT_DEBUG_TRACE, ("Rule 1 CCA value : Min Dirtiness (Include extension channel) ==> Select Channel %d \n", ch)); + DBGPRINT(RT_DEBUG_TRACE, ("Min Dirty = %u\n", min_dirty)); + DBGPRINT(RT_DEBUG_TRACE, ("ExChannel = %d , %d\n", candidate_ExChannel[0], candidate_ExChannel[1])); + DBGPRINT(RT_DEBUG_TRACE, ("BW = %s\n", (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)? "40" : "20")); + 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) + && (pChannelInfo->IsABand && (GetABandChOffset(ch) == 0))) + continue; +#endif /* DOT11_N_SUPPORT */ + + if ((GetABandChOffset(ch) != 0) + && ((channel_idx + GetABandChOffset(ch)) >=0) + && ((channel_idx + GetABandChOffset(ch)) < pAd->ChannelListNum)) + { + INT ChOffsetIdx = channel_idx + GetABandChOffset(ch); + falsecca += (pChannelInfo->FalseCCA[ChOffsetIdx] + + pChannelInfo->dirtyness[ChOffsetIdx]); + } + +#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; + DBGPRINT(RT_DEBUG_TRACE, ("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; + + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("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) + { + 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; + } + } + } + } + /*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); + + DBGPRINT(RT_DEBUG_TRACE, ("=====================================================\n")); + for (channel_index=0 ; channel_index < pAd->ChannelListNum ; channel_index++) + /* debug messages */ + DBGPRINT(RT_DEBUG_TRACE, ("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")); + DBGPRINT(RT_DEBUG_TRACE, ("=====================================================\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 */ + + if (pChannelInfo->dirtyness[channel_index] == 0) break; + } + if (channel_index < pAd->ChannelListNum) + { + DBGPRINT(RT_DEBUG_TRACE,("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) + && (BW40_ChannelCheck(pAd->ChannelList[channel_index].Channel) == FALSE)) + continue; + + 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) + { + DBGPRINT(RT_DEBUG_TRACE,("Rule 2 APCnt : minimum APCnt with minimum interference(dirtiness: 30~32) ==> Select Channel %d\n", final_channel)); + DBGPRINT(RT_DEBUG_TRACE,(" 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->ApCfg.bAvoidDfsChannel == TRUE) + &&(pChannelInfo->IsABand == TRUE) + && RadarChannelCheck(pAd, final_channel)) + continue; + + break; + } + DBGPRINT(RT_DEBUG_TRACE,("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], pBssid, Ssid, SsidLen, + ChannelNo, ExtChOffset, Rssi); + pBssInfoTab->BssNr++; + } + else + { + AutoChBssEntrySet(&pBssInfoTab->BssEntry[Idx], pBssid, Ssid, SsidLen, + ChannelNo, ExtChOffset, Rssi); + } + + return Idx; +} + + +void AutoChBssTableInit( + IN PRTMP_ADAPTER pAd) +{ +/* pAd->pBssInfoTab = (PBSSINFO)kmalloc(sizeof(BSSINFO), GFP_ATOMIC); */ + 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) +{ +/* pAd->pChannelInfo = (PCHANNELINFO)kmalloc(sizeof(CHANNELINFO), GFP_ATOMIC); */ + 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) + { +/* kfree(pAd->pBssInfoTab); */ + os_free_mem(NULL, pAd->pBssInfoTab); + pAd->pBssInfoTab = NULL; + } + + return; +} + +void ChannelInfoDestroy( + IN PRTMP_ADAPTER pAd) +{ + if (pAd->pChannelInfo) + { +/* kfree(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( + IN PRTMP_ADAPTER pAd) +{ + + pAd->pChannelInfo->IsABand = ((pAd->CommonCfg.PhyMode == PHY_11A) + || (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) +#ifdef DOT11_N_SUPPORT + || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) + || (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) + || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) + || (pAd->CommonCfg.PhyMode == PHY_11N_5G) +#endif /* DOT11_N_SUPPORT */ + ) ? TRUE : FALSE; + + return; +} + + +UCHAR SelectBestChannel( + IN PRTMP_ADAPTER pAd, + IN ChannelSel_Alg Alg) +{ + UCHAR ch = 0; + + /* init pAd->pChannelInfo->IsABand */ + CheckPhyModeIsABand(pAd); + + 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(IN PRTMP_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( + IN PRTMP_ADAPTER pAd, + IN 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 + { + /*find RSSI in each channel */ + for (i=0; iChannelListNum; i++) + { + + 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 + if (QLOAD_DOES_ALARM_OCCUR(pAd)) + { /* QLOAD ALARM, ever alarm from QLOAD module */ + OS_WAIT(400); /* wait for 400 ms at each channel. */ + } + else +#endif /* AP_QLOAD_SUPPORT */ + { + OS_WAIT(200); /* wait for 200 ms at each channel. */ + } + + 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(IN PRTMP_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(): Channel Selection not checked because there are %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/mt7620/src/ap/ap_band_steering.c b/mt7620/src/ap/ap_band_steering.c new file mode 100644 index 0000000..852719c --- /dev/null +++ b/mt7620/src/ap/ap_band_steering.c @@ -0,0 +1,868 @@ +/* + *************************************************************************** + * 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); + + return TRUE; +} + + +INT Set_BndStrg_RssiCheck( + PRTMP_ADAPTER pAd, + PSTRING arg) +{ + CHAR RssiCheck = (CHAR) simple_strtol(arg, 0, 10); + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + + if (table->Ops) + table->Ops->SetRssiCheck(table, RssiCheck); + + table->RssiCheck = RssiCheck; + DBGPRINT(RT_DEBUG_OFF, + ("%s(): RssiCheck = %u\n", __FUNCTION__, table->RssiCheck)); + + 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; +} + + +#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 (PHY_MODE_IS_5G_BAND(pAd->CommonCfg.PhyMode)) + table->Band = BAND_5G; + else + table->Band = BAND_24G; + + BndStrg_SetInfFlags(pAd, table, TRUE); + + table->Ops = &D_BndStrgOps; + table->RssiCheck = BND_STRG_RSSI_CHECK; + 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->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); + 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_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; + + 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_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; +} + +INT BndStrg_CheckConnectionReq( + PRTMP_ADAPTER pAd, + PUCHAR pSrcAddr, + UINT8 FrameType, + PCHAR Rssi, + BOOLEAN *bAuthCheck) +{ + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + + if (table->Ops && (table->bEnabled == TRUE)) + { + table->Ops->CheckConnectionReq( + pAd, + pSrcAddr, + FrameType, + Rssi, + bAuthCheck); + } + else + { + if (bAuthCheck) + *bAuthCheck = TRUE; + } + + 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 (PHY_MODE_IS_5G_BAND(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].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].Bssid), + bInfReady ? "ready" : "not ready")); + } + + return ret_val; +} + + +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; +} + +static 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; + + if (table->Band == BAND_24G) + { + INT i; + + BND_STRG_DBGPRINT(RT_DEBUG_OFF, + ("\t2G Accessible Clients:\n")); + + 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 INT D_CheckConnectionReq( + PRTMP_ADAPTER pAd, + PUCHAR pSrcAddr, + UINT8 FrameType, + PCHAR Rssi, + BOOLEAN *bAuthCheck) +{ + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + BNDSTRG_MSG msg; + + /* Send to daemon */ + NdisCopyMemory(msg.Rssi, Rssi, 3); + msg.Action= CONNECTION_REQ; + msg.Band = table->Band; + msg.FrameType = FrameType; + msg.bAuthCheck = bAuthCheck ? 1:0; + COPY_MAC_ADDR(msg.Addr, pSrcAddr); + D_BndStrgSendMsg(pAd, &msg); + + if (bAuthCheck) + { + PBND_STRG_CLI_TABLE table = P_BND_STRG_TABLE; + PBND_STRG_CLI_ENTRY entry = NULL; + + if (table->Ops) + entry = table->Ops->TableLookup(table, pSrcAddr); + + if (entry || table->Band == BAND_5G) + *bAuthCheck = TRUE; +#ifdef BND_STRG_QA + else + { + *bAuthCheck = FALSE; + BND_STRG_PRINTQAMSG(table, pSrcAddr, + (RED("check 2.4G connection failed. client (%02x:%02x:%02x:%02x:%02x:%02x)" + " is not allowed to connect 2.4G.\n"), PRINT_MAC(pSrcAddr))); + } +#endif + } + + 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 (!(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; + } + + pAd->ApCfg.BandSteering = enable; + + 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_SetRssiCheck( + PBND_STRG_CLI_TABLE table, + CHAR RssiCheck) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) table->priv; + BNDSTRG_MSG msg; + + table->RssiCheck = RssiCheck; + DBGPRINT(RT_DEBUG_OFF, + ("%s(): RssiCheck = %u\n", __FUNCTION__, table->RssiCheck)); + + msg.Action = SET_RSSI_CHECK; + msg.RssiCheck = RssiCheck; + 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; +} + + +#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 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; + } + +} + +static 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, + .SetRssiCheck = D_SetRssiCheck, + .SetAgeTime = D_SetAgeTime, + .SetHoldTime = D_SetHoldTime, + .SetCheckTime = D_SetCheckTime, +#ifdef BND_STRG_DBG + .SetMntAddr = D_SetMntAddr, +#endif /* BND_STRG_DBG */ + .MsgHandle= D_MsgHandle, +}; +#endif /* BAND_STEERING */ + diff --git a/mt7620/src/ap/ap_cfg.c b/mt7620/src/ap/ap_cfg.c new file mode 100644 index 0000000..1fade36 --- /dev/null +++ b/mt7620/src/ap/ap_cfg.c @@ -0,0 +1,14700 @@ +/**************************************************************************** + * 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", FALSE, 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_SSID_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_TxRate_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +#ifdef RT305x +INT Set_RfRead_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_RfWrite_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); +#endif /* RT305x */ + +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_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_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); + +INT Set_AutoChannelSel_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#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_MacTable_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_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 RTMP_MAC_PCI +#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); + +INT Show_Diag_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* DBG_DAIGNOSE */ +#endif /* RTMP_MAC_PCI */ + +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 NINTENDO_AP +int Set_NintendiCapable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +int Set_NintendoGet_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +int Set_NintendoSet_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* NINTENDO_AP */ + +#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); +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + +#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); +#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); + +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); + +#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_WscSetupLock_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 EASY_CONFIG_SETUP +INT Set_AP_AutoProvisionEnable_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_RssiThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef WAC_SUPPORT +INT Set_AP_WACEnable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* WAC_SUPPORT */ +#endif /* EASY_CONFIG_SETUP */ + +#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( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_AP2040ReScan_Proc( + IN PRTMP_ADAPTER pAd, + IN 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 */ + +#ifdef RT3883 +INT Set_CwCTest_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* RT3883 */ + +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 P2P_SUPPORT +INT Set_P2p_OpMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_Ssid_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_Bssid_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_AuthMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_EncrypType_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_WPAPSK_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_Key1_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_Key2_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_Key3_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_Key4_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_TxMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_TxMcs_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef WSC_AP_SUPPORT +INT Set_P2pCli_WscSsid_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* WSC_AP_SUPPORT */ +#endif /* P2P_SUPPORT */ + +INT Set_MacWatchDog_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT Set_DumpRF_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT Set_DumpBBP_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT Set_KickOutHwNull_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +#ifdef DYNAMIC_VGA_SUPPORT +INT Set_DyncVgaEnable_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); +#endif /* DYNAMIC_VGA_SUPPORT */ + +#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 */ + {"SSID", Set_AP_SSID_Proc}, + {"WirelessMode", Set_WirelessMode_Proc}, + {"BasicRate", Set_BasicRate_Proc}, + {"ShortSlot", Set_ShortSlot_Proc}, + {"Channel", Set_Channel_Proc}, + {"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_SendPSMPAction_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 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}, + {"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 */ +#ifdef AP_SCAN_SUPPORT + {"SiteSurvey", Set_SiteSurvey_Proc}, + {"AutoChannelSel", Set_AutoChannelSel_Proc}, + {"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}, +#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}, + {"Fcc5Thrd", Set_Fcc5Thrd_Proc}, + {"ChBusyThrd", Set_ChBusyThrd_Proc}, + {"RssiThrd", Set_RssiThrd_Proc}, + {"PollTime", Set_PollTime_Proc}, + {"CEPrint", Set_CEPrint_Proc}, + {"RadarSim", Set_RadarSim_Proc}, + {"PrintBusyIdle", Set_PrintBusyIdle_Proc}, + {"BusyIdleRatio", Set_BusyIdleRatio_Proc}, + {"DfsRssiHigh", Set_DfsRssiHigh_Proc}, + {"DfsRssiLow", Set_DfsRssiLow_Proc}, + {"Ch0EventExpire", Set_Ch0EventExpire_Proc}, + {"Ch1EventExpire", Set_Ch1EventExpire_Proc}, + {"Ch2EventExpire", Set_Ch2EventExpire_Proc}, + {"Ch3EventExpire", Set_Ch3EventExpire_Proc}, + {"Ch0LErr", Set_Ch0LErr_Proc}, + {"PeriodErr", Set_PeriodErr_Proc}, + {"MaxPeriod", Set_MaxPeriod_Proc}, + {"Ch0HErr", Set_Ch0HErr_Proc}, + {"Ch1Shift", Set_Ch1Shift_Proc}, + {"Ch2Shift", Set_Ch2Shift_Proc}, + {"CheckLoop", Set_CheckLoop_Proc}, + {"DeclareThres", Set_DeclareThres_Proc}, + {"ChMovTime", Set_ChMovingTime_Proc}, + {"BlockChReset", Set_BlockChReset_Proc}, + {"RfReg", Set_RfReg_Proc}, +#ifdef DFS_DEBUG + {"DfsLowerLimit", Set_DfsLowerLimit_Proc}, + {"DfsUpperLimit", Set_DfsUpperLimit_Proc}, + /*{"FixDfsLimit", Set_FixDfsLimit_Proc},*/ + /*{"AvgRssiReq", Set_AvgRssiReq_Proc},*/ + {"CEPrintDebug", Set_CEPrintDebug_Proc}, +#endif /* DFS_DEBUG */ +#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 RT305x + {"RfRead", Set_RfRead_Proc}, + {"RfWrite", Set_RfWrite_Proc}, + {"HiPower", Set_HiPower_Proc}, +#if defined(RT3352) || defined(RT5350) +#ifdef RTMP_INTERNAL_TX_ALC + {"TSSIMaxRange", Set_TSSIMaxRange_Proc}, +#endif /* RTMP_INTERNAL_TX_ALC */ +#endif /* defined(RT3352) || defined(RT5350) */ +#endif /* RT305x */ + +#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}, +#ifdef RTMP_TEMPERATURE_CALIBRATION + {"ATETEMPCAL", Set_ATE_TEMP_CAL_Proc}, + {"ATESHOWTSSI", Set_ATE_SHOW_TSSI_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 */ + {"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}, +#ifndef RTMP_RF_RW_SUPPORT + {"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 /* RTMP_RF_RW_SUPPORT */ + {"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}, + {"ATEIPG", Set_ATE_IPG_Proc}, + {"ATEPAYLOAD", Set_ATE_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}, + {"ATETxBfCal", Set_ATE_TXBF_CAL_Proc}, + {"ATETxBfGolden", Set_ATE_TXBF_GOLDEN_Proc}, + {"ATETxBfVerify", Set_ATE_TXBF_VERIFY_Proc}, + {"ATETxBfVerifyN", Set_ATE_TXBF_VERIFY_NoComp_Proc}, + {"ATEForceBBP", Set_ATE_ForceBBP_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}, +#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 + {"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_AUTO_CONNECT_SUPPORT + {"ApCliAutoConnect", Set_ApCli_AutoConnect_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 WSC_AP_SUPPORT + {"ApCliWscSsid", Set_AP_WscSsid_Proc}, +#endif /* WSC_AP_SUPPORT */ +#ifdef APCLI_CERT_SUPPORT + {"ApCliCertEnable", Set_ApCli_Cert_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 WSC_V2_SUPPORT + {"WscV2Support", Set_WscV2Support_Proc}, + {"WscVersion2", Set_WscVersion2_Proc}, + {"WscExtraTlvTag", Set_WscExtraTlvTag_Proc}, + {"WscExtraTlvType", Set_WscExtraTlvType_Proc}, + {"WscExtraTlvData", Set_WscExtraTlvData_Proc}, + {"WscSetupLock", Set_WscSetupLock_Proc}, + {"WscFragment", Set_WscFragment_Proc}, + {"WscFragmentSize", Set_WscFragmentSize_Proc}, + {"WscMaxPinAttack", Set_WscMaxPinAttack_Proc}, + {"WscSetupLockTime", Set_WscSetupLockTime_Proc}, +#endif /* WSC_V2_SUPPORT */ + {"WscAutoTriggerDisable", Set_WscAutoTriggerDisable_Proc}, +#endif /* WSC_AP_SUPPORT */ +#ifdef EASY_CONFIG_SETUP + {"AutoProvisionEn", Set_AP_AutoProvisionEnable_Proc}, + {"RssiThreshold", Set_RssiThreshold_Proc}, +#ifdef WAC_SUPPORT + {"WACEnable", Set_AP_WACEnable_Proc}, +#endif /* WAC_SUPPORT */ +#endif /* EASY_CONFIG_SETUP */ +#ifdef NINTENDO_AP + {"NintendoCapable", Set_NintendiCapable_Proc}, + {"NintendoLogin", Set_NintendoSet_Proc}, +/* {"Nintendoget", Set_NintendoGet_Proc}, */ +#endif /* NINTENDO_AP */ +#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 MESH_SUPPORT + {"MeshId", Set_MeshId_Proc}, + {"MeshHostName", Set_MeshHostName_Proc}, + {"MeshAutoLink", Set_MeshAutoLink_Proc}, + {"MeshForward", Set_MeshForward_Proc}, + {"MeshAddLink", Set_MeshAddLink_Proc}, + {"MeshDelLink", Set_MeshDelLink_Proc}, + {"MeshMultiCastAgeOut", Set_MeshMultiCastAgeOut_Proc}, + {"MeshAuthMode", Set_MeshAuthMode_Proc}, + {"MeshEncrypType", Set_MeshEncrypType_Proc}, + {"MeshDefaultkey", Set_MeshDefaultkey_Proc}, + {"MeshWEPKEY", Set_MeshWEPKEY_Proc}, + {"MeshWPAKEY", Set_MeshWPAKEY_Proc}, +#endif /* MESH_SUPPORT */ + +#ifdef TXBF_SUPPORT + {"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}, + {"InvTxBfTag", Set_InvTxBfTag_Proc}, + {"ITxBfCal", Set_ITxBfCal_Proc}, + {"ITxBfDivCal", Set_ITxBfDivCal_Proc}, + {"ITxBfLnaCal", Set_ITxBfLnaCal_Proc}, + + {"ITxBfEn", Set_ITxBfEn_Proc}, + {"ETxBfEnCond", Set_ETxBfEnCond_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}, +#endif /* TXBF_SUPPORT */ + +#if defined(RT2883) || defined(RT3883) + {"PhyRateLimit", Set_PhyRateLimit_Proc}, +#ifdef DBG + {"FixedRate", Set_FixedRate_Proc}, +#endif /* DBG */ +#endif /* defined (RT2883) || defined (RT3883) */ + +#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 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 RT5350 + {"HwAntDiv", Set_Hw_Antenna_Div_Proc}, +#endif /* RT5350 */ + +#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 */ + +#ifdef P2P_SUPPORT + {"P2pCliEnable", Set_P2pCli_Enable_Proc}, + {"P2pCliSsid", Set_P2pCli_Ssid_Proc}, + {"P2pCliBssid", Set_P2pCli_Bssid_Proc}, + {"P2pCliAuthMode", Set_P2pCli_AuthMode_Proc}, + {"P2pCliEncrypType", Set_P2pCli_EncrypType_Proc}, + {"P2pCliDefaultKeyID", Set_P2pCli_DefaultKeyID_Proc}, + {"P2pCliWPAPSK", Set_P2pCli_WPAPSK_Proc}, + {"P2pCliKey1", Set_P2pCli_Key1_Proc}, + {"P2pCliKey2", Set_P2pCli_Key2_Proc}, + {"P2pCliKey3", Set_P2pCli_Key3_Proc}, + {"P2pCliKey4", Set_P2pCli_Key4_Proc}, + {"P2pCliTxMode", Set_P2pCli_TxMode_Proc}, + {"P2pCliTxMcs", Set_P2pCli_TxMcs_Proc}, +#ifdef WSC_AP_SUPPORT + {"P2pCliWscSsid", Set_P2pCli_WscSsid_Proc}, +#endif /* WSC_AP_SUPPORT */ + {"P2pOpMode", Set_P2p_OpMode_Proc}, + {"p2pEnable", Set_P2P_Enable}, + {"p2pLisCh", Set_P2P_Listen_Channel}, + {"p2pOpCh", Set_P2P_Operation_Channel}, + {"p2pGoInt", Set_P2P_GO_Intent}, + {"p2pDevName", Set_P2P_Device_Name}, + {"p2pWscMode", Set_P2P_WSC_Mode}, + {"p2pWscConf", Set_P2P_WSC_ConfMethod}, + {"p2pNoACnt", Set_P2P_NoA_Count}, + {"p2pNoADuration", Set_P2P_NoA_Duration}, + {"p2pNoAInv", Set_P2P_NoA_Interval}, + {"p2pExtLst", Set_P2P_Extend_Listen}, + {"p2pExtLstPrd", Set_P2P_Extend_Listen_Periodic}, + {"p2pExtLstInv", Set_P2P_Extend_Listen_Interval}, + {"p2pIntraBss", Set_P2P_Intra_Bss}, + {"p2pScan", Set_P2P_Scan}, + {"p2pProv", Set_P2P_Provision_Proc}, + {"p2pInv", Set_P2P_Invite_Proc}, + {"p2pDevDisc", Set_P2P_Device_Discoverability_Proc}, + {"p2pLink", Set_P2P_Connect_GoIndex_Proc}, + {"p2pCfg", Set_P2P_Print_Cfg}, + {"p2pTab", Set_P2P_Print_GroupTable_Proc}, + {"p2pPerTab", Set_P2P_Print_PersistentTable_Proc}, + {"p2pStat", Set_P2P_State_Proc}, + {"p2pReset", Set_P2P_Reset_Proc}, + {"p2pDefConfMthd", Set_P2P_Default_Config_Method_Proc}, +#endif /* P2P_SUPPORT */ + + {"VcoPeriod", Set_VcoPeriod_Proc}, + +#ifdef SINGLE_SKU + {"ModuleTxpower", Set_ModuleTxpower_Proc}, +#endif /* SINGLE_SKU */ + + {"MacWatchDog", Set_MacWatchDog_Proc}, + {"DumpRF", Set_DumpRF_Proc}, + {"DumpBBP", Set_DumpBBP_Proc}, + {"TestLOFTCalibration", Set_TestLoftTxIQCalibration_Proc}, + {"TestRxIQCalibration", Set_TestRxIQCalibration_Proc}, + {"DPDCalPassThres", Set_DPDCalPassThres_Proc}, + {"TestDPDCalibration", Set_TestDPDCalibration_Proc}, + {"TestDPDCalibrationTX0", Set_TestDPDCalibrationTX0_Proc}, + {"TestDPDCalibrationTX1", Set_TestDPDCalibrationTX1_Proc}, + {"KickOutHwNull", Set_KickOutHwNull_Proc}, + + +#if defined(MICROWAVE_OVEN_SUPPORT) || defined(DYNAMIC_VGA_SUPPORT) + {"MO_FalseCCATh", Set_MO_FalseCCATh_Proc}, + {"MO_LowFalseCCATh", Set_MO_LowFalseCCATh_Proc}, +#ifdef DYNAMIC_VGA_SUPPORT + {"DyncVgaEnable", Set_DyncVgaEnable_Proc}, +#endif /* DYNAMIC_VGA_SUPPORT */ +#endif /* defined(MICROWAVE_OVEN_SUPPORT) || defined(DYNAMIC_VGA_SUPPORT) */ + +#ifdef THERMAL_PROTECT_SUPPORT + {"tpc", set_thermal_protection_criteria_proc}, +#endif /* THERMAL_PROTECT_SUPPORT */ +#ifdef BAND_STEERING + {"BndStrgEnable", Set_BndStrg_Enable}, + {"BndStrgRssiCheck", Set_BndStrg_RssiCheck}, + {"BndStrgAge", Set_BndStrg_Age}, + {"BndStrgHoldTime", Set_BndStrg_HoldTime}, + {"BndStrgCheckTime", Set_BndStrg_CheckTime5G}, +#ifdef BND_STRG_DBG + {"BndStrgMntAddr", Set_BndStrg_MonitorAddr}, +#endif /* BND_STRG_DBG */ +#endif /* BAND_STEERING */ + {NULL,} +}; + + +static struct { + PSTRING name; + INT (*set_proc)(PRTMP_ADAPTER pAdapter, PSTRING arg); +} *PRTMP_PRIVATE_SHOW_PROC, RTMP_PRIVATE_SHOW_SUPPORT_PROC[] = { + {"stainfo", Show_MacTable_Proc}, + {"stacountinfo", Show_StaCount_Proc}, + {"stasecinfo", Show_StaSecurityInfo_Proc}, + {"descinfo", Show_DescInfo_Proc}, + {"driverinfo", Show_DriverInfo_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 MESH_SUPPORT + {"meshinfo", Set_MeshInfo_Display_Proc}, + {"neighinfo", Set_NeighborInfo_Display_Proc}, + {"meshrouteinfo", Set_MeshRouteInfo_Display_Proc}, + {"meshproxyinfo", Set_MeshProxyInfo_Display_Proc}, + {"meshentryinfo", Set_MeshEntryInfo_Display_Proc}, + {"multipathinfo", Set_MultipathInfo_Display_Proc}, + {"multicastageoutinfo", Set_MultiCastAgeOut_Display_Proc}, + {"pktsiginfo", Set_PktSig_Display_Proc}, +#endif /* MESH_SUPPORT */ +#ifdef DFS_SUPPORT + {"blockch", Show_BlockCh_Proc}, +#endif /* DFS_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}, +#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}, +#endif /* WSC_AP_SUPPORT */ +#ifdef BAND_STEERING + {"BndStrgList", Show_BndStrg_List}, + {"BndStrgInfo", Show_BndStrg_Info}, +#endif /* BAND_STEERING */ + {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) && + (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; + +} + +#ifdef INF_AR9 +#ifdef AR9_MAPI_SUPPORT +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, + IN OUT 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 */ + UINT KeyIdx = 0; + PNDIS_AP_802_11_KEY pKey = NULL; + TX_RTY_CFG_STRUC tx_rty_cfg; + ULONG ShortRetryLimit, LongRetryLimit; +#endif /* SNMP_SUPPORT */ + UCHAR ctmp; + +#ifdef MESH_SUPPORT + BOOLEAN RestartMeshIsRequired = FALSE; +#endif /* MESH_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].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 */ + RTMP_ASIC_SHARED_KEY_TABLE(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 */ + RTMP_ASIC_SHARED_KEY_TABLE(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); + if (enabled == 1) + { + NdisAcquireSpinLock(&pAd->MacTabLock); + pMacEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + NdisReleaseSpinLock(&pAd->MacTabLock); + } + else + { + NdisAcquireSpinLock(&pAd->MacTabLock); + 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*/ + + #ifdef P2P_SUPPORT + + case OID_802_11_P2P_MODE: + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_P2P_MODE \n")); + printk("wrq->u.data.length =%d sizeof(UCHAR)=%d\n",wrq->u.data.length,sizeof(UCHAR)); + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + UCHAR OpMode=1; + Status = copy_from_user(&OpMode, wrq->u.data.pointer, wrq->u.data.length); + if (OpMode == OPMODE_AP) + { + if (P2P_CLI_ON(pAd)) + P2P_CliStop(pAd); + + if ((!P2P_GO_ON(pAd)) || (P2P_GO_ON(pAd))) + { + P2PCfgInit(pAd); + P2P_GoStartUp(pAd, MAIN_MBSSID); + } + } + else if (OpMode == OPMODE_APSTA) + { + if (P2P_GO_ON(pAd)) + P2P_GoStop(pAd); + + if ((!P2P_CLI_ON(pAd)) || (P2P_CLI_ON(pAd))) + { + P2PCfgInit(pAd); + P2P_CliStartUp(pAd); + AsicEnableBssSync(pAd); + } + } + else + { + if (P2P_CLI_ON(pAd)) + P2P_CliStop(pAd); + else if (P2P_GO_ON(pAd)) + { + P2P_GoStop(pAd); + if (INFRA_ON(pAd)) + AsicEnableBssSync(pAd); + } + P2PCfgInit(pAd); + } + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(p2p%d) Set_P2p_OpMode_Proc::(OpMode = %d)\n", pObj->ioctl_if, OpMode)); + + + } + break; +/* + case OID_802_11_P2P_CLEAN_TABLE: + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_P2P_CLEAN_TABLE \n")); + { + P2pGroupTabInit(pAd); + } + break; +*/ + case OID_802_11_P2P_DEVICE_NAME: + DBGPRINT(RT_DEBUG_ERROR, ("Set::OID_802_11_P2P_DEVICE_NAME \n")); + if (wrq->u.data.length > 32) + Status = -EINVAL; + else + { + UCHAR DeviceName[MAX_LEN_OF_SSID] = {0}; + + NdisZeroMemory(DeviceName, sizeof(DeviceName)); + Status = copy_from_user(&DeviceName, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_ERROR, ("Set::OID_802_11_P2P_DEVICE_NAME DeviceName=%s\n",DeviceName)); + { + + pAd->P2pCfg.DeviceNameLen = wrq->u.data.length; + NdisZeroMemory(pAd->P2pCfg.DeviceName, 32); + NdisMoveMemory(pAd->P2pCfg.DeviceName, DeviceName, pAd->P2pCfg.DeviceNameLen); + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Device Name = %s.\n", __FUNCTION__, pAd->P2pCfg.DeviceName)); + } + + } + break; + + case OID_802_11_P2P_LISTEN_CHANNEL: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_P2P_LISTEN_CHANNEL \n")); + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + /*UCHAR __buf[4]; */ + UCHAR listen_ch; + Status = copy_from_user(&listen_ch, wrq->u.data.pointer, wrq->u.data.length); + /*sprintf(__buf, "%d", listen_ch);*/ + DBGPRINT(RT_DEBUG_ERROR, ("%s:: listen_ch = %d.\n", __FUNCTION__, listen_ch)); + + { + /* + POS_COOKIE pObj; + UINT32 channel; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + channel = (UCHAR) simple_strtol(arg, 0, 10); + */ + /* check if this channel is valid */ + if (ChannelSanity(pAd, listen_ch) == TRUE) + { + pAd->P2pCfg.ListenChannel = listen_ch; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Listen Channel out of range, using default.\n")); + pAd->P2pCfg.ListenChannel = 1; + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Listen Channel = %d.\n", __FUNCTION__, pAd->P2pCfg.ListenChannel)); + } + } + break; + + case OID_802_11_P2P_OPERATION_CHANNEL: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_P2P_OPERATION_CHANNEL \n")); + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + UCHAR op_ch; + Status = copy_from_user(&op_ch, wrq->u.data.pointer, wrq->u.data.length); + + /* check if this channel is valid */ + if (ChannelSanity(pAd, op_ch) == TRUE) + { + pAd->P2pCfg.GroupChannel = op_ch; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Opertation Channel out of range, using default.\n")); + pAd->P2pCfg.GroupChannel = 1; + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Op Channel = %d.\n", __FUNCTION__, pAd->P2pCfg.GroupChannel)); + + } + break; + + case OID_802_11_P2P_GO_INT: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_P2P_GO_INT \n")); + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + UCHAR intent; + Status = copy_from_user(&intent, wrq->u.data.pointer, wrq->u.data.length); + + /* check if this channel is valid */ + + if (intent <= 15) + pAd->P2pCfg.GoIntentIdx = intent; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("GO Intent out of range 0 ~ 15, using default.\n")); + pAd->P2pCfg.GoIntentIdx = 0; + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: GO Intent = %d.\n", __FUNCTION__, pAd->P2pCfg.GoIntentIdx)); + + } + break; + + case OID_802_11_P2P_SCAN: + DBGPRINT(RT_DEBUG_ERROR, ("Set::OID_802_11_P2P_SCAN \n")); + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + + UCHAR bScan; + Status = copy_from_user(&bScan, wrq->u.data.pointer, wrq->u.data.length); + + + if (bScan) + { + pAd->StaCfg.bAutoReconnect = FALSE; + P2pScan(pAd); + } + else + { + pAd->StaCfg.bAutoReconnect = TRUE; + P2pStopScan(pAd); + } + } + break; + + + case OID_P2P_WSC_PIN_CODE: + DBGPRINT(RT_DEBUG_ERROR, ("Set::OID_P2P_WSC_PIN_CODE wrq->u.data.length=%d\n",wrq->u.data.length)); + 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_AP_WscPinCode_Proc(pAd, (PSTRING) &PinCode[0]) == FALSE) + Status = -EINVAL; + } + } + break; + + case OID_802_11_P2P_WscMode: + DBGPRINT(RT_DEBUG_ERROR, ("Set::OID_802_11_P2P_WscMode \n")); + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + UCHAR p2pWscMode; + Status = copy_from_user(&p2pWscMode, wrq->u.data.pointer, wrq->u.data.length); + + /* check if this channel is valid */ + + if (p2pWscMode <= 2 && p2pWscMode >= 1) + pAd->P2pCfg.WscMode= p2pWscMode; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("WscMode is invalid, using default.\n")); + pAd->P2pCfg.WscMode = WSC_PIN_MODE; /* PIN */ + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: WscMode = %s.\n", __FUNCTION__, (p2pWscMode == 1) ? "PIN" : "PBC")); + } + break; + + case OID_802_11_P2P_WscConf: + DBGPRINT(RT_DEBUG_ERROR, ("Set::OID_802_11_P2P_WscConf \n")); + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + UCHAR method; + Status = copy_from_user(&method, wrq->u.data.pointer, wrq->u.data.length); + + if (pAd->P2pCfg.WscMode == WSC_PIN_MODE) + { + if (method == 1) + { + /* Display PIN */ + pAd->P2pCfg.Dpid = DEV_PASS_ID_REG; + pAd->P2pCfg.ConfigMethod = WSC_CONFMET_DISPLAY; + DBGPRINT(RT_DEBUG_ERROR, (" *************************************************\n")); + DBGPRINT(RT_DEBUG_ERROR, (" * *\n")); + DBGPRINT(RT_DEBUG_ERROR, (" * PIN Code = %08u *\n", pAd->ApCfg.ApCliTab[0].WscControl.WscEnrolleePinCode)); + DBGPRINT(RT_DEBUG_ERROR, (" * *\n")); + DBGPRINT(RT_DEBUG_ERROR, (" *************************************************\n")); + + } + else if (method == 2) + { + /* Enter PIN */ + pAd->P2pCfg.Dpid = DEV_PASS_ID_USER; + pAd->P2pCfg.ConfigMethod = WSC_CONFMET_KEYPAD; + } + } + else if (pAd->P2pCfg.WscMode == WSC_PBC_MODE) + { + if (method == 3) + { + pAd->P2pCfg.Dpid = DEV_PASS_ID_PBC; + pAd->P2pCfg.ConfigMethod = WSC_CONFMET_PBC; + } + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Config Method = %s.\n", __FUNCTION__, decodeConfigMethod(pAd->P2pCfg.ConfigMethod))); + } + break; + + case OID_802_11_P2P_Link: + DBGPRINT(RT_DEBUG_ERROR, ("Set::OID_802_11_P2P_Link \n")); + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + + UCHAR p2pindex; + PUCHAR pAddr; + Status = copy_from_user(&p2pindex, wrq->u.data.pointer, wrq->u.data.length); + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: TabIdx[%d]\n", __FUNCTION__, p2pindex)); + if (p2pindex < pAd->P2pTable.ClientNumber) + { + /*P2PPrintP2PEntry(pAd, P2pTabIdx); */ + /*pAd->P2pCfg.ConnectingIndex = 0; */ + /*if (pAd->P2pTable.Client[P2pTabIdx].P2pClientState == P2PSTATE_DISCOVERY) */ + /* pAd->P2pTable.Client[P2pTabIdx].P2pClientState = P2PSTATE_CONNECT_COMMAND; */ + /*COPY_MAC_ADDR(pAd->P2pCfg.ConnectingMAC, pAd->P2pTable.Client[P2pTabIdx].addr); */ + /*pAd->P2pTable.Client[P2pTabIdx].StateCount = 10; */ + /*pAd->P2pTable.Client[P2pTabIdx].bValid = TRUE; */ + /*P2pConnect(pAd); */ + pAddr = &pAd->P2pTable.Client[p2pindex].addr[0]; + P2pConnectPrepare(pAd, pAddr, P2PSTATE_CONNECT_COMMAND); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("Table Idx out of range!\n")); + } + break; +#endif /* P2P_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)); + +#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; + + 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); + + } + 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->Aid; + 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 + { + RTMP_GET_OS_PID(pObj->IappPid, IappPid); + pObj->IappPid_nr = IappPid; + DBGPRINT(RT_DEBUG_TRACE, ("RT_SET_APD_PID::(IappPid=%lu(0x%x))\n", IappPid, (UINT32)pObj->IappPid)); + } + } + break; +#endif /* IAPP_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 + { + 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%p))\n", apd_pid, pObj->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) + { + MlmeDeAuthAction(pAd, pEntry, REASON_DISASSOC_STA_LEAVING, FALSE); +/* MacTableDeleteEntry(pAd, pEntry->Aid, Addr); */ + } + } + break; +#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 */ +#ifdef WSC_AP_SUPPORT + case RT_OID_WSC_SET_SELECTED_REGISTRAR: + { + PUCHAR upnpInfo; + UCHAR apidx = pObj->ioctl_if; + +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[apidx].Hostapd == TRUE) + { + 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 == TRUE) + { + 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; + BOOLEAN bGetDeviceInfo = FALSE; + + 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; + bGetDeviceInfo = TRUE; + } + 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 NINTENDO_AP + case RT_OID_802_11_NINTENDO_SET_TABLE: + RTMPIoctlNintendoSetTable(pAd, wrq); + break; + case RT_OID_802_11_NINTENDO_CAPABLE: + RTMPIoctlNintendoCapable(pAd, wrq); + break; +#endif /* NINTENDO_AP */ + +#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].DefaultKeyId].KeyLen = (UCHAR) pKey->KeyLength; + NdisMoveMemory(&pAd->SharedKey[pObj->ioctl_if][pAd->ApCfg.MBSSID[pObj->ioctl_if].DefaultKeyId].Key, &pKey->KeyMaterial, pKey->KeyLength); + if (pKey->KeyIndex & 0x80000000) + { + /* Default key for tx (shared key) */ + pAd->ApCfg.MBSSID[pObj->ioctl_if].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].DefaultKeyId, wrq->u.data.pointer, wrq->u.data.length); + + break; + +#endif /* SNMP_SUPPORT */ + + 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; + +#ifdef MESH_SUPPORT + case OID_802_11_MESH_SECURITY_INFO: + Status = RTMPIoctlSetMeshSecurityInfo(pAd, wrq); + if (Status == NDIS_STATUS_SUCCESS) + RestartMeshIsRequired = TRUE; + break; + + case OID_802_11_MESH_ID: + if (wrq->u.data.length >= MAX_MESH_ID_LEN) + { + Status = -EINVAL; + break; + } + + { + UCHAR MeshID[MAX_MESH_ID_LEN]; + + NdisZeroMemory(pAd->MeshTab.MeshId, MAX_MESH_ID_LEN); + + Status = copy_from_user(&MeshID,wrq->u.data.pointer, wrq->u.data.length); + NdisMoveMemory(&pAd->MeshTab.MeshId, MeshID, wrq->u.data.length); + pAd->MeshTab.MeshIdLen = (UCHAR)wrq->u.data.length; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_MESH_ID (=%s)\n", pAd->MeshTab.MeshId)); + RestartMeshIsRequired = TRUE; + } + break; + + case OID_802_11_MESH_AUTO_LINK: + if (wrq->u.data.length != 1) + { + Status = -EINVAL; + break; + } + + { + UCHAR Enable = TRUE; + + Status = copy_from_user(&Enable, wrq->u.data.pointer, wrq->u.data.length); + pAd->MeshTab.MeshAutoLink = (Enable > 0) ? TRUE : FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_MESH_AUTO_LINK (=%s)\n", + pAd->MeshTab.MeshAutoLink == TRUE ? "Enable" : "Disable")); + } + break; + + case OID_802_11_MESH_ADD_LINK: + if (wrq->u.data.length != MAC_ADDR_LEN) + { + Status = -EINVAL; + break; + } + + { + UCHAR MacAddr[MAC_ADDR_LEN]; + UINT LinkIdx; + + Status = copy_from_user(&MacAddr, wrq->u.data.pointer, MAC_ADDR_LEN); + LinkIdx = GetMeshLinkId(pAd, (PCHAR)MacAddr); + if (LinkIdx == BSS_NOT_FOUND) + { + LinkIdx = MeshLinkAlloc(pAd, MacAddr, MESH_LINK_STATIC); + if (LinkIdx == BSS_NOT_FOUND) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() All Mesh-Links been occupied.\n", __FUNCTION__)); + return FALSE; + } + } + + if (!VALID_MESH_LINK_ID(LinkIdx)) + break; + + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_ACTOPN, 0, NULL, LinkIdx); + DBGPRINT(RT_DEBUG_TRACE, ("%s::(LinkIdx = %d)\n", __FUNCTION__, LinkIdx)); + } + break; + + case OID_802_11_MESH_DEL_LINK: + if (wrq->u.data.length != MAC_ADDR_LEN) + { + Status = -EINVAL; + break; + } + + { + UCHAR MacAddr[MAC_ADDR_LEN]; + UINT LinkIdx; + + Status = copy_from_user(&MacAddr, wrq->u.data.pointer, MAC_ADDR_LEN); + LinkIdx = GetMeshLinkId(pAd, (PCHAR)MacAddr); + if (!VALID_MESH_LINK_ID(LinkIdx)) + break; + + pAd->MeshTab.MeshLink[LinkIdx].Entry.LinkType = MESH_LINK_DYNAMIC; + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_CNCL, 0, NULL, LinkIdx); + DBGPRINT(RT_DEBUG_TRACE, ("%s::(LinkIdx = %d)\n", __FUNCTION__, LinkIdx)); + } + break; + + case OID_802_11_MESH_MAX_TX_RATE: + if (wrq->u.data.length != 1) + { + Status = -EINVAL; + break; + } + + { + UCHAR TxRate; + + Status = copy_from_user(&TxRate, wrq->u.data.pointer, wrq->u.data.length); + if (TxRate <= 12) + pAd->MeshTab.MeshMaxTxRate = TxRate; + else + pAd->MeshTab.MeshMaxTxRate = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_MESH_MAX_TX_RATE (=%ld)\n", + pAd->MeshTab.MeshMaxTxRate)); + } + break; + + case OID_802_11_MESH_CHANNEL: + if (wrq->u.data.length != 1) + { + Status = -EINVAL; + break; + } + { + UCHAR Channel; + + if (INFRA_ON(pAd) || ADHOC_ON(pAd)) + break; + + Status = copy_from_user(&Channel, wrq->u.data.pointer, wrq->u.data.length); + if (pAd->MeshTab.UCGEnable == TRUE) + { + pAd->MeshTab.MeshChannel = Channel; + MlmeEnqueue(pAd, MESH_CTRL_STATE_MACHINE, MESH_CTRL_UCG_EVT, 0, NULL, 0); + } + else + { + pAd->MeshTab.MeshChannel = pAd->CommonCfg.Channel = Channel; +#ifdef DOT11_N_SUPPORT + N_ChannelCheck(pAd); + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED + && pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + { + N_SetCenCh(pAd); + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + DBGPRINT(RT_DEBUG_TRACE, ("BW_40, control_channel(%d), CentralChannel(%d) \n", + pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, ("BW_20, Channel(%d)\n", pAd->CommonCfg.Channel)); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_MESH_CHANNEL (=%d)\n", (int)Channel)); + } + break; + + case OID_802_11_MESH_HOSTNAME: + if (wrq->u.data.length >= MAX_HOST_NAME_LEN) + { + Status = -EINVAL; + break; + } + + { + NdisZeroMemory(pAd->MeshTab.HostName, MAX_HOST_NAME_LEN); + Status = copy_from_user(pAd->MeshTab.HostName, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_HOSTNAME_ID (=%s)\n", pAd->MeshTab.HostName)); + } + break; + + case OID_802_11_MESH_ONLY_MODE: + if (wrq->u.data.length != 1) + { + Status = -EINVAL; + break; + } + { + UCHAR Enable; + + Status = copy_from_user(&Enable, wrq->u.data.pointer, wrq->u.data.length); + + pAd->MeshTab.MeshOnly = (Enable == 1 ? TRUE : FALSE); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_MESH_ONLY_MODE (=%s)\n", pAd->MeshTab.MeshOnly == TRUE ? "Enable" : "Disable")); + } + break; + + case OID_802_11_MESH_FORWARD: + if (wrq->u.data.length != 1) + { + Status = -EINVAL; + break; + } + + { + UCHAR Enable = TRUE; + + Status = copy_from_user(&Enable, wrq->u.data.pointer, wrq->u.data.length); + pAd->MeshTab.MeshCapability.field.Forwarding = (Enable > 0) ? (1) : (0); + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_MESH_FORWARD (=%s)\n", + pAd->MeshTab.MeshCapability.field.Forwarding == 1 ? "Enable" : "Disable")); + } + break; +#endif /* MESH_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%x))\n", wapi_pid, pObj->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].AuthMode != AuthMode) + { + /* Config has changed */ + pAd->bConfigChanged = TRUE; + } + pAd->ApCfg.MBSSID[pObj->ioctl_if].AuthMode = AuthMode; + } + pAd->ApCfg.MBSSID[pObj->ioctl_if].PortSecured = WPA_802_1X_PORT_NOT_SECURED; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_AUTHENTICATION_MODE (=%d) \n",pAd->ApCfg.MBSSID[0].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) + { + if (pAd->ApCfg.MBSSID[pObj->ioctl_if].WepStatus != WepStatus) + { + /* Config has changed */ + pAd->bConfigChanged = TRUE; + } + pAd->ApCfg.MBSSID[pObj->ioctl_if].WepStatus = WepStatus; + + if (pAd->ApCfg.MBSSID[pObj->ioctl_if].WepStatus == Ndis802_11Encryption4Enabled){ + pAd->ApCfg.MBSSID[pObj->ioctl_if].GroupKeyWepStatus = Ndis802_11Encryption2Enabled; + } + else{ + pAd->ApCfg.MBSSID[pObj->ioctl_if].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; + //UINT apidx = pObj->ioctl_if; + 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->Aid, + &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; + RTMP_ASIC_SHARED_KEY_TABLE(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->Aid, + &pEntry->PairwiseKey); + + RTMPSetWcidSecurityInfo(pAd, + pEntry->apidx, + (UINT8)KeyIdx, + pEntry->PairwiseKey.CipherAlg, + pEntry->Aid, + 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); + + RTMP_ASIC_SHARED_KEY_TABLE(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->Aid != 0) + { + NdisZeroMemory(&pEntry->PairwiseKey, sizeof(CIPHER_KEY)); + AsicRemovePairwiseKeyEntry(pAd,(UCHAR)pEntry->Aid); + } + } + 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].IEEE8021X, pEntry->WepStatus); + if (pAd->ApCfg.MBSSID[pObj->ioctl_if].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->Aid, + &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->Aid; + 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 == TRUE) + 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 0f 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 BAND_STEERING + case OID_BNDSTRG_MSG: + BndStrg_MsgHandle(pAd, wrq); + break; +#endif /* BAND_STEERING */ + + default: + DBGPRINT(RT_DEBUG_TRACE, ("Set::unknown IOCTL's subcmd = 0x%08x\n", cmd)); + Status = -EOPNOTSUPP; + break; + } + +#ifdef MESH_SUPPORT + /* important parameter is changed, restart mesh */ + if (RestartMeshIsRequired) + { + MeshDown(pAd, TRUE); + MeshUp(pAd); + } +#endif /* MESH_SUPPORT */ + + return Status; +} + + +INT RTMPAPQueryInformation( + IN PRTMP_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; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + STRING driverVersion[8]; + +#if defined(DBG) || defined(WSC_AP_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 + /*for snmp, kathy */ + //ULONG ulInfo; + 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 APCLI_SUPPORT +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + UCHAR ifIndex; + BOOLEAN apcliEn=FALSE; + INT i,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; + PAPCLI_STRUCT pApCliEntry=NULL; + NDIS_802_11_SSID Ssid; + UINT we_version_compiled; +#endif/*APCLI_WPA_SUPPLICANT_SUPPORT*/ +#endif/*APCLI_SUPPORT*/ + + + NDIS_802_11_STATISTICS *pStatistics; + +#ifdef EASY_CONFIG_SETUP + PUCHAR pStaMacAddr = NULL; +#endif /* EASY_CONFIG_SETUP */ + +#ifdef P2P_SUPPORT + /*RT_P2P_UI_TABLE UI_table;*/ + PRT_P2P_UI_TABLE pUI_table; + PRT_P2P_TABLE pP2pTable; + PRT_P2P_CLIENT_ENTRY pPAdCli, pUICli; + PRT_P2P_CONFIG pP2PCtrl; /* = &pAd->P2pCfg; */ + UCHAR tmp[24]; + UCHAR i; +#endif /* P2P_SUPPORT */ + + + INT IEEE8021X = 0; + NDIS_802_11_AUTHENTICATION_MODE AuthMode = Ndis802_11AuthModeMax; + switch(cmd) + { +#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].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].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 OID_802_11_PASSPHRASE: + { + MULTISSID_STRUCT *pMBSSStruct; + pMBSSStruct = &pAd->ApCfg.MBSSID[pObj->ioctl_if]; + wrq->u.data.length = pMBSSStruct->WscControl.WpaPskLen; + Status = copy_to_user(wrq->u.data.pointer, &pMBSSStruct->WscControl.WpaPsk, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_PASSPHRASE\n")); + hex_dump("OID_802_11_PASSPHRASE : ",(unsigned char*)&pMBSSStruct->WscControl.WpaPsk,wrq->u.data.length); + 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 (=%lu)\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); + Status = copy_to_user(wrq->u.data.pointer, &pAd->ApCfg.MBSSID[pObj->ioctl_if].bWmmCapable, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_WMM (=%d)\n",pAd->ApCfg.MBSSID[pObj->ioctl_if].bWmmCapable)); + break; + + case OID_802_11_BSSID: + { + //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); + Status = copy_to_user(wrq->u.data.pointer, &pAd->ApCfg.MBSSID[pObj->ioctl_if].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))); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID (%02x:%02x:%02x:%02x:%02x:%02x)\n", PRINT_MAC(pAd->ApCfg.MBSSID[pObj->ioctl_if].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; + + 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; + + + 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; +#ifdef P2P_SUPPORT + case OID_802_11_P2P_Connected_MAC: + wrq->u.data.length = MAC_ADDR_LEN; + Status = copy_to_user(wrq->u.data.pointer, &pAd->P2pCfg.ConnectingMAC, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_Connected_MAC\n")); + break; + + case OID_802_11_P2P_MODE: + wrq->u.data.length = sizeof(char); + Status = copy_to_user(wrq->u.data.pointer, &pAd->P2pCfg.Rule, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_MODE (Len=%d, Rule=%s)\n", sizeof(char),pAd->P2pCfg.Rule)); + break; + + case OID_802_11_P2P_DEVICE_NAME: + wrq->u.data.length = pAd->P2pCfg.DeviceNameLen; + Status = copy_to_user(wrq->u.data.pointer, pAd->P2pCfg.DeviceName, pAd->P2pCfg.DeviceNameLen); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_DEVICE_NAME (Len=%d, DeviceName=%s)\n", pAd->P2pCfg.DeviceNameLen,pAd->P2pCfg.DeviceName)); + break; + + case OID_802_11_P2P_LISTEN_CHANNEL: + wrq->u.data.length = sizeof(char); + Status = copy_to_user(wrq->u.data.pointer, &pAd->P2pCfg.ListenChannel, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_LISTEN_CHANNEL (Len=%d, Listen_Ch=%d)\n", sizeof(char),pAd->P2pCfg.ListenChannel)); + break; + + case OID_802_11_P2P_OPERATION_CHANNEL: + wrq->u.data.length = sizeof(char); + Status = copy_to_user(wrq->u.data.pointer, &pAd->P2pCfg.GroupChannel, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_OPERATION_CHANNEL (Len=%d, Op_Ch=%d)\n", sizeof(char),pAd->P2pCfg.GroupOpChannel)); + break; + + + case OID_802_11_P2P_MAC_ADDR: + wrq->u.data.length = 6; + Status = copy_to_user(wrq->u.data.pointer, pAd->P2pCfg.Bssid, wrq->u.data.length); + /*DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_MAC_ADDR (Len=%d, Rule=%s)\n", sizeof(char),pAd->P2pCfg.GroupOpChannel)); */ + break; + + case OID_802_11_P2P_CTRL_STATUS: + wrq->u.data.length = 24; + pP2PCtrl = &pAd->P2pCfg; + NdisZeroMemory(tmp, 24); + sprintf(tmp,"%s",decodeCtrlState(pP2PCtrl->CtrlCurrentState)); + Status = copy_to_user(wrq->u.data.pointer, tmp, 24); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_MODE (Len=%d, DeviceName=%s)\n", pAd->P2pCfg.DeviceNameLen,pAd->P2pCfg.DeviceName)); + break; + + case OID_802_11_P2P_DISC_STATUS: + wrq->u.data.length = 24; + pP2PCtrl = &pAd->P2pCfg; + NdisZeroMemory(tmp, 24); + sprintf(tmp,"%s",decodeDiscoveryState(pP2PCtrl->DiscCurrentState)); + Status = copy_to_user(wrq->u.data.pointer, tmp, 24); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_MODE (Len=%d, DeviceName=%s)\n", pAd->P2pCfg.DeviceNameLen,pAd->P2pCfg.DeviceName)); + break; + + case OID_802_11_P2P_GOFORM_STATUS: + wrq->u.data.length = 24; + pP2PCtrl = &pAd->P2pCfg; + NdisZeroMemory(tmp, 24); + sprintf(tmp,"%s",decodeGroupFormationState(pP2PCtrl->GoFormCurrentState)); + Status = copy_to_user(wrq->u.data.pointer, tmp, 24); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_MODE (Len=%d, DeviceName=%s)\n", pAd->P2pCfg.DeviceNameLen,pAd->P2pCfg.DeviceName)); + break; + + case OID_802_11_P2P_SCAN_LIST: + + os_alloc_mem(NULL, (UCHAR **)&pUI_table, sizeof(RT_P2P_UI_TABLE)); + pP2pTable = &pAd->P2pTable; + /*NdisZeroMemory(&UI_table, sizeof(UI_table));*/ + /*pUI_table = &UI_table;*/ + NdisZeroMemory(pUI_table, sizeof(RT_P2P_UI_TABLE)); + pUI_table->ClientNumber = pAd->P2pTable.ClientNumber; + for (i=0; i < pAd->P2pTable.ClientNumber; i++) + { + pPAdCli = &pP2pTable->Client[i]; + pUICli = &pUI_table->Client[i]; + NdisMoveMemory(pUICli, pPAdCli, sizeof(RT_P2P_CLIENT_ENTRY)); + } + printk("Query::OID_802_11_P2P_SCAN_LIST\n"); + Status = copy_to_user(wrq->u.data.pointer, pUI_table, sizeof(RT_P2P_UI_TABLE)); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_SCAN_LIST (Len=%d, Rule=%s)\n", sizeof(char),pAd->P2pCfg.GroupOpChannel)); + break; + + case OID_P2P_WSC_PIN_CODE: + wrq->u.data.length = sizeof(UINT); + WscPinCode = pAd->ApCfg.ApCliTab[0].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; +#endif /* P2P_SUPPORT */ + + 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", AP_DRIVER_VERSION); + driverVersion[7] = '\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")); + + + if (FlgIs11rSup == FALSE) + { + { + Status = -EFAULT; + } + } + } + break; + + +#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 */ +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + if (P2P_CLI_ON(pAd)) + { + INT ApCliIdx = pObj->ioctl_if; + APCLI_MR_APIDX_SANITY_CHECK(ApCliIdx); + WscStatus = pAd->ApCfg.ApCliTab[ApCliIdx].WscControl.WscStatus; + } + else + { + WscStatus = pAd->ApCfg.MBSSID[apidx].WscControl.WscStatus; + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_WscConfMode_Proc:: This command is from p2p interface now.\n", apidx)); + } + else +#endif /* P2P_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); */ +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + if (P2P_CLI_ON(pAd)) + { + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + } + else + { + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_WscConfMode_Proc:: This command is from p2p interface now.\n", apidx)); + } + else +#endif /* P2P_SUPPORT */ + 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; +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + if (P2P_CLI_ON(pAd)) + { + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + } + else + { + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_WscConfMode_Proc:: This command is from p2p interface now.\n", apidx)); + } + else +#endif /* P2P_SUPPORT */ + 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].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; + } +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + if (P2P_CLI_ON(pAd)) + { + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + } + else + { + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_WscConfMode_Proc:: This command is from p2p interface now.\n", apidx)); + } + else +#endif /* P2P_SUPPORT */ + 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 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 */ +#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)) + { + 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; + } + } + 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 NINTENDO_AP + case RT_OID_802_11_NINTENDO_GET_TABLE: + RTMPIoctlNintendoGetTable(pAd, wrq); + break; +#endif /* NINTENDO_AP */ +#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; +#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].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 = 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].DefaultKeyId].KeyLen; + NdisMoveMemory(pKeyIdxValue->Value, + &pAd->SharedKey[pObj->ioctl_if][pAd->ApCfg.MBSSID[pObj->ioctl_if].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].DefaultKeyId, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("DefaultKeyId =%d \n", pAd->ApCfg.MBSSID[pObj->ioctl_if].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].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 */ + + 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 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; + PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[apidx]; + + os_alloc_mem(pAd, (UCHAR * *) &pMbssStat, sizeof(MBSS_STATISTICS)); + NdisZeroMemory(pMbssStat, sizeof(MBSS_STATISTICS)); + + pMbssStat->TransmittedByteCount = pMbss->TransmittedByteCount; + pMbssStat->ReceivedByteCount = pMbss->ReceivedByteCount; + 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 MacTab; + + MacTab.Num = 0; + for (i=0; iMacTab.Content[i]) && (pAd->MacTab.Content[i].Sst == SST_ASSOC)) + { + memcpy(&MacTab.Entry[MacTab.Num], &pAd->MacTab.Content[i].TxBFCounters, sizeof(RT_COUNTER_TXBF)); + MacTab.Num++; + } + } + + wrq->u.data.length = sizeof(RT_802_11_TXBF_TABLE); + Status = copy_to_user(wrq->u.data.pointer, &MacTab, wrq->u.data.length); + } + break; +#endif /* TXBF_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef MESH_SUPPORT + case OID_802_11_MESH_DEVICENAME: + if (pAd->MeshTab.dev) + { + wrq->u.data.length = strlen(RtmpOsGetNetDevName(pAd->MeshTab.dev)) + 1; + Status = copy_to_user(wrq->u.data.pointer, RtmpOsGetNetDevName(pAd->MeshTab.dev), strlen(RtmpOsGetNetDevName(pAd->MeshTab.dev))); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_DEVICENAME (Len=%d, Name=%s)\n", wrq->u.data.length, RtmpOsGetNetDevName(pAd->MeshTab.dev))); + } + break; + + case OID_802_11_MESH_SECURITY_INFO: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_SECURITY_INFO \n")); + if (wrq->u.data.length != sizeof(MESH_SECURITY_INFO)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Len Diff %d/%d \n", wrq->u.data.length, sizeof(MESH_SECURITY_INFO))); + Status = -EINVAL; + } + else + RTMPIoctlQueryMeshSecurityInfo(pAd, wrq); + break; + + case OID_802_11_MESH_ID: + wrq->u.data.length = pAd->MeshTab.MeshIdLen; + Status = copy_to_user(wrq->u.data.pointer, &pAd->MeshTab.MeshId, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_ID (Len=%d, MeshID=%s)\n", pAd->MeshTab.MeshIdLen, + pAd->MeshTab.MeshId)); + break; + + case OID_802_11_MESH_AUTO_LINK: + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &pAd->MeshTab.MeshAutoLink, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_AUTO_LINK (=%d)\n", pAd->MeshTab.MeshAutoLink)); + break; + + case OID_802_11_MESH_LINK_STATUS: + { + MESH_LINK_INFO MeshLinkInfo; + UCHAR i; + + NdisZeroMemory(&MeshLinkInfo, sizeof(MESH_LINK_INFO)); + + for (i=0; iMeshTab.MeshLink[i].Entry; + + COPY_MAC_ADDR(MeshLinkInfo.Entry[i].PeerMacAddr, pEntry->PeerMacAddr); + MeshLinkInfo.Entry[i].LinkType = pEntry->LinkType; + MeshLinkInfo.Entry[i].Status = PeerLinkValidCheck(pAd, i); + MeshLinkInfo.Entry[i].Rssi = + RTMPMaxRssi(pAd, pAd->MacTab.Content[pEntry->MacTabMatchWCID].RssiSample.AvgRssi0, + pAd->MacTab.Content[pEntry->MacTabMatchWCID].RssiSample.AvgRssi1, + pAd->MacTab.Content[pEntry->MacTabMatchWCID].RssiSample.AvgRssi2); + MeshLinkInfo.Entry[i].CurTxRate = pAd->MacTab.Content[pEntry->MacTabMatchWCID].HTPhyMode; + } + + wrq->u.data.length = sizeof(MESH_LINK_INFO); + Status = copy_to_user(wrq->u.data.pointer, &MeshLinkInfo, wrq->u.data.length); + } + break; + + case OID_802_11_MESH_LIST: + { + PMESH_NEIGHBOR_INFO pMeshNeighborInfo; /* = kmalloc(sizeof(MESH_NEIGHBOR_INFO), GFP_ATOMIC); */ + UCHAR i, idx = 0; + + os_alloc_mem(pAd, (UCHAR **)&pMeshNeighborInfo, sizeof(MESH_NEIGHBOR_INFO)); + if (pMeshNeighborInfo == NULL) + break; + + NdisZeroMemory(pMeshNeighborInfo, sizeof(MESH_NEIGHBOR_INFO)); + for (i=0; iMeshTab.pMeshNeighborTab->NeighborMP[i]; + + if (pEntry->Valid) + { + strcpy((PSTRING) pMeshNeighborInfo->Entry[idx].HostName, (PSTRING) pEntry->HostName); + COPY_MAC_ADDR(pMeshNeighborInfo->Entry[idx].MacAddr, pEntry->PeerMac); + strcpy((PSTRING) pMeshNeighborInfo->Entry[idx].MeshId, (PSTRING) pEntry->MeshId); + pMeshNeighborInfo->Entry[idx].Channel = pEntry->Channel; + pMeshNeighborInfo->Entry[idx].Rssi = pEntry->RealRssi; + pMeshNeighborInfo->Entry[idx].Status = pEntry->State != LINK_AVAILABLE ? 0 : 1; + pMeshNeighborInfo->Entry[idx].MeshEncrypType = + MeshCheckPeerMpCipher(pEntry->CapabilityInfo, pEntry->RSNIE, pEntry->RSNIE_Len);; + idx++; + } + } + pMeshNeighborInfo->num = idx; + wrq->u.data.length = sizeof(MESH_NEIGHBOR_INFO); + Status = copy_to_user(wrq->u.data.pointer, pMeshNeighborInfo, wrq->u.data.length); + + if (pMeshNeighborInfo) +/* kfree(pMeshNeighborInfo); */ + os_free_mem(NULL, pMeshNeighborInfo); + } + break; + + case OID_802_11_MESH_ROUTE_LIST: + { + PRT_MESH_ROUTE_TABLE rt_table; /* = kmalloc(sizeof(RT_MESH_ROUTE_TABLE), GFP_ATOMIC); */ + UCHAR i; + + os_alloc_mem(pAd, (UCHAR **)&rt_table, sizeof(RT_MESH_ROUTE_TABLE)); + if (rt_table == NULL) + break; + + NdisZeroMemory(rt_table, sizeof(RT_MESH_ROUTE_TABLE)); + + for (i=0; iMeshTab.pMeshRouteTab->Content[i]; + + if (pEntry->Valid) + { + COPY_MAC_ADDR(rt_table->Entry[rt_table->Num].MeshDA, pEntry->MeshDA); + rt_table->Entry[rt_table->Num].Dsn = pEntry->Dsn; + COPY_MAC_ADDR(rt_table->Entry[rt_table->Num].NextHop, pEntry->NextHop); + rt_table->Entry[rt_table->Num].Metric = pEntry->PathMetric; + rt_table->Num++; + } + } + + wrq->u.data.length = sizeof(RT_MESH_ROUTE_TABLE); + Status = copy_to_user(wrq->u.data.pointer, rt_table, wrq->u.data.length); + + if (rt_table) +/* kfree(rt_table); */ + os_free_mem(NULL, rt_table); + + DBGPRINT(RT_DEBUG_OFF, ("Query::OID_802_11_MESH_ROUTE_LIST \n")); + } + break; + + case OID_802_11_MESH_MAX_TX_RATE: + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &pAd->MeshTab.MeshMaxTxRate, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_CHANNEL (=%d)\n", pAd->MeshTab.MeshChannel)); + break; + + case OID_802_11_MESH_CHANNEL: + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &pAd->MeshTab.MeshChannel, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_CHANNEL (=%d)\n", pAd->MeshTab.MeshChannel)); + break; + + case OID_802_11_MESH_HOSTNAME: + wrq->u.data.length = strlen((PSTRING) pAd->MeshTab.HostName) + 1; + Status = copy_to_user(wrq->u.data.pointer, &pAd->MeshTab.HostName, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_HOSTNAME (MeshHostName=%s)\n", pAd->MeshTab.HostName)); + break; + case OID_802_11_MESH_ONLY_MODE: + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &pAd->MeshTab.MeshOnly, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_ONLY_MODE (=%s)\n", pAd->MeshTab.MeshOnly == TRUE ? "Enable" : "Disable")); + break; +#endif /* MESH_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->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->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 */ + +#ifdef EASY_CONFIG_SETUP + case OID_PIN_OF_ENROLLEE: + os_alloc_mem(NULL, &pStaMacAddr, MAC_ADDR_LEN); + if (pStaMacAddr) + { + Status = copy_from_user(pStaMacAddr, wrq->u.data.pointer, MAC_ADDR_LEN); + if (Status == NDIS_STATUS_SUCCESS) + { + PMAC_TABLE_ENTRY pEntry = NULL; + PEASY_CONFIG_INFO pEasyConf = &pAd->ApCfg.MBSSID[pObj->ioctl_if].EasyConfigInfo; + + DBGPRINT(RT_DEBUG_TRACE,("Query::OID_PIN_OF_ENROLLEE(STA - %02X:%02X:%02X:%02X:%02X:%02X)\n", + pStaMacAddr[0], + pStaMacAddr[1], + pStaMacAddr[2], + pStaMacAddr[3], + pStaMacAddr[4], + pStaMacAddr[5])); + pEntry = MacTableLookup(pAd, pStaMacAddr); + if (pEntry && pEntry->bRaAutoWpsCapable) + { + wrq->u.data.length = 8; + Status = copy_to_user(wrq->u.data.pointer, pEasyConf->WpsPinCode, wrq->u.data.length); + } + else + wrq->u.data.length = 0; + } + os_free_mem(NULL, pStaMacAddr); + } + break; +#endif /* EASY_CONFIG_SETUP */ + +#ifdef WAC_SUPPORT + case RT_OID_WAC_REQ: + if (wrq->u.data.length < sizeof(WAC_REQUEST)) + { + Status = -EINVAL; + } + else + { + WAC_IoctlReq(pAd, pObj->ioctl_if, wrq); + } + break; +#endif /* WAC_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; + + 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; + } + + 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) + { + switch(pAd->CommonCfg.PhyMode) + { + case PHY_11BG_MIXED: /* 0 */ + case PHY_11B: /* 1 */ + case PHY_11G: /* 4 */ +#ifdef DOT11_N_SUPPORT + case PHY_11N_2_4G: /* 6 */ + case PHY_11GN_MIXED: /* 7 */ + case PHY_11BGN_MIXED: /* 9 */ +#endif /* DOT11_N_SUPPORT */ + if (pAd->CommonCfg.CountryRegionForABand & 0x80) + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryString_Proc::parameter of CountryRegion in eeprom is programmed \n")); + success = FALSE; + } + else + { + if (allCountry[index].SupportGBand == TRUE) + { + NdisZeroMemory(pAd->CommonCfg.CountryCode, 3); + NdisMoveMemory(pAd->CommonCfg.CountryCode, allCountry[index].IsoName, 2); + pAd->CommonCfg.CountryCode[2] = ' '; + + pAd->CommonCfg.bCountryFlag = TRUE; + + pAd->CommonCfg.CountryRegion = (UCHAR) allCountry[index].RegDomainNum11G; + + /* 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); */ + + success = TRUE; + } + else + { + success = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("The Country are not Support G Band Channel\n")); + } + } + + break; + case PHY_11A: /* 2 */ +#ifdef DOT11_N_SUPPORT + case PHY_11AN_MIXED: /* 8 */ + case PHY_11N_5G: /* 11 */ +#endif /* DOT11_N_SUPPORT */ + if (pAd->CommonCfg.CountryRegion & 0x80) + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryString_Proc::parameter of CountryRegion in eeprom is programmed \n")); + success = FALSE; + } + else + { + if (allCountry[index].SupportABand == TRUE) + { + NdisZeroMemory(pAd->CommonCfg.CountryCode, 3); + NdisMoveMemory(pAd->CommonCfg.CountryCode, allCountry[index].IsoName, 2); + pAd->CommonCfg.CountryCode[2] = ' '; + + pAd->CommonCfg.bCountryFlag = TRUE; + + pAd->CommonCfg.CountryRegionForABand = (UCHAR) allCountry[index].RegDomainNum11A; + + /* 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); */ + + success = TRUE; + } + else + { + success = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("The Country are not Support A Band Channel\n")); + } + } + break; + + default : + success = FALSE; + break; + } + } + + if (success == 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; +} + + +/* + ========================================================================== + Description: + Set SSID + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_SSID_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + INT success = FALSE; + POS_COOKIE pObj = (POS_COOKIE) pAdapter->OS_Cookie; + + if(strlen(arg) <= MAX_LEN_OF_SSID) + { + NdisZeroMemory(pAdapter->ApCfg.MBSSID[pObj->ioctl_if].Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAdapter->ApCfg.MBSSID[pObj->ioctl_if].Ssid, arg, strlen(arg)); + pAdapter->ApCfg.MBSSID[pObj->ioctl_if].SsidLen = (UCHAR)strlen(arg); + success = TRUE; + + +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + if (P2P_GO_ON(pAdapter)) + { + P2P_GoStop(pAdapter); + P2P_GoStartUp(pAdapter, MAIN_MBSSID); + DBGPRINT(RT_DEBUG_TRACE, ("I/F(p2p%d) Set_SSID_Proc::(Len=%d,Ssid=%s)\n", pObj->ioctl_if, + pAdapter->ApCfg.MBSSID[pObj->ioctl_if].SsidLen, pAdapter->ApCfg.MBSSID[pObj->ioctl_if].Ssid)); + } + } + else +#endif /* P2P_SUPPORT */ + { + /* If in detection mode, need to stop detect first. */ + if (pAdapter->CommonCfg.bIEEE80211H == FALSE) + { + APStop(pAdapter); + APStartUp(pAdapter); + } + else + { + /* each mode has different restart method */ + if (pAdapter->Dot11_H.RDMode == RD_SILENCE_MODE) + { + APStop(pAdapter); + APStartUp(pAdapter); + } + else if (pAdapter->Dot11_H.RDMode == RD_SWITCHING_MODE) + { + } + else if (pAdapter->Dot11_H.RDMode == RD_NORMAL_MODE) + { + APStop(pAdapter); + APStartUp(pAdapter); + AsicEnableBssSync(pAdapter); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Set_SSID_Proc::(Len=%d,Ssid=%s)\n", pObj->ioctl_if, + pAdapter->ApCfg.MBSSID[pObj->ioctl_if].SsidLen, pAdapter->ApCfg.MBSSID[pObj->ioctl_if].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( + IN PRTMP_ADAPTER pAd, + IN 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; +} + +#ifdef RT305x +INT Set_RfRead_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + int i; + UCHAR Value; + + for (i = 0; i < 32; i++) + { + RT30xxReadRFRegister(pAdapter, i, &Value); + printk("%02x ", Value); + if (((i + 1) % 4) == 0) + printk("\n"); + } + return TRUE; +} + +INT Set_RfWrite_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + ULONG offset = 0; + ULONG value = 0; + PUCHAR p2 = (PUCHAR)arg; + + while((*p2 != ':') && (*p2 != '\0')) + { + p2++; + } + + if (*p2 == ':') + { + A2Hex(offset, arg); + A2Hex(value, p2+ 1); + } + else + { + A2Hex(value, arg); + } + + if (offset >= 32) + { + return FALSE; + } + + RT30xxWriteRFRegister(pAdapter, offset, value); + + return TRUE; +} +#endif /* RT305x */ + + +/* + ========================================================================== + 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].bWmmCapable = TRUE; + else if (bWmmCapable == 0) + pAd->ApCfg.MBSSID[pObj->ioctl_if].bWmmCapable = FALSE; + else + return FALSE; /*Invalid argument */ + + pAd->ApCfg.MBSSID[pObj->ioctl_if].bWmmCapableOrg = \ + pAd->ApCfg.MBSSID[pObj->ioctl_if].bWmmCapable; + +#ifdef RTL865X_FAST_PATH + if (!isFastPathCapable(pAd)) { + rtlairgo_fast_tx_unregister(); + rtl865x_extDev_unregisterUcastTxDev(pAd->net_dev); + } +#endif + +#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].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=%ld)\n", + pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].IsolateInterStaTraffic)); + + 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=%ld)\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; + + pAd->ApCfg.MBSSID[pObj->ioctl_if].VLAN_VID = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_VLANID_Proc::(VLAN_VID=%d)\n", pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].VLAN_VID)); + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set VLAN's priority field + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_VLANPriority_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + pAd->ApCfg.MBSSID[pObj->ioctl_if].VLAN_Priority = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_VLANPriority_Proc::(VLAN_Priority=%d)\n", pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].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( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + BOOLEAN bVLAN_Tag; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + 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 + + if (pAd->ApCfg.MBSSID[pObj->ioctl_if].bVLAN_Tag != bVLAN_Tag) + { + pAd->ApCfg.MBSSID[pObj->ioctl_if].bVLAN_Tag = bVLAN_Tag; + } + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_VLAN_TAG_Proc::(VLAN_Tag=%d)\n", pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].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; + + 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; + } + } + + /* reset the PortSecure this BSS */ + pAd->ApCfg.MBSSID[apidx].PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + /* Default key index is always 2 in WPA mode */ + if(pAd->ApCfg.MBSSID[apidx].AuthMode >= Ndis802_11AuthModeWPA) + pAd->ApCfg.MBSSID[apidx].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; + + if ((strcmp(arg, "NONE") == 0) || (strcmp(arg, "none") == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11WEPDisabled; + else if ((strcmp(arg, "WEP") == 0) || (strcmp(arg, "wep") == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11WEPEnabled; + else if ((strcmp(arg, "TKIP") == 0) || (strcmp(arg, "tkip") == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11Encryption2Enabled; + else if ((strcmp(arg, "AES") == 0) || (strcmp(arg, "aes") == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11Encryption3Enabled; + else if ((strcmp(arg, "TKIPAES") == 0) || (strcmp(arg, "tkipaes") == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11Encryption4Enabled; +#ifdef WAPI_SUPPORT + else if ((strcmp(arg, "SMS4") == 0) || (strcmp(arg, "sms4") == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11EncryptionSMS4Enabled; +#endif /* WAPI_SUPPORT */ + else + return FALSE; + + if (pAd->ApCfg.MBSSID[apidx].WepStatus >= Ndis802_11Encryption2Enabled) + pAd->ApCfg.MBSSID[apidx].DefaultKeyId = 1; + + /* decide the group key encryption type */ + if (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11Encryption4Enabled) + pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus = Ndis802_11Encryption2Enabled; + else + pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus = pAd->ApCfg.MBSSID[apidx].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, pAd->ApCfg.MBSSID[apidx].WepStatus)); + + 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; + + /* + 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) + */ + if ((strncmp(arg, "WPA_AES_WPA2_TKIPAES", 20) == 0) || (strncmp(arg, "wpa_aes_wpa2_tkipaes", 20) == 0)) + pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher = WPA_AES_WPA2_TKIPAES; + else if ((strncmp(arg, "WPA_AES_WPA2_TKIP", 17) == 0) || (strncmp(arg, "wpa_aes_wpa2_tkip", 17) == 0)) + pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher = WPA_AES_WPA2_TKIP; + else if ((strncmp(arg, "WPA_TKIP_WPA2_AES", 17) == 0) || (strncmp(arg, "wpa_tkip_wpa2_aes", 17) == 0)) + pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher = WPA_TKIP_WPA2_AES; + else if ((strncmp(arg, "WPA_TKIP_WPA2_TKIPAES", 21) == 0) || (strncmp(arg, "wpa_tkip_wpa2_tkipaes", 21) == 0)) + pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher = WPA_TKIP_WPA2_TKIPAES; + else if ((strncmp(arg, "WPA_TKIPAES_WPA2_AES", 20) == 0) || (strncmp(arg, "wpa_tkipaes_wpa2_aes", 20) == 0)) + pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher = WPA_TKIPAES_WPA2_AES; + else if ((strncmp(arg, "WPA_TKIPAES_WPA2_TKIPAES", 24) == 0) || (strncmp(arg, "wpa_tkipaes_wpa2_tkipaes", 24) == 0)) + pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIPAES; + else if ((strncmp(arg, "WPA_TKIPAES_WPA2_TKIP", 21) == 0) || (strncmp(arg, "wpa_tkipaes_wpa2_tkip", 21) == 0)) + pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIP; + else + return FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Set_AP_WpaMixPairCipher_Proc=0x%02x\n", apidx, pAd->ApCfg.MBSSID[apidx].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; +} + +#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")); + + 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; +} + +/* + ========================================================================== + 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].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].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].AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + RTMP_ASIC_SHARED_KEY_TABLE(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].AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + RTMP_ASIC_SHARED_KEY_TABLE(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].AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + RTMP_ASIC_SHARED_KEY_TABLE(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].AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + RTMP_ASIC_SHARED_KEY_TABLE(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")); + 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; + +#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; + +} + + +/* + ========================================================================== + 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( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + printk("Driver version: %s\n", AP_DRIVER_VERSION); + + return TRUE; +} + +INT Show_MacTable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i;/*, QueIdx=0; */ + UINT32 RegValue; + ULONG DataRate=0; + /*PRXD_STRUC pRxD; */ + /*PTXD_STRUC pTxD; */ + /*PRTMP_TX_RING pTxRing = &pAd->TxRing[QueIdx]; */ + /*PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing; */ + /*PRTMP_RX_RING pRxRing = &pAd->RxRing; */ + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + + 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"); + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + for (i=0; i < MaxWcidNum; i++) + { + PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.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; + getRate(pEntry->HTPhyMode, &DataRate); + 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->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", GetPhyMode(pEntry->HTPhyMode.field.MODE)); + printk("%-6s", GetBW(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_StaCount_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i;/*, QueIdx=0; */ + 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_StaSecurityInfo_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i; + UCHAR apidx; + + printk("\n"); + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + printk(" BSS(%d) AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s, WPAMixPairCipher(0x%02X)\n", + apidx, + pAd->ApCfg.MBSSID[apidx].AuthMode, + GetAuthMode(pAd->ApCfg.MBSSID[apidx].AuthMode), + pAd->ApCfg.MBSSID[apidx].WepStatus, + GetEncryptType(pAd->ApCfg.MBSSID[apidx].WepStatus), + pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus, + GetEncryptType(pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus), + pAd->ApCfg.MBSSID[apidx].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 ", + 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->apidx); + printk("%-15s", GetAuthMode(pEntry->AuthMode)); + printk("%-12s", GetEncryptType(pEntry->WepStatus)); + printk("\n"); + } + } + + return TRUE; +} + + +#ifdef DOT11_N_SUPPORT +INT Show_BaTable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i, j; + BA_ORI_ENTRY *pOriBAEntry; + BA_REC_ENTRY *pRecBAEntry; + STRING tmpBuf[6]; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + for (i=0; i < MaxWcidNum; 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)) + 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", + pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], + pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5], 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( + IN PRTMP_ADAPTER pAd, + IN 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 */ + +#if defined (RT2883) || defined (RT3883) + DBGPRINT(RT_DEBUG_OFF, ("FixedRate: %d\n", pAd->CommonCfg.FixedRate)); +#endif /* defined (RT2883) || defined (RT3883) */ + +#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 RTMP_MAC_PCI +#ifdef DBG_DIAGNOSE +INT Set_DiagOpt_Proc( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT32 i, QueIdx=0; + ULONG RegValue; + PRXD_STRUC pRxD; + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PRXD_STRUC pDestRxD; + RXD_STRUC RxD; + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; +#endif /* RT_BIG_ENDIAN */ + PRTMP_TX_RING pTxRing = &pAd->TxRing[QueIdx]; + PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing; + PRTMP_RX_RING pRxRing = &pAd->RxRing; + + printk("\n"); + RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue); + printk("BackOff Slot : %s slot time, BKOFF_SLOT_CFG(0x1104) = 0x%08lx\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.RxSwReadIdx, + pAd->RxRing.RxCpuIdx, + pAd->RxRing.RxDmaIdx); + +#ifdef RT_BIG_ENDIAN + pDestRxD = (PRXD_STRUC) pRxRing->Cell[pAd->RxRing.RxSwReadIdx].AllocVa; + RxD = *pDestRxD; + pRxD = &RxD; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + pRxD = (PRXD_STRUC) pRxRing->Cell[pAd->RxRing.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.RxCpuIdx].AllocVa; + RxD = *pDestRxD; + pRxD = &RxD; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + pRxD = (PRXD_STRUC) pRxRing->Cell[pAd->RxRing.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.RxDmaIdx].AllocVa; + RxD = *pDestRxD; + pRxD = &RxD; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + pRxD = (PRXD_STRUC) pRxRing->Cell[pAd->RxRing.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", GetPhyMode(pEntry->HTPhyMode.field.MODE)); + printk("%-6s", GetBW(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; +} + +INT Show_Diag_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + RtmpDiagStruct *pDiag; + UCHAR i, start, stop, McsIdx, SwQNumLevel, TxDescNumLevel; + unsigned long irqFlags; + UCHAR McsMaxIdx = MAX_MCS_SET; + + +#ifdef DOT11N_SS3_SUPPORT + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + McsMaxIdx = 24; +#endif /* DOT11N_SS3_SUPPORT */ + pDiag = &pAd->DiagStruct; + + if (pDiag->inited == FALSE) + return TRUE; + + RTMP_IRQ_LOCK(&pAd->irq_lock, irqFlags); + 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->TxDataCnt[i]); + } + printk("\n %-12s", "TxFailCnt"); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->TxFailCnt[i]); + } + printk("\n %-12s", "TxAggCnt"); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->TxAggCnt[i]); + } + printk("\n"); + + + 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->TxSWQueCnt[i][SwQNumLevel]); + } + printk("\n"); + } + + 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->TxDescCnt[i][TxDescNumLevel]); + } + printk("\n"); + } + +#ifdef DOT11_N_SUPPORT + 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->TxAMPDUCnt[i][McsIdx], pDiag->TxAMPDUCnt[i][McsIdx] ? (pDiag->TxAMPDUCnt[i][McsIdx] * 100 / pDiag->TxAggCnt[i]) : 0); + } +/* printk("\n\t%-6s", "R(%)"); */ +/* for (i = start, count=0; count < DIAGNOSE_TIME; i = (i+1) % DIAGNOSE_TIME, count++) */ +/* { */ +/* printk("%-5d", pDiag->TxAMPDUCnt[i][McsIdx] ? (pDiag->TxAMPDUCnt[i][McsIdx] * 100 / pDiag->TxTotalCnt[i]) : 0); */ +/* } */ + printk("\n"); + } +#endif /* DOT11_N_SUPPORT */ + + printk("\n %-12s\n", "TxMcsCnt"); + for (McsIdx =0 ; McsIdx < McsMaxIdx; McsIdx++) + { + printk("\t%-6d", McsIdx); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->TxMcsCnt[i][McsIdx]); + } + printk("\n"); + } + + printk("Rx Info\n"); + printk(" %-12s", "RxDataCnt"); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->RxDataCnt[i]); + } + printk("\n %-12s", "RxCrcErrCnt"); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->RxCrcErrCnt[i]); + } + printk("\n %-12s\n", "RxMcsCnt"); + for (McsIdx =0 ; McsIdx < McsMaxIdx; McsIdx++) /* 3*3 */ + { + printk("\t%-6d", McsIdx); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->RxMcsCnt[i][McsIdx]); + } + printk("\n"); + } + printk("\n-------------\n"); + + RTMP_IRQ_UNLOCK(&pAd->irq_lock, irqFlags); + + return TRUE; + +} +#endif /* DBG_DIAGNOSE */ +#endif /* RTMP_MAC_PCI */ + + +#ifdef DOT11_N_SUPPORT +#if defined(RT2883) || defined(RT3883) +#define MAX_AGG_CNT 16 +#else +#define MAX_AGG_CNT 8 +#endif /* defined(RT2883) || defined(RT3883) */ + +/* DisplayTxAgg - display Aggregation statistics from MAC */ +static void DisplayTxAgg ( + IN PRTMP_ADAPTER pAd) +{ + TX_AGG_CNT_STRUC TxAggCnt; + TX_AGG_CNT0_STRUC TxAggCnt0; + TX_AGG_CNT1_STRUC TxAggCnt1; + TX_AGG_CNT2_STRUC TxAggCnt2; + TX_AGG_CNT3_STRUC TxAggCnt3; +#if MAX_AGG_CNT>8 + TX_AGG_CNTN_STRUC TxAggCntN; + static USHORT aggReg[] = { + TX_AGG_CNT4, TX_AGG_CNT5, TX_AGG_CNT6, TX_AGG_CNT7, + }; +#endif + + UINT32 totalCount; + UINT32 aggCnt[MAX_AGG_CNT]; + int i; + + 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); + + aggCnt[0] = TxAggCnt0.field.AggSize1Count; + aggCnt[1] = TxAggCnt0.field.AggSize2Count; + aggCnt[2] = TxAggCnt1.field.AggSize3Count; + aggCnt[3] = TxAggCnt1.field.AggSize4Count; + aggCnt[4] = TxAggCnt2.field.AggSize5Count; + aggCnt[5] = TxAggCnt2.field.AggSize6Count; + aggCnt[6] = TxAggCnt3.field.AggSize7Count; + aggCnt[7] = TxAggCnt3.field.AggSize8Count; + +#if MAX_AGG_CNT>8 + for (i=0; i<(MAX_AGG_CNT-8)/2; i++) { + RTMP_IO_READ32(pAd, aggReg[i], &TxAggCntN.word); + aggCnt[2*i + 8] = TxAggCntN.field.AggSizeLowCount; + aggCnt[2*i + 9] = TxAggCntN.field.AggSizeHighCount; + } +#endif + + totalCount = TxAggCnt.field.NonAggTxCount + TxAggCnt.field.AggTxCount; + if (totalCount > 0) + for (i=0; iWlanCounters.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); +#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 = %ld\n", (ULONG)pAd->ApCfg.MBSSID[apidx].RxCount); + printk("Packets Sent = %ld\n", (ULONG)pAd->ApCfg.MBSSID[apidx].TxCount); + printk("Bytes Received = %ld\n", (ULONG)pAd->ApCfg.MBSSID[apidx].ReceivedByteCount); + printk("Byte Sent = %ld\n", (ULONG)pAd->ApCfg.MBSSID[apidx].TransmittedByteCount); + printk("Error Packets Received = %ld\n", (ULONG)pAd->ApCfg.MBSSID[apidx].RxErrorCount); + printk("Drop Received Packets = %ld\n", (ULONG)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 - ", + 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]); + } + } + } + } + } + } + +} + +#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); +#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; +#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); + + 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->IEEE8021X) ? 1 : 0; + + if (p1xBssInfo->ieee8021xWEP) + { + /* Default Key index, length and material */ + keyidx = pMbss->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; + + if ((pAd->ApCfg.MBSSID[pObj->ioctl_if].AuthMode == Ndis802_11AuthModeWPA) + || (pAd->ApCfg.MBSSID[pObj->ioctl_if].AuthMode == Ndis802_11AuthModeWPA2) + || (pAd->ApCfg.MBSSID[pObj->ioctl_if].AuthMode == Ndis802_11AuthModeWPA1WPA2) + || (pAd->ApCfg.MBSSID[pObj->ioctl_if].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].AuthMode >= Ndis802_11AuthModeWPA) + { + if ((pKey->KeyLength == 32) || (pKey->KeyLength == 64)) + { + if ((pEntry = MacTableLookup(pAd, pKey->addr)) != NULL) + { + INT k_offset = 0; + + + 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; + PUCHAR Key; + + 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].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; + Key = pAd->SharedKey[apidx][KeyIdx].Key; + + /* Set Group key material to Asic */ + RTMP_ASIC_SHARED_KEY_TABLE(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->Aid, + &pEntry->PairwiseKey); + + /* update WCID attribute table and IVEIV table for this entry */ + RTMPSetWcidSecurityInfo(pAd, + pEntry->apidx, + (UINT8)KeyIdx, + pEntry->PairwiseKey.CipherAlg, + pEntry->Aid, + 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].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].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 + { + UINT32 len; + + len = 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].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->Aid, + &pEntry->PairwiseKey); + + /* update WCID attribute table and IVEIV table for this entry */ + RTMPSetWcidSecurityInfo(pAd, + pEntry->apidx, + (UINT8)KeyIdx, + pEntry->PairwiseKey.CipherAlg, + pEntry->Aid, + 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; +} +#endif /* DOT1X_SUPPORT */ + +#ifdef DBG +/* + ========================================================================== + 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) +{ + 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; + + + + 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; + bCopyMsg = ((wrq->u.data.flags & RTPRIV_IOCTL_FLAG_NOSPACE) == RTPRIV_IOCTL_FLAG_NOSPACE) ? 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); + 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); + 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); + 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); + 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")); +} + + +/* + ========================================================================== + 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 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; + UINT32 macAddr = 0; + UCHAR temp[16]; + STRING temp2[16]; + UINT32 macValue; + BOOLEAN bIsPrintAllMAC = FALSE, bFromUI; + + +/* 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; + } + + 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); + 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 */ + /* 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; */ + } + + /* 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(pAdapter, macAddr, &macValue); + if (!bFromUI) + DBGPRINT(RT_DEBUG_ERROR, ("MacAddr=0x%x, MacValue=0x%x\n", macAddr, macValue)); + sprintf(msg+strlen(msg), "[0x%08x]:%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; /* 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[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) + { + pAdapter->BbpTuning.bEnable = TRUE; + DBGPRINT(RT_DEBUG_ERROR, ("turn on R17 tuning\n")); + } + else + { + UCHAR R66; + pAdapter->BbpTuning.bEnable = FALSE; + R66 = 0x26 + GET_LNA_GAIN(pAdapter); + /* todo AsicBBPWriteWithRxChain(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)), RX_CHAIN_ALL); */ + if (!bFromUI) + DBGPRINT(RT_DEBUG_ERROR, ("turn off R66 tuning, restore to 0x%02x\n", R66)); + } + goto done; + } + if (!bFromUI) + DBGPRINT(RT_DEBUG_ERROR, ("MacAddr=%02x, MacValue=0x%x\n", macAddr, macValue)); + + RTMP_IO_WRITE32(pAdapter, macAddr, macValue); + sprintf(msg+strlen(msg), "[0x%08x]:%08x ", macAddr, macValue); + } + } + } + } else { + UINT32 IdMac; + + for(IdMac=0; IdMac<=0x2000; IdMac+=4) + { + if ((IdMac & 0x0f) == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("\n0x%04x: ", IdMac)); + } + + RTMP_IO_READ32(pAdapter, IdMac, &macValue); + DBGPRINT(RT_DEBUG_TRACE, ("%08x ", macValue)); + } + + bIsPrintAllMAC = TRUE; + } + + + 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_TRACE, ("<==RTMPIoctlMAC\n\n")); +} + + +#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); + + 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 RF_BANK + if (IS_RT6352(pAdapter)) + ATE_RF_IO_READ8_BY_REG_ID(pAdapter, pAdapter->RfBank, rfId, ®RF); +#else + ATE_RF_IO_READ8_BY_REG_ID(pAdapter, rfId, ®RF); +#endif /* RF_BANK */ + /* 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 + ATE_RF_IO_READ8_BY_REG_ID(pAdapter, rfId, ®RF); + ATE_RF_IO_WRITE8_BY_REG_ID(pAdapter, (UCHAR)rfId,(UCHAR) rfValue); +#endif + + + /* Read it back for showing. */ +#ifdef RF_BANK + if (IS_RT6352(pAdapter)) + ATE_RF_IO_READ8_BY_REG_ID(pAdapter, pAdapter->RfBank, rfId, ®RF); +#else + ATE_RF_IO_READ8_BY_REG_ID(pAdapter, rfId, ®RF); +#endif /* RF_BANK */ + /* 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 RF_BANK + if (IS_RT6352(pAdapter)) + ATE_RF_IO_READ8_BY_REG_ID(pAdapter, pAdapter->RfBank, rfId, ®RF); +#else + ATE_RF_IO_READ8_BY_REG_ID(pAdapter, rfId, ®RF); +#endif /* RF_BANK */ + /* 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"); + } + } + } + /* RtmpDrvAllRFPrint(NULL, msg, strlen(msg)); */ + /* 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 +#ifdef RTMP_EFUSE_SUPPORT +extern VOID eFuseGetFreeBlockCount(PRTMP_ADAPTER pAd, PUINT EfuseFreeBlock); +#endif /* RTMP_EFUSE_SUPPORT */ + + +/* + ========================================================================== + 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( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + INT Status; + PSTRING msg; +#ifdef WSC_AP_SUPPORT + UCHAR idx = 0; +#endif /* WSC_AP_SUPPORT */ +#ifdef P2P_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; +#endif /* P2P_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 */ + +/* 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, 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), "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 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); + sprintf(msg+strlen(msg), "False CCA (one second) = %ld\n", (ULONG)pAd->RalinkCounters.OneSecFalseCCACnt1); +#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[4] = {"CCK", "OFDM", "MM", "GF"}; + + for (i=1; iMacTab.Content[i]); + if (IS_ENTRY_CLIENT(pEntry) && pEntry->Sst==SST_ASSOC) + { + UINT32 lastRxRate = pEntry->LastRxRate; + + sprintf(msg+strlen(msg), "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": " "); + +#if defined(RT2883) || defined(RT3883) + sprintf(msg+strlen(msg), "BF SNR = %d.%02d, %d.%02d, %d.%02d FO:%02X\n", + pEntry->BF_SNR[0]/4, (pEntry->BF_SNR[0] % 4)*25, + pEntry->BF_SNR[1]/4, (pEntry->BF_SNR[1] % 4)*25, + pEntry->BF_SNR[2]/4, (pEntry->BF_SNR[2] % 4)*25, + pEntry->freqOffset & 0xFF); +#endif /* defined(RT2883) || defined(RT3883) */ + 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 P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + if (pAd->ApCfg.ApCliTab[0].WscControl.WscEnrolleePinCodeLen == 8) + sprintf(msg+strlen(msg), "P2P Client PinCode %08u\n", + pAd->ApCfg.ApCliTab[0].WscControl.WscEnrolleePinCode); + else + sprintf(msg+strlen(msg), "P2P Client PinCode %04u\n", + pAd->ApCfg.ApCliTab[0].WscControl.WscEnrolleePinCode); + sprintf(msg+strlen(msg), "P2P Client WPS Profile Count = %d\n", + pAd->ApCfg.ApCliTab[0].WscControl.WscProfile.ProfileCnt); + } + else +#endif /* P2P_SUPPORT */ + { + 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); + } + } +#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 */ +#ifdef RTMP_EFUSE_SUPPORT + if (pAd->bUseEfuse == FALSE && pAd->bFroceEEPROMBuffer == FALSE) + { + ; + } + else + { + eFuseGetFreeBlockCount(pAd, &efusefreenum); + sprintf(msg+strlen(msg), "efuseFreeNumber = %d\n", efusefreenum); + } +#endif /* RTMP_EFUSE_SUPPORT */ + /* 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); + + os_free_mem(NULL, msg); +/* kfree(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) + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s(): Error! Failed to vmalloc for BA table.\n", __FUNCTION__)); + 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)); + + ApCliIfDown(pAd); + + return TRUE; +} + +INT Set_ApCli_Ssid_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR ifIndex; + BOOLEAN apcliEn; + INT success = FALSE; + /*UCHAR keyMaterial[40]; */ + UCHAR PskKey[100]; + + 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) + { + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + + /* bring apcli interface down first */ + if(apcliEn == TRUE ) + { + pAd->ApCfg.ApCliTab[ifIndex].Enable = FALSE; + ApCliIfDown(pAd); + } + + 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); + success = TRUE; + + /* Upadte PMK and restart WPAPSK state machine for ApCli link */ + if (((pAd->ApCfg.ApCliTab[ifIndex].AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->ApCfg.ApCliTab[ifIndex].AuthMode == Ndis802_11AuthModeWPA2PSK)) && + pAd->ApCfg.ApCliTab[ifIndex].PSKLen > 0) + { + NdisZeroMemory(PskKey, 100); + NdisMoveMemory(PskKey, pAd->ApCfg.ApCliTab[ifIndex].PSK, pAd->ApCfg.ApCliTab[ifIndex].PSKLen); + + RT_CfgSetWPAPSKKey(pAd, (PSTRING)PskKey, + pAd->ApCfg.ApCliTab[ifIndex].PSKLen, + (PUCHAR)pAd->ApCfg.ApCliTab[ifIndex].CfgSsid, + pAd->ApCfg.ApCliTab[ifIndex].CfgSsidLen, + pAd->ApCfg.ApCliTab[ifIndex].PMK); + } + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_Ssid_Proc::(Len=%d,Ssid=%s)\n", ifIndex, + pAd->ApCfg.ApCliTab[ifIndex].CfgSsidLen, pAd->ApCfg.ApCliTab[ifIndex].CfgSsid)); + + pAd->ApCfg.ApCliTab[ifIndex].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; + 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 (%02X:%02X:%02X:%02X:%02X:%02X)\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( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG i; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + ifIndex = pObj->ioctl_if; + + if ((strcmp(arg, "WEPAUTO") == 0) || (strcmp(arg, "wepauto") == 0)) + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeAutoSwitch; + else if ((strcmp(arg, "SHARED") == 0) || (strcmp(arg, "shared") == 0)) + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeShared; + else if ((strcmp(arg, "WPAPSK") == 0) || (strcmp(arg, "wpapsk") == 0)) + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeWPAPSK; + else if ((strcmp(arg, "WPA2PSK") == 0) || (strcmp(arg, "wpa2psk") == 0) || (strcmp(arg, "WPAPSKWPA2PSK") == 0)) + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeWPA2PSK; + +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + else if ((strcmp(arg, "WPA") == 0) || (strcmp(arg, "wpa") == 0)) + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeWPA; + else if ((strcmp(arg, "WPA2") == 0) || (strcmp(arg, "wpa2") == 0)) + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeWPA2; +#endif /*APCLI_WPA_SUPPLICANT_SUPPORT */ + + else + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeOpen; + + for (i=0; i < MaxWcidNum; i++) + { + if (IS_ENTRY_APCLI(&pAd->MacTab.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; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_ApCli_AuthMode_Proc::(AuthMode=%d)\n", ifIndex, pAd->ApCfg.ApCliTab[ifIndex].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; + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + pApCliEntry->WepStatus = Ndis802_11WEPDisabled; + if ((strcmp(arg, "WEP") == 0) || (strcmp(arg, "wep") == 0)) + { + if (pApCliEntry->AuthMode < Ndis802_11AuthModeWPA) + pApCliEntry->WepStatus = Ndis802_11WEPEnabled; + } + else if ((strcmp(arg, "TKIP") == 0) || (strcmp(arg, "tkip") == 0)) + { + if (pApCliEntry->AuthMode >= Ndis802_11AuthModeWPA) + pApCliEntry->WepStatus = Ndis802_11Encryption2Enabled; + } + else if ((strcmp(arg, "AES") == 0) || (strcmp(arg, "aes") == 0) || (strcmp(arg, "TKIPAES") == 0)) + { + if (pApCliEntry->AuthMode >= Ndis802_11AuthModeWPA) + pApCliEntry->WepStatus = Ndis802_11Encryption3Enabled; + } + else + { + pApCliEntry->WepStatus = Ndis802_11WEPDisabled; + } + + pApCliEntry->PairCipher = pApCliEntry->WepStatus; + pApCliEntry->GroupCipher = pApCliEntry->WepStatus; + pApCliEntry->bMixCipher = FALSE; + + if (pApCliEntry->WepStatus >= Ndis802_11Encryption2Enabled) + pApCliEntry->DefaultKeyId = 1; + + RTMPMakeRSNIE(pAd, pApCliEntry->AuthMode, pApCliEntry->WepStatus, (ifIndex + MIN_NET_DEVICE_FOR_APCLI)); + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_ApCli_EncrypType_Proc::(EncrypType=%d)\n", ifIndex, pApCliEntry->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; + UCHAR ifIndex; + PAPCLI_STRUCT pApCliEntry = NULL; + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + KeyIdx = simple_strtol(arg, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + pApCliEntry->DefaultKeyId = (UCHAR) (KeyIdx - 1 ); + else + return FALSE; /* Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_DefaultKeyID_Proc::(DefaultKeyID(0~3)=%d)\n", ifIndex, pApCliEntry->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; + + NdisMoveMemory(pApCliEntry->PSK, arg, strlen(arg)); + pApCliEntry->PSKLen = strlen(arg); + + 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; + 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->DesiredTransmitSetting.field.FixedTxMode = + RT_CfgSetFixedTxPhyMode(arg); + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_TxMode_Proc = %d\n", ifIndex, + pApCliEntry->DesiredTransmitSetting.field.FixedTxMode)); + + return TRUE; +} + +INT Set_ApCli_TxMcs_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->DesiredTransmitSetting.field.MCS = + RT_CfgSetTxMCSProc(arg, &pApCliEntry->bAutoTxRateSwitch); + + if (pApCliEntry->DesiredTransmitSetting.field.MCS == MCS_AUTO) + { + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_TxMcs_Proc = AUTO\n", ifIndex)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_TxMcs_Proc = %d\n", ifIndex, + pApCliEntry->DesiredTransmitSetting.field.MCS)); + } + + return TRUE; +} + + +#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->IEEE8021X = TRUE; + else if (ieee8021x == 0) + pApCliEntry->IEEE8021X = FALSE; + else + return FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_ApCli_IEEE8021X_Proc::(IEEE8021X=%d)\n", pObj->ioctl_if, pApCliEntry->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, (" Repeate Mode (OFF)\n")); + } + RTMP_IO_WRITE32(pAd, MAC_ADDR_EXT_EN, MacReg); + + DBGPRINT(RT_DEBUG_WARN, (" MACRepeaterEn = %d \n", pAd->ApCfg.bMACRepeaterEn)); + + return TRUE; +} + +#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; + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + pApCfg = &pAd->ApCfg; + ifIndex = pObj->ioctl_if; + + if (pApCfg->ApCliAutoConnectRunning == FALSE) + { + Set_ApCli_Enable_Proc(pAd, "0"); + pApCfg->ApCliAutoConnectRunning = TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Set_ApCli_AutoConnect_Proc() is still running\n")); + return 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)); + + + /* + use site survey function to trigger auto connecting (when pAd->ApCfg.ApAutoConnectRunning == TRUE) + */ + Set_SiteSurvey_Proc(pAd, "");//pApCfg->ApCliTab[ifIndex].CfgSsid); + + return TRUE; +} +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + +#endif /* MAC_REPEATER_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 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 */ + +#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; +} +#endif /* APCLI_CERT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + + +#ifdef WSC_AP_SUPPORT +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 == TRUE) + { + 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 */ +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + if (P2P_CLI_ON(pAd)) + { + bFromApCli = TRUE; + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + } + else + { + bFromApCli = FALSE; + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_WscConfMode_Proc:: This command is from p2p interface now.\n", apidx)); + } + else +#endif /* P2P_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)); + } + + 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; + WscInit(pAd, TRUE, apidx); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_WscConfMode_Proc:: Ap Client only supports Enrollee mode.(ConfModeIdx=%d)\n", apidx, ConfModeIdx)); + return FALSE; + } + } + 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].CurrentAddress[0], MAC_ADDR_LEN); + } + else +#endif /* APCLI_SUPPORT */ + { + memcpy(mac_addr, &pAd->ApCfg.MBSSID[apidx].Bssid[0], MAC_ADDR_LEN); + } + + DBGPRINT(RT_DEBUG_TRACE, ("IF(%02X:%02X:%02X:%02X:%02X:%02X) Set_WscConfMode_Proc::(WscConfMode(0~7)=%d)\n", + mac_addr[0], + mac_addr[1], + mac_addr[2], + mac_addr[3], + mac_addr[4], + mac_addr[5], + 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 == TRUE) + { + 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 */ + +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + if (P2P_CLI_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_WscConfStatus_Proc:: P2P Client doesn't need this command.\n", apidx)); + return FALSE; + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_WscConfStatus_Proc:: This command is from p2p interface now.\n", apidx)); + } +#endif /* P2P_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", + pAd->ApCfg.MBSSID[apidx].Bssid[0], + pAd->ApCfg.MBSSID[apidx].Bssid[1], + pAd->ApCfg.MBSSID[apidx].Bssid[2], + pAd->ApCfg.MBSSID[apidx].Bssid[3], + pAd->ApCfg.MBSSID[apidx].Bssid[4], + pAd->ApCfg.MBSSID[apidx].Bssid[5], + 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 == TRUE) + { + 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 */ +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + if (P2P_CLI_ON(pAd)) + { + bFromApCli = TRUE; + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + } + else + { + bFromApCli = FALSE; + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_WscMode_Proc:: This command is from p2p interface now.\n", apidx)); + } + else +#endif /* P2P_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].CurrentAddress, MAC_ADDR_LEN); + } + else +#endif /* APCLI_SUPPORT */ + { + memcpy(mac_addr, pAd->ApCfg.MBSSID[apidx].Bssid, MAC_ADDR_LEN); + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(%02X:%02X:%02X:%02X:%02X:%02X) Set_WscMode_Proc::(WscMode=%d)\n", + mac_addr[0], + mac_addr[1], + mac_addr[2], + mac_addr[3], + mac_addr[4], + mac_addr[5], + 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 = pAd->ApCfg.ApCliTab[apidx].Enable; +#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 == TRUE) + { + 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 (apcliEn == FALSE) + 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); + 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 */ +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + if (P2P_CLI_ON(pAd)) + { + bFromApCli = TRUE; + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + } + else + { + bFromApCli = FALSE; + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_AP_WscGetConf_Proc:: This command is from p2p interface now.\n", apidx)); + } + else +#endif /* P2P_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)); + } + + 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 P2P_SUPPORT + if (pAd->P2pCfg.Dpid != DEV_PASS_ID_NOSPEC) + WscMode = pAd->P2pCfg.Dpid; +#endif /* P2P_SUPPORT */ + WscInitRegistrarPair(pAd, pWscControl, apidx); + /* Enrollee 192 random bytes for DH key generation */ + for (idx = 0; idx < 192; idx++) + pWscControl->RegData.EnrolleeRandom[idx] = RandomByte(pAd); + +#ifdef APCLI_SUPPORT + if (bFromApCli) + { + /* bring apcli interface down first */ + pAd->ApCfg.ApCliTab[apidx].Enable = FALSE; + ApCliIfDown(pAd); + + if (WscMode == DEV_PASS_ID_PIN) + { + NdisMoveMemory(pWscControl->RegData.SelfInfo.MacAddr, + pAd->ApCfg.ApCliTab[apidx].CurrentAddress, + 6); + + pAd->ApCfg.ApCliTab[apidx].Enable = apcliEn; + NdisMoveMemory(mac_addr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress, 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].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].Bssid, 3, 0, AP_MODE); + } + else + { + RTMP_SEM_LOCK(&pWscControl->WscPeerListSemLock); + WscClearPeerList(&pWscControl->WscPeerList); + RTMP_SEM_UNLOCK(&pWscControl->WscPeerListSemLock); + } + } + +#ifdef WSC_LED_SUPPORT +#ifdef CONFIG_WIFI_LED_SHARE + /* Change FW default mode to HUAWEI WPS 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_SHARE */ + WPSLEDStatus = LED_WPS_IN_PROCESS; + RTMPSetLED(pAd, WPSLEDStatus); +#endif /* WSC_LED_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("IF(%02X:%02X:%02X:%02X:%02X:%02X) Set_WscGetConf_Proc trigger WSC state machine, wscGetConfMode=%d\n", + mac_addr[0], + mac_addr[1], + mac_addr[2], + mac_addr[3], + mac_addr[4], + mac_addr[5], + wscGetConfMode)); + + return TRUE; +} + +INT Set_AP_WscPinCode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT PinCode = 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 == TRUE) + { + 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 */ +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + if (P2P_CLI_ON(pAd)) + { + bFromApCli = TRUE; + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + } + else + { + bFromApCli = FALSE; + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_WscMode_Proc:: This command is from p2p interface now.\n", apidx)); + } + else +#endif /* P2P_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)); + } + + 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:%s)\n", arg)); + return FALSE; + } + else + { + pWscControl->WscPinCode = PinCode; + pWscControl->WscLastPinFromEnrollee = pWscControl->WscPinCode; + pWscControl->WscRejectSamePinFromEnrollee = FALSE; + /* PIN Code */ + if (strlen(arg) == 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].CurrentAddress, MAC_ADDR_LEN); + } + else +#endif /* APCLI_SUPPORT */ + { + memcpy(mac_addr, pAd->ApCfg.MBSSID[apidx].Bssid, MAC_ADDR_LEN); + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(%02X:%02X:%02X:%02X:%02X:%02X) Set_WscPinCode_Proc::(PinCode=%d)\n", + mac_addr[0], + mac_addr[1], + mac_addr[2], + mac_addr[3], + mac_addr[4], + mac_addr[5], + 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 == TRUE) + { + 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_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].Bssid[3], + pAd->ApCfg.MBSSID[apidx].Bssid[4], + pAd->ApCfg.MBSSID[apidx].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 == TRUE) + { + 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; + 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); + } + + 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; + +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[apidx].Hostapd == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + return; + } +#endif /*HOSTAPD_SUPPORT*/ + + + memset(&Profile, 0x00, sizeof(WSC_CONFIGURED_VALUE)); + Profile.WscConfigured = pAd->ApCfg.MBSSID[apidx].WscControl.WscConfStatus; + + NdisZeroMemory(Profile.WscSsid, 32); + NdisMoveMemory(Profile.WscSsid, pAd->ApCfg.MBSSID[apidx].Ssid, + pAd->ApCfg.MBSSID[apidx].SsidLen); + Profile.WscSsidLen = pAd->ApCfg.MBSSID[apidx].SsidLen; + + + if (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + Profile.WscAuthMode = WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK; + else + Profile.WscAuthMode = WscGetAuthType(pAd->ApCfg.MBSSID[apidx].AuthMode); + if (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11Encryption4Enabled) + Profile.WscEncrypType = WSC_ENCRTYPE_TKIP |WSC_ENCRTYPE_AES; + else + Profile.WscEncrypType = WscGetEncryType(pAd->ApCfg.MBSSID[apidx].WepStatus); + NdisZeroMemory(Profile.WscWPAKey, 64); + + if (Profile.WscEncrypType == 2) + { + Profile.DefaultKeyIdx = pAd->ApCfg.MBSSID[apidx].DefaultKeyId + 1; + { + int i; + for (i=0; iSharedKey[apidx][pAd->ApCfg.MBSSID[apidx].DefaultKeyId].KeyLen; i++) + { + snprintf((PSTRING) Profile.WscWPAKey, sizeof(Profile.WscWPAKey), + "%s%02x", Profile.WscWPAKey, + pAd->SharedKey[apidx][pAd->ApCfg.MBSSID[apidx].DefaultKeyId].Key[i]); + } + Profile.WscWPAKeyLen = pAd->SharedKey[apidx][pAd->ApCfg.MBSSID[apidx].DefaultKeyId].KeyLen; + } + } + else if (Profile.WscEncrypType >= 4) + { + Profile.DefaultKeyIdx = 2; + NdisMoveMemory(Profile.WscWPAKey, pAd->ApCfg.MBSSID[apidx].WscControl.WpaPsk, + pAd->ApCfg.MBSSID[apidx].WscControl.WpaPskLen); + Profile.WscWPAKeyLen = pAd->ApCfg.MBSSID[apidx].WscControl.WpaPskLen; + } + 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 (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + sprintf(msg+strlen(msg), "%-12s", "WPAPSKWPA2PSK"); + else + sprintf(msg+strlen(msg), "%-12s", WscGetAuthTypeStr(Profile.WscAuthMode)); + if (pAd->ApCfg.MBSSID[apidx].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); +} + +#ifdef INF_AR9 +#ifdef AR9_MAPI_SUPPORT + +/* + ========================================================================== + 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; + + 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 (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + Profile.WscAuthMode = WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK; + else + Profile.WscAuthMode = WscGetAuthType(pAd->ApCfg.MBSSID[apidx].AuthMode); + if (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11Encryption4Enabled) + Profile.WscEncrypType = WSC_ENCRTYPE_TKIP |WSC_ENCRTYPE_AES; + else + Profile.WscEncrypType = WscGetEncryType(pAd->ApCfg.MBSSID[apidx].WepStatus); + NdisZeroMemory(Profile.WscWPAKey, 64 + 1); + + if (Profile.WscEncrypType == 2) + { + Profile.DefaultKeyIdx = pAd->ApCfg.MBSSID[apidx].DefaultKeyId + 1; + { + int i; + for (i=0; iSharedKey[apidx][pAd->ApCfg.MBSSID[apidx].DefaultKeyId].KeyLen; i++) + { + snprintf((PSTRING) Profile.WscWPAKey, sizeof(Profile.WscWPAKey), + "%s%02x", Profile.WscWPAKey, + pAd->SharedKey[apidx][pAd->ApCfg.MBSSID[apidx].DefaultKeyId].Key[i]); + } + Profile.WscWPAKey[(pAd->SharedKey[apidx][pAd->ApCfg.MBSSID[apidx].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 (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + sprintf(msg+strlen(msg), "%-12s", "WPAPSKWPA2PSK"); + else + sprintf(msg+strlen(msg), "%-12s", WscGetAuthTypeStr(Profile.WscAuthMode)); + if (pAd->ApCfg.MBSSID[apidx].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); + 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); + 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 /*AR9_MAPI_SUPPORT*/ +#endif/* INF_AR9 */ +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_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].Bssid[3], + pAd->ApCfg.MBSSID[apidx].Bssid[4], + pAd->ApCfg.MBSSID[apidx].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 + 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; + } + +} +#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_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); + } + + pWscControl->PinAttackCount = 0; + 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; +} + +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; + //INT IsAPConfigured = pWscControl->WscConfStatus; + + 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].WepStatus == Ndis802_11WEPEnabled) || + (pAd->ApCfg.MBSSID[pObj->ioctl_if].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 EASY_CONFIG_SETUP +INT Set_AP_AutoProvisionEnable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PEASY_CONFIG_INFO pEasyConfig = &pAd->ApCfg.MBSSID[apidx].EasyConfigInfo; + BOOLEAN bEnable = FALSE; + + if (strcmp(arg, "0") == 0) + bEnable = FALSE; + else if (strcmp(arg, "1") == 0) + bEnable = TRUE; + else + return FALSE; + + if (pEasyConfig->bEnable != bEnable) + { + pEasyConfig->bEnable = bEnable; +#ifdef WSC_AP_SUPPORT + WscInit(pAd, FALSE, apidx); +#endif /* WSC_AP_SUPPORT */ + } + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_AP_AutoProvisionEnable_Proc::(AutoProvisionEnable=%d)\n", + apidx, pEasyConfig->bEnable)); + + return TRUE; +} + +INT Set_RssiThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + CHAR Value; + PEASY_CONFIG_INFO pEasyConfig = NULL; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + + if (apidx != MAIN_MBSSID) + { + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_RssiThreshold_Proc:: Only support ra0\n",apidx)); + return FALSE; + } + Value = (CHAR)simple_strtol(arg, 0, 10); + + pEasyConfig = &pAd->ApCfg.MBSSID[apidx].EasyConfigInfo; + + if (Value > 70 || Value < 40) + pEasyConfig->RssiThreshold = -50; + else + pEasyConfig->RssiThreshold = (CHAR)(-1)*Value; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_RssiThreshold_Proc::(RssiThreshold=%d)\n",pEasyConfig->RssiThreshold)); + + return TRUE; +} + +#endif /* EASY_CONFIG_SETUP */ + +#ifdef WAC_SUPPORT +INT Set_AP_WACEnable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PEASY_CONFIG_INFO pEasyConfig = &pAd->ApCfg.MBSSID[apidx].EasyConfigInfo; + BOOLEAN bEnable = FALSE; + + if (strcmp(arg, "0") == 0) + bEnable = FALSE; + else if (strcmp(arg, "1") == 0) + bEnable = TRUE; + else + return FALSE; + + pEasyConfig->bEnableWAC = bEnable; + APUpdateBeaconFrame(pAd, pObj->ioctl_if); + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_AP_WACEnable_Proc::(bEnableWAC=%d)\n", + apidx, pEasyConfig->bEnableWAC)); + + return TRUE; +} +#endif /* WAC_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); + 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, &macAddr[i++], 1); + } + + pEntry = MacTableLookup(pAd, macAddr); + if (pEntry) + { + MlmeDeAuthAction(pAd, pEntry, REASON_DISASSOC_STA_LEAVING, FALSE); +/* MacTableDeleteEntry(pAd, pEntry->Aid, Addr); */ + } + + return TRUE; +} + +INT Set_DisConnectAllSta_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + { + MacTableReset(pAd); + } + + 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; + + ieee8021x = simple_strtol(arg, 0, 10); + + if (ieee8021x == 1) + pAd->ApCfg.MBSSID[pObj->ioctl_if].IEEE8021X = TRUE; + else if (ieee8021x == 0) + pAd->ApCfg.MBSSID[pObj->ioctl_if].IEEE8021X = FALSE; + else + return FALSE; /*Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_IEEE8021X_Proc::(IEEE8021X=%d)\n", pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].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; + /* End of if */ + + 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; + break; +#ifdef DOT11_N_SUPPORT + case MCAST_HTMIX: /* HTMIX */ + pAd->CommonCfg.MCastPhyMode.field.MODE = MODE_HTMIX; + break; +#endif /* DOT11_N_SUPPORT */ + default: + printk("unknow Muticast PhyMode %d.\n", PhyMode); + printk("0:Disable 1:CCK, 2:OFDM, 3:HTMIX.\n"); + break; + } + + return TRUE; +} + +INT Set_McastMcs( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR Mcs = simple_strtol(arg, 0, 10); + + if (Mcs > 15) + printk("Mcs must in range of 0 to 15\n"); + + switch(pAd->CommonCfg.MCastPhyMode.field.MODE) + { + case MODE_CCK: + if ((Mcs <= 3) || (Mcs >= 8 && Mcs <= 11)) + pAd->CommonCfg.MCastPhyMode.field.MCS = Mcs; + else + printk("MCS must in range of 0 ~ 3 and 8 ~ 11 for CCK Mode.\n"); + break; + + case MODE_OFDM: + if (Mcs > 7) + printk("MCS must in range from 0 to 7 for CCK 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) +{ + printk("Mcast PhyMode =%d\n", pAd->CommonCfg.MCastPhyMode.field.MODE); + printk("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) +{ + if ((strcmp(arg, "WEPAUTO") == 0) || (strcmp(arg, "wepauto") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeAutoSwitch; + else if ((strcmp(arg, "OPEN") == 0) || (strcmp(arg, "open") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeOpen; + else if ((strcmp(arg, "SHARED") == 0) || (strcmp(arg, "shared") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeShared; + else if ((strcmp(arg, "WPAPSK") == 0) || (strcmp(arg, "wpapsk") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPAPSK; + else if ((strcmp(arg, "WPA2PSK") == 0) || (strcmp(arg, "wpa2psk") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPA2PSK; + else if ((strcmp(arg, "WPAPSKWPA2PSK") == 0) || (strcmp(arg, "wpapskwpa2psk") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPA1PSKWPA2PSK; +#ifdef DOT1X_SUPPORT + else if ((strcmp(arg, "WPA") == 0) || (strcmp(arg, "wpa") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPA; + else if ((strcmp(arg, "WPA2") == 0) || (strcmp(arg, "wpa2") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPA2; + else if ((strcmp(arg, "WPA1WPA2") == 0) || (strcmp(arg, "wpa1wpa2") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPA1WPA2; +#endif /* DOT1X_SUPPORT */ +#ifdef WAPI_SUPPORT + else if ((strcmp(arg, "WAICERT") == 0) || (strcmp(arg, "waicert") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWAICERT; + else if ((strcmp(arg, "WAIPSK") == 0) || (strcmp(arg, "waipsk") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWAIPSK; +#endif /* WAPI_SUPPORT */ + else + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeOpen; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d)::AuthMode=%d\n", apidx, pAd->ApCfg.MBSSID[apidx].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 */ + + + +#ifdef RT3883 +INT Set_CwCTest_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + char *Cwc_mode_str[] = {"OFF", "ON", "AUTO"}; + long x = simple_strtol(arg, 0, 10); + + if ((x >= 0) && (x <= 2)) + { + pAd->FlgCWC = x; + if (x == 0 || x == 1) + RT3883_CWC_AsicSet(pAd, x); + DBGPRINT(RT_DEBUG_OFF, ("CwC %s\n", Cwc_mode_str[x])); + } + else + { + DBGPRINT(RT_DEBUG_OFF, ("current FlgCWC = %d\n", pAd->FlgCWC)); + } + + return TRUE; +} +#endif /* RT3883 */ + + +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 */ + RTMP_ASIC_SHARED_KEY_TABLE(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->Aid, + &pEntry->PairwiseKey); + + /* update WCID attribute table and IVEIV table for this entry */ + RTMPSetWcidSecurityInfo(pAd, + BssIdx, + KeyIdx, + pEntry->PairwiseKey.CipherAlg, + pEntry->Aid, + 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 */ + RTMP_ASIC_SHARED_KEY_TABLE(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; + + + 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].PhyMode; + DBGPRINT(RT_DEBUG_ERROR, ("\t%d\t\t", IdBss-1)); + } /* End of if */ + + switch(PhyMode) + { + case PHY_11BG_MIXED: + DBGPRINT(RT_DEBUG_ERROR, ("BG Mixed\n")); + break; + + case PHY_11B: + DBGPRINT(RT_DEBUG_ERROR, ("B Only\n")); + break; + + case PHY_11A: + DBGPRINT(RT_DEBUG_ERROR, ("A Only\n")); + break; + + case PHY_11ABG_MIXED: + DBGPRINT(RT_DEBUG_ERROR, ("ABG Mixed ==> BG Mixed\n")); + break; + + case PHY_11G: + DBGPRINT(RT_DEBUG_ERROR, ("G Only\n")); + break; + +#ifdef DOT11_N_SUPPORT + case PHY_11ABGN_MIXED: + DBGPRINT(RT_DEBUG_ERROR, ("ABGN Mixed ==> BGN Mixed\n")); + break; + + case PHY_11N_2_4G: + DBGPRINT(RT_DEBUG_ERROR, ("2.4G N Only\n")); + break; + + case PHY_11GN_MIXED: + DBGPRINT(RT_DEBUG_ERROR, ("GN Mixed\n")); + break; + + case PHY_11AN_MIXED: + DBGPRINT(RT_DEBUG_ERROR, ("AN Mixed\n")); + break; + + case PHY_11BGN_MIXED: + DBGPRINT(RT_DEBUG_ERROR, ("BGN Mixed\n")); + break; + + case PHY_11AGN_MIXED: + DBGPRINT(RT_DEBUG_ERROR, ("AGN Mixed\n")); + break; + + case PHY_11N_5G: + DBGPRINT(RT_DEBUG_ERROR, ("5G N Only\n")); + break; +#endif /* DOT11_N_SUPPORT */ + } /* End of switch */ + } /* End of for */ + + 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) pAd->CommonCfg.PhyMode; + wrq->u.data.length = 1; + /**(ULONG *)pData = (ULONG)pAd->CommonCfg.PhyMode; */ + 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; + +#ifdef DBG + 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 /* DBG */ + +#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: +#ifdef RTMP_RBUS_SUPPORT + RTMPIoctlGetMacTableStaInfo(pAd, wrq); +#endif /* RTMP_RBUS_SUPPORT */ + 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].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: + 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].Bssid[0]; + } + + if (pBssidStr != NULL) + { + memcpy(pBssidDest, pBssidStr, ETH_ALEN); + DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIWAP(=%02x:%02x:%02x:%02x:%02x:%02x)\n", + pBssidStr[0],pBssidStr[1],pBssidStr[2], pBssidStr[3],pBssidStr[4],pBssidStr[5])); + } + 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 MESH_SUPPORT + if (pRate->priv_flags == INT_MESH) + HtPhyMode = pAd->MeshTab.HTPhyMode; + else +#endif /* MESH_SUPPORT */ +#ifdef APCLI_SUPPORT + if (pRate->priv_flags == INT_APCLI) + HtPhyMode = pAd->ApCfg.ApCliTab[pObj->ioctl_if].HTPhyMode; + else +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (pRate->priv_flags == INT_WDS) + HtPhyMode = pAd->WdsTab.WdsEntry[pObj->ioctl_if].HTPhyMode; + else +#endif /* WDS_SUPPORT */ + { + HtPhyMode = pAd->ApCfg.MBSSID[pObj->ioctl_if].HTPhyMode; + +#ifdef MBSS_SUPPORT + /* reset phy mode for MBSS */ + MBSS_PHY_MODE_RESET(pObj->ioctl_if, HtPhyMode); +#endif /* MBSS_SUPPORT */ + } + + RtmpDrvMaxRateGet(pAd, HtPhyMode.field.MODE, HtPhyMode.field.ShortGI, + HtPhyMode.field.BW, HtPhyMode.field.MCS, + (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; +} + +#ifdef P2P_SUPPORT +INT Set_P2p_OpMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT OpMode; + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return FALSE; + + OpMode = simple_strtol(arg, 0, 16); + + + if (OpMode == OPMODE_AP) + { + if (P2P_CLI_ON(pAd)) + P2P_CliStop(pAd); + + if ((!P2P_GO_ON(pAd)) || (P2P_GO_ON(pAd))) + { + P2PCfgInit(pAd); + P2P_GoStartUp(pAd, MAIN_MBSSID); + } + } + else if (OpMode == OPMODE_APSTA) + { + if (P2P_GO_ON(pAd)) + P2P_GoStop(pAd); + + if ((!P2P_CLI_ON(pAd)) || (P2P_CLI_ON(pAd))) + { + P2PCfgInit(pAd); + P2P_CliStartUp(pAd); + AsicEnableBssSync(pAd); + } + } + else + { + if (P2P_CLI_ON(pAd)) + P2P_CliStop(pAd); + else if (P2P_GO_ON(pAd)) + { + P2P_GoStop(pAd); + if (INFRA_ON(pAd)) + AsicEnableBssSync(pAd); + } + P2PCfgInit(pAd); + } + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(p2p%d) Set_P2p_OpMode_Proc::(OpMode = %d)\n", pObj->ioctl_if, OpMode)); + + return TRUE; +} + +INT Set_P2pCli_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_P2P) + 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(p2p%d) Set_P2pCli_Enable_Proc::(enable = %d)\n", ifIndex, pAd->ApCfg.ApCliTab[ifIndex].Enable)); + + ApCliIfDown(pAd); + + return TRUE; +} + + +INT Set_P2pCli_Ssid_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR ifIndex; + BOOLEAN apcliEn; + INT success = FALSE; + /*UCHAR keyMaterial[40]; */ + UCHAR PskKey[100]; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return FALSE; + + ifIndex = pObj->ioctl_if; + + if(strlen(arg) <= MAX_LEN_OF_SSID) + { + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + + /* bring apcli interface down first */ + if(apcliEn == TRUE ) + { + pAd->ApCfg.ApCliTab[ifIndex].Enable = FALSE; + ApCliIfDown(pAd); + } + + 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); + + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscSsid.Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscSsid.Ssid, arg, strlen(arg)); + pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscSsid.SsidLength = (UCHAR)strlen(arg); + + success = TRUE; + + /* Upadte PMK and restart WPAPSK state machine for ApCli link */ + if (((pAd->ApCfg.ApCliTab[ifIndex].AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->ApCfg.ApCliTab[ifIndex].AuthMode == Ndis802_11AuthModeWPA2PSK)) && + pAd->ApCfg.ApCliTab[ifIndex].PSKLen > 0) + { + NdisZeroMemory(PskKey, 100); + NdisMoveMemory(PskKey, pAd->ApCfg.ApCliTab[ifIndex].PSK, pAd->ApCfg.ApCliTab[ifIndex].PSKLen); + + RT_CfgSetWPAPSKKey(pAd, (PSTRING)PskKey, + pAd->ApCfg.ApCliTab[ifIndex].PSKLen, + (PUCHAR)pAd->ApCfg.ApCliTab[ifIndex].CfgSsid, + pAd->ApCfg.ApCliTab[ifIndex].CfgSsidLen, + pAd->ApCfg.ApCliTab[ifIndex].PMK); + } + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(p2p%d) Set_P2pCli_Ssid_Proc::(Len=%d,Ssid=%s)\n", ifIndex, + pAd->ApCfg.ApCliTab[ifIndex].CfgSsidLen, pAd->ApCfg.ApCliTab[ifIndex].CfgSsid)); + + pAd->ApCfg.ApCliTab[ifIndex].Enable = apcliEn; + } + else + success = FALSE; + + return success; +} + + +INT Set_P2pCli_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_P2P) + 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; + 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_P2pCli_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_P2pCli_AuthMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG i; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex; + + if (pObj->ioctl_if_type != INT_P2P) + return FALSE; + + ifIndex = pObj->ioctl_if; + + if ((strncmp(arg, "WEPAUTO", 7) == 0) || (strncmp(arg, "wepauto", 7) == 0)) + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeAutoSwitch; + else if ((strncmp(arg, "SHARED", 6) == 0) || (strncmp(arg, "shared", 6) == 0)) + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeShared; + else if ((strncmp(arg, "WPAPSK", 6) == 0) || (strncmp(arg, "wpapsk", 6) == 0)) + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeWPAPSK; + else if ((strncmp(arg, "WPA2PSK", 7) == 0) || (strncmp(arg, "wpa2psk", 7) == 0)) + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeWPA2PSK; + else + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeOpen; + + 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; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_P2pCli_AuthMode_Proc::(AuthMode=%d)\n", ifIndex, pAd->ApCfg.ApCliTab[ifIndex].AuthMode)); + return TRUE; +} + + +/* + ========================================================================== + Description: + Set ApCli-IF Encryption Type + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_P2pCli_EncrypType_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex; + PAPCLI_STRUCT pApCliEntry = NULL; + + if (pObj->ioctl_if_type != INT_P2P) + return FALSE; + + ifIndex = pObj->ioctl_if; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + pApCliEntry->WepStatus = Ndis802_11WEPDisabled; + if ((strncmp(arg, "WEP", 3) == 0) || (strncmp(arg, "wep", 3) == 0)) + { + if (pApCliEntry->AuthMode < Ndis802_11AuthModeWPA) + pApCliEntry->WepStatus = Ndis802_11WEPEnabled; + } + else if ((strncmp(arg, "TKIP", 4) == 0) || (strncmp(arg, "tkip", 4) == 0)) + { + if (pApCliEntry->AuthMode >= Ndis802_11AuthModeWPA) + pApCliEntry->WepStatus = Ndis802_11Encryption2Enabled; + } + else if ((strncmp(arg, "AES", 3) == 0) || (strncmp(arg, "aes", 3) == 0)) + { + if (pApCliEntry->AuthMode >= Ndis802_11AuthModeWPA) + pApCliEntry->WepStatus = Ndis802_11Encryption3Enabled; + } + else + { + pApCliEntry->WepStatus = Ndis802_11WEPDisabled; + } + + pApCliEntry->PairCipher = pApCliEntry->WepStatus; + pApCliEntry->GroupCipher = pApCliEntry->WepStatus; + pApCliEntry->bMixCipher = FALSE; + + if (pApCliEntry->WepStatus >= Ndis802_11Encryption2Enabled) + pApCliEntry->DefaultKeyId = 1; + + RTMPMakeRSNIE(pAd, pApCliEntry->AuthMode, pApCliEntry->WepStatus, (ifIndex + MIN_NET_DEVICE_FOR_APCLI)); + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_P2pCli_EncrypType_Proc::(EncrypType=%d)\n", ifIndex, pApCliEntry->WepStatus)); + + return TRUE; +} + + + +/* + ========================================================================== + Description: + Set Default Key ID + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_P2pCli_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG KeyIdx; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex; + PAPCLI_STRUCT pApCliEntry = NULL; + + if (pObj->ioctl_if_type != INT_P2P) + return FALSE; + + ifIndex = pObj->ioctl_if; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + KeyIdx = simple_strtol(arg, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + pApCliEntry->DefaultKeyId = (UCHAR) (KeyIdx - 1 ); + else + return FALSE; /* Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_P2pCli_DefaultKeyID_Proc::(DefaultKeyID(0~3)=%d)\n", ifIndex, pApCliEntry->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_P2pCli_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_P2P) + return FALSE; + + ifIndex = pObj->ioctl_if; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_P2pCli_WPAPSK_Proc::(WPAPSK=%s)\n", ifIndex, arg)); + + retval = RT_CfgSetWPAPSKKey(pAd, arg, strlen(arg), (PUCHAR)pApCliEntry->CfgSsid, pApCliEntry->CfgSsidLen, pApCliEntry->PMK); + if (retval == FALSE) + return FALSE; + + NdisMoveMemory(pApCliEntry->PSK, arg, strlen(arg)); + pApCliEntry->PSKLen = strlen(arg); + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set WEP KEY1 for ApCli-IF + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_P2pCli_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_P2P) + 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(p2p%d) Set_P2pCli_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_P2pCli_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_P2P) + 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(p2p%d) Set_P2pCli_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_P2pCli_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_P2P) + 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(p2p%d) Set_P2pCli_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_P2pCli_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_P2P) + 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(p2p%d) Set_P2pCli_Key4_Proc::(Key4=%s) success!\n", ifIndex, arg)); + + return retVal; +} + +INT Set_P2pCli_TxMode_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_P2P) + return FALSE; + + ifIndex = pObj->ioctl_if; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + pApCliEntry->DesiredTransmitSetting.field.FixedTxMode = + RT_CfgSetFixedTxPhyMode(arg); + DBGPRINT(RT_DEBUG_TRACE, ("I/F(p2p%d) Set_P2pCli_TxMode_Proc = %d\n", ifIndex, + pApCliEntry->DesiredTransmitSetting.field.FixedTxMode)); + + return TRUE; +} + +INT Set_P2pCli_TxMcs_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_P2P) + return FALSE; + + ifIndex = pObj->ioctl_if; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + pApCliEntry->DesiredTransmitSetting.field.MCS = + RT_CfgSetTxMCSProc(arg, &pApCliEntry->bAutoTxRateSwitch); + + if (pApCliEntry->DesiredTransmitSetting.field.MCS == MCS_AUTO) + { + DBGPRINT(RT_DEBUG_TRACE, ("I/F(p2p%d) Set_P2pCli_TxMcs_Proc = AUTO\n", ifIndex)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("I/F(p2p%d) Set_P2pCli_TxMcs_Proc = %d\n", ifIndex, + pApCliEntry->DesiredTransmitSetting.field.MCS)); + } + + return TRUE; +} + +#ifdef WSC_AP_SUPPORT +INT Set_P2pCli_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_P2P) + 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, ("I/F(p2p%d) Set_P2pCli_WscSsid_Proc:: (Select SsidLen=%d,Ssid=%s)\n", ifIndex, + pWscControl->WscSsid.SsidLength, pWscControl->WscSsid.Ssid)); + } + else + return FALSE; /* Invalid argument */ + + return TRUE; + +} +#endif /* WSC_AP_SUPPORT */ +#endif /* P2P_SUPPORT */ + +INT Set_MacWatchDog_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + BOOLEAN bEnableWD; + + bEnableWD = simple_strtol(arg, 0, 10); + + pAd->bEnableMacWD = bEnableWD; + + DBGPRINT(RT_DEBUG_TRACE, ("EnableMacWD = %d \n", pAd->bEnableMacWD)); + + return TRUE; +} + +INT Set_DumpRF_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + int i; + UCHAR Value; + + for (i = 0; i < pAd->chipCap.MaxNumOfRfId; i++) + { + RT635xReadRFRegister(pAd, RF_BANK0, i, &Value); + printk("%d %03d %02X\n", RF_BANK0, i, Value); + } + + for (i = 0; i < pAd->chipCap.MaxNumOfRfId; i++) + { + RT635xReadRFRegister(pAd, RF_BANK4, i, &Value); + printk("%d %03d %02X\n", RF_BANK4, i, Value); + } + + for (i = 0; i < pAd->chipCap.MaxNumOfRfId; i++) + { + RT635xReadRFRegister(pAd, RF_BANK5, i, &Value); + printk("%d %03d %02X\n", RF_BANK5, i, Value); + } + + for (i = 0; i < pAd->chipCap.MaxNumOfRfId; i++) + { + RT635xReadRFRegister(pAd, RF_BANK6, i, &Value); + printk("%d %03d %02X\n", RF_BANK6, i, Value); + } + + for (i = 0; i < pAd->chipCap.MaxNumOfRfId; i++) + { + RT635xReadRFRegister(pAd, RF_BANK7, i, &Value); + printk("%d %03d %02X\n", RF_BANK7, i, Value); + } + + return TRUE; +} + +INT Set_DumpBBP_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + int i; + UCHAR BBPValue = 0; + + for (i = 0; i < pAd->chipCap.MaxNumOfBbpId; i++) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, i, &BBPValue); + printk("%03d = %02X\n", i, BBPValue); + } + + for (i = 0; i < pAd->chipCap.MaxNumOfBbpId; i++) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, i); + printk("%03d = %02X\n", BBP_R158, i); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &BBPValue); + printk("%03d = %02X\n", BBP_R159, BBPValue); + } + + for (i = 0; i < pAd->chipCap.MaxNumOfBbpId; i++) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, i); + printk("%03d = %02X\n", BBP_R195, i); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R196, &BBPValue); + printk("%03d = %02X\n", BBP_R196, BBPValue); + } + + return TRUE; +} + +INT Set_KickOutHwNull_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + BOOLEAN bEnableWD; + + bEnableWD = simple_strtol(arg, 0, 10); + + RtmpKickOutHwNullFrame(pAd, TRUE, TRUE); + + DBGPRINT(RT_DEBUG_ERROR, ("KickOutHwNull = %d \n", bEnableWD)); + + return TRUE; +} + +#if defined(MICROWAVE_OVEN_SUPPORT) || defined(DYNAMIC_VGA_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; +} + +INT Set_MO_LowFalseCCATh_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.nLowFalseCCATh = th; + + DBGPRINT(RT_DEBUG_OFF, ("%s: set low falseCCA threshold %lu for microwave oven application!!\n", __FUNCTION__, th)); + + return TRUE; +} + +#ifdef DYNAMIC_VGA_SUPPORT +INT Set_DyncVgaEnable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT Enable; + + Enable = simple_strtol(arg, 0, 10); + + pAd->CommonCfg.MO_Cfg.bDyncVGAEnable = (Enable > 0) ? TRUE : FALSE; + + if (pAd->CommonCfg.MO_Cfg.bDyncVGAEnable) + { + 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); + } + else + { + 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); + AsicBBPWriteWithRxChain(pAd, BBP_R66, pAd->CommonCfg.MO_Cfg.Stored_BBP_R66, RX_CHAIN_ALL); + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_DyncVgaEnable_Proc::(enable = %d)\n", pAd->CommonCfg.MO_Cfg.bDyncVGAEnable)); + + return TRUE; +} +#endif /* DYNAMIC_VGA_SUPPORT */ +#endif /* defined(MICROWAVE_OVEN_SUPPORT) || defined(DYNAMIC_VGA_SUPPORT) */ + +#ifdef THERMAL_PROTECT_SUPPORT +INT set_thermal_protection_criteria_proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + 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; +} +#endif /* THERMAL_PROTECT_SUPPORT */ diff --git a/mt7620/src/ap/ap_connect.c b/mt7620/src/ap/ap_connect.c new file mode 100644 index 0000000..547148c --- /dev/null +++ b/mt7620/src/ap/ap_connect.c @@ -0,0 +1,1217 @@ +/**************************************************************************** + * 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( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN 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 */ + + + 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].dev != NULL) + && (RTMP_OS_NETDEV_STATE_RUNNING(pAd->WdsTab.WdsEntry[idx].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( + IN PRTMP_ADAPTER pAd, + IN INT apidx) +{ + UCHAR DsLen = 1, SsidLen;/*, TimLen = 4, */ + /*BitmapControl = 0, VirtualBitmap = 0, EmptySsidLen = 0, SsidLen; */ +/* UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; */ + HEADER_802_11 BcnHdr; + LARGE_INTEGER FakeTimestamp; + ULONG FrameLen = 0; + PTXWI_STRUC pTxWI = &pAd->BeaconTxWI; + PUCHAR pBeaconFrame = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; + UCHAR *ptr; + UINT i; + UINT32 longValue; + HTTRANSMIT_SETTING BeaconTransmit; /* MGMT frame PHY rate setting when operatin at Ht rate. */ + UCHAR PhyMode, SupRateLen; + UINT8 TXWISize = pAd->chipCap.TXWISize; +#ifdef SPECIFIC_TX_POWER_SUPPORT + UCHAR TxPwrAdj = 0; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + + if(!BeaconTransmitRequired(pAd, apidx, &pAd->ApCfg.MBSSID[apidx])) + return; + + PhyMode = pAd->ApCfg.MBSSID[apidx].PhyMode; + + if (pAd->ApCfg.MBSSID[apidx].bHideSsid) + SsidLen = 0; + else + SsidLen = pAd->ApCfg.MBSSID[apidx].SsidLen; + + MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, +#ifdef P2P_SUPPORT + pAd->ApCfg.MBSSID[apidx].Bssid, +#endif /* P2P_SUPPORT */ + pAd->ApCfg.MBSSID[apidx].Bssid); + + + /* for update framelen to TxWI later. */ + SupRateLen = pAd->CommonCfg.SupRateLen; + if (PhyMode == PHY_11B) + SupRateLen = 4; + +#ifdef P2P_SUPPORT + if (P2P_GO_ON(pAd)) + { + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateIe = IE_SUPP_RATES; + UCHAR SupRateLen = 0; + + 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; + + MakeOutgoingFrame(pBeaconFrame, &FrameLen, + sizeof(HEADER_802_11), &BcnHdr, + TIMESTAMP_LEN, &FakeTimestamp, + 2, &pAd->CommonCfg.BeaconPeriod, + 2, &pAd->ApCfg.MBSSID[apidx].CapabilityInfo, + 1, &SsidIe, + 1, &SsidLen, + SsidLen, pAd->ApCfg.MBSSID[apidx].Ssid, + 1, &SupRateIe, + 1, &SupRateLen, + SupRateLen, &SupRate, + 1, &DsIe, + 1, &DsLen, + 1, &pAd->CommonCfg.Channel, + END_OF_ARGS); + + } + else +#endif /* P2P_SUPPORT */ + MakeOutgoingFrame(pBeaconFrame, &FrameLen, + sizeof(HEADER_802_11), &BcnHdr, + TIMESTAMP_LEN, &FakeTimestamp, + 2, &pAd->CommonCfg.BeaconPeriod, + 2, &pAd->ApCfg.MBSSID[apidx].CapabilityInfo, + 1, &SsidIe, + 1, &SsidLen, + SsidLen, pAd->ApCfg.MBSSID[apidx].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 != PHY_11B)) + { + 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[256]; */ + 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 */ + + + /* 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 DOT11_N_SUPPORT + /* AP Channel Report */ + { + 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 == PHY_11BGN_MIXED) + { + MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, + 1, &APChannelReportIe, + 1, &rclasslen, + rclasslen, rclass32, + 1, &APChannelReportIe, + 1, &rclasslen, + rclasslen, rclass33, + END_OF_ARGS); + FrameLen += TmpLen; + } + } + +#endif /* DOT11_N_SUPPORT */ + + + BeaconTransmit.word = 0; + +#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, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, BSS0Mcast_WCID, + FrameLen, PID_MGMT, 0, 0,IFS_HTTXOP, FALSE, &BeaconTransmit); + +#ifdef SPECIFIC_TX_POWER_SUPPORT + if (IS_RT6352(pAd)) + pTxWI->TxPwrAdj = TxPwrAdj; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + /* + step 6. move BEACON TXD and frame content to on-chip memory + */ + ptr = (PUCHAR)&pAd->BeaconTxWI; +#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_CHIP_UPDATE_BEACON(pAd, pAd->BeaconOffset[pAd->ApCfg.MBSSID[apidx].BcnBufIdx] + i, longValue, 4); + ptr += 4; + } + + /* update BEACON frame content. start right after the TXWI field. */ + ptr = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); +#endif + + for (i= 0; i< FrameLen; i+=4) + { + longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); + RTMP_CHIP_UPDATE_BEACON(pAd, pAd->BeaconOffset[pAd->ApCfg.MBSSID[apidx].BcnBufIdx] + TXWISize + i, longValue, 4); + ptr += 4; + } + + + pAd->ApCfg.MBSSID[apidx].TimIELocationInBeacon = (UCHAR)FrameLen; + pAd->ApCfg.MBSSID[apidx].CapabilityInfoLocationInBeacon = sizeof(HEADER_802_11) + TIMESTAMP_LEN + 2; +} + + +/* + ========================================================================== + 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( + IN PRTMP_ADAPTER pAd, + IN INT apidx) +{ + /*PTXWI_STRUC pTxWI = &pAd->BeaconTxWI; */ + PUCHAR pBeaconFrame = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; + UCHAR *ptr; + ULONG FrameLen = pAd->ApCfg.MBSSID[apidx].TimIELocationInBeacon; + ULONG UpdatePos = pAd->ApCfg.MBSSID[apidx].TimIELocationInBeacon; + /*ULONG CapInfoPos = pAd->ApCfg.MBSSID[apidx].CapabilityInfoLocationInBeacon; */ + UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; + UCHAR ID_1B, TimFirst, TimLast, *pTim; + MULTISSID_STRUCT *pMbss; + COMMON_CONFIG *pComCfg; + UCHAR PhyMode; + BOOLEAN bHasWpsIE = FALSE; +#ifdef SPECIFIC_TX_POWER_SUPPORT + UCHAR TxPwrAdj = 0; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + + UINT i; + HTTRANSMIT_SETTING BeaconTransmit; /* MGMT frame PHY rate setting when operatin at Ht rate. */ + + pMbss = &pAd->ApCfg.MBSSID[apidx]; + pComCfg = &pAd->CommonCfg; + PhyMode = pMbss->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)); + +#ifdef HOSTAPD_SUPPORT + if ( pAd->ApCfg.MBSSID[apidx].HostapdWPS && (pAd->ApCfg.MBSSID[apidx].WscIEBeacon.ValueLen)) + bHasWpsIE = TRUE; +#endif + +#ifdef WSC_AP_SUPPORT + /* add Simple Config Information Element */ + if (((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode >= 1) && (pAd->ApCfg.MBSSID[apidx].WscIEBeacon.ValueLen))) + { + bHasWpsIE = TRUE; + } +#endif /* WSC_AP_SUPPORT */ + + if (bHasWpsIE) + { + ULONG WscTmpLen = 0; + + MakeOutgoingFrame(pBeaconFrame+FrameLen, &WscTmpLen, + pAd->ApCfg.MBSSID[apidx].WscIEBeacon.ValueLen, pAd->ApCfg.MBSSID[apidx].WscIEBeacon.Value, + END_OF_ARGS); + FrameLen += WscTmpLen; + } + +#ifdef WSC_AP_SUPPORT + if ((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode != WSC_DISABLE) && +#ifdef DOT1X_SUPPORT + (pAd->ApCfg.MBSSID[apidx].IEEE8021X == FALSE) && +#endif /* DOT1X_SUPPORT */ + (pAd->ApCfg.MBSSID[apidx].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 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 */ + +#ifdef WAC_SUPPORT + WAC_AddDevAdvAttrIE(pAd, apidx, pBeaconFrame, &FrameLen); + if (pAd->ApCfg.MBSSID[apidx].EasyConfigInfo.pVendorInfoForBeacon) + { + ULONG tmpWACLen = 0; + MakeOutgoingFrame(pBeaconFrame+FrameLen, + &tmpWACLen, + pAd->ApCfg.MBSSID[apidx].EasyConfigInfo.VendorInfoForBeaconLen, + pAd->ApCfg.MBSSID[apidx].EasyConfigInfo.pVendorInfoForBeacon, + END_OF_ARGS); + FrameLen += tmpWACLen; + } +#endif /* WAC_SUPPORT */ + + /* Update ERP */ + if ((pComCfg->ExtRateLen) && (PhyMode != PHY_11B)) + { + /* 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)) + { + ptr = pBeaconFrame + FrameLen; + *ptr = IE_CHANNEL_SWITCH_ANNOUNCEMENT; + *(ptr + 1) = 3; + *(ptr + 2) = 1; + *(ptr + 3) = pComCfg->Channel; + *(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); + } +#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 ((PhyMode >= PHY_11ABGN_MIXED) && (pMbss->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 DOT11N_DRAFT3 + /* + P802.11n_D3.03, 7.3.2.60 Overlapping BSS Scan Parameters IE + */ + if ((PhyMode >= PHY_11ABGN_MIXED) && + (pComCfg->Channel <= 14) && + (pMbss->DesiredHtPhyInfo.bHtEnable) && + (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 */ +#endif /* DOT11_N_SUPPORT */ + +#if defined(DOT11N_DRAFT3) || defined(DOT11V_WNM_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 ((PhyMode >= PHY_11ABGN_MIXED) && (pComCfg->Channel <= 14) && + (pMbss->DesiredHtPhyInfo.bHtEnable) && (pComCfg->bBssCoexEnable == TRUE) + ) + { + extCapInfo.BssCoexistMgmtSupport = 1; + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + + pInfo = (PUCHAR)(&extCapInfo); + for (infoPos = 0; infoPos < extInfoLen; infoPos++) + { + if (pInfo[infoPos] != 0) + { + bNeedAppendExtIE = TRUE; + break; + } + } + + if (bNeedAppendExtIE == TRUE) + { + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &ExtCapIe, + 1, &extInfoLen, + extInfoLen, &extCapInfo, + END_OF_ARGS); + FrameLen += TmpLen; + } + } +#endif /* defined(DOT11N_DRAFT3) || defined(DOT11V_WNM_SUPPORT) */ + + + if ((pMbss->AuthMode == Ndis802_11AuthModeWPA) || + (pMbss->AuthMode == Ndis802_11AuthModeWPAPSK)) + RSNIe = IE_WPA; + else if ((pMbss->AuthMode == Ndis802_11AuthModeWPA2) || + (pMbss->AuthMode == Ndis802_11AuthModeWPA2PSK)) + RSNIe = IE_WPA2; +#ifdef WAPI_SUPPORT + else if ((pMbss->AuthMode == Ndis802_11AuthModeWAICERT) || + (pMbss->AuthMode == Ndis802_11AuthModeWAIPSK)) + RSNIe = IE_WAPI; +#endif /* WAPI_SUPPORT */ + + /* Append RSN_IE when WPA OR WPAPSK, */ + if ((pMbss->AuthMode == Ndis802_11AuthModeWPA1WPA2) || + (pMbss->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 (pMbss->AuthMode >= Ndis802_11AuthModeWPA) + { + ULONG TmpLen; + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &RSNIe, + 1, &pMbss->RSNIE_Len[0], + pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], + END_OF_ARGS); + FrameLen += TmpLen; + } + + /* add WMM IE here */ + if (pMbss->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->FlgQloadEnable != 0) + { + 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) + ) + { + 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; + } +#endif /* A_BAND_SUPPORT */ + + +#ifdef DOT11_N_SUPPORT + if ((PhyMode >= PHY_11ABGN_MIXED) && + (pMbss->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); + + 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 */ + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 9, RalinkSpecificIe, + END_OF_ARGS); + FrameLen += TmpLen; + +#ifdef RT3883 + if (IS_RT3883(pAd)) + FrameLen += RT3883_ext_pkt_len(pBeaconFrame, FrameLen, RalinkSpecificIe, 9); +#endif /* RT3883 */ +} + + /* step 6. Since FrameLen may change, update TXWI. */ +#ifdef A_BAND_SUPPORT + if (pAd->CommonCfg.Channel > 14) + BeaconTransmit.word = 0x4000; + else +#endif /* A_BAND_SUPPORT */ + BeaconTransmit.word = 0; + +#ifdef P2P_SUPPORT + if (P2P_GO_ON(pAd)) + { + PUCHAR pP2pNoAIE = NULL; + ULONG P2pTmpLen; + UCHAR P2pCapId = SUBID_P2P_CAP, P2pDevId = SUBID_P2P_DEVICE_ID; + USHORT P2pCapIdLen = 2, P2pDevIdLen = 6; + UCHAR P2pIEFixed[6] = {0xdd, 0x12, 0x50, 0x6f, 0x9a, 0x9}; + + MakeOutgoingFrame(pBeaconFrame+FrameLen, &P2pTmpLen, + 6, &P2pIEFixed[0], + 1, &P2pCapId, + 2, &P2pCapIdLen, + 2, &pAd->P2pCfg.P2pCapability, + END_OF_ARGS); + FrameLen += P2pTmpLen; + + MakeOutgoingFrame(pBeaconFrame+FrameLen, &P2pTmpLen, + 1, &P2pDevId, + 2, &P2pDevIdLen, + 6, &pAd->P2pCfg.CurrentAddress, + END_OF_ARGS); + FrameLen += P2pTmpLen; + + /* NoA */ + pP2pNoAIE = pBeaconFrame + FrameLen; + P2pTmpLen = P2pUpdateNoABeacon(pAd, apidx, pP2pNoAIE); + FrameLen += P2pTmpLen; + BeaconTransmit.field.MODE = 1; + BeaconTransmit.field.MCS = MCS_RATE_6; + + } + +#endif /* P2P_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, 0xff, + FrameLen, PID_MGMT, QID_MGMT, 0, IFS_HTTXOP, FALSE, &BeaconTransmit); + +#ifdef SPECIFIC_TX_POWER_SUPPORT + if (IS_RT6352(pAd)) + pAd->BeaconTxWI.TxPwrAdj = TxPwrAdj; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + + /* */ + /* step 7. move BEACON TXWI and frame content to on-chip memory */ + /* */ + RT28xx_UpdateBeaconToAsic(pAd, apidx, FrameLen, UpdatePos); + +} + + +/* + ========================================================================== + Description: + Pre-build All BEACON frame in the shared memory + ========================================================================== +*/ +static UCHAR GetBcnNum( + IN PRTMP_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 ++; + } + } + +#ifdef MESH_SUPPORT + if (pAd->MeshTab.bBcnSntReq) + { + pAd->MeshTab.BcnBufIdx = NumBcn; + NumBcn++; + } +#endif /* MESH_SUPPORT */ + + return NumBcn; +} + +VOID APMakeAllBssBeacon( + IN PRTMP_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; + + +#ifdef P2P_SUPPORT +#ifdef P2P_ODD_MAC_ADJUST + if (NumOfMacs != 2) + { + DBGPRINT(RT_DEBUG_ERROR, + ("The P2P mode is enabled, the NumOfMacs MUST be 2, NumOfMacs=%d\n", + NumOfMacs)); + } +#endif /* P2P_ODD_MAC_ADJUST */ +#endif /* P2P_SUPPORT */ + + /* set Multiple BSSID mode */ + if (NumOfMacs <= 1) + { + pAd->ApCfg.MacMask = ~(1-1); + /*regValue |= 0x0; */ + } + else if (NumOfMacs <= 2) + { + if ((pAd->CurrentAddress[5] % 2 != 0) +#ifdef P2P_SUPPORT +#ifdef P2P_ODD_MAC_ADJUST + && FALSE +#endif /* P2P_ODD_MAC_ADJUST */ +#endif /* P2P_SUPPORT */ + ) + DBGPRINT(RT_DEBUG_ERROR, ("The 2-BSSID mode is enabled, the BSSID byte5 MUST be the multiple of 2\n")); + + regValue |= (1<<16); + pAd->ApCfg.MacMask = ~(2-1); + } + else if (NumOfMacs <= 4) + { + 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")); + + regValue |= (2<<16); + pAd->ApCfg.MacMask = ~(4-1); + } + else if (NumOfMacs <= 8) + { + 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")); + + regValue |= (3<<16); + pAd->ApCfg.MacMask = ~(8-1); + } +#ifdef SPECIFIC_BCN_BUF_SUPPORT + else if (NumOfMacs <= 16) + { + /* Set MULTI_BSSID_MODE_BIT4 in MAC register 0x1014 */ + regValue |= (1<<22); + pAd->ApCfg.MacMask = ~(16-1); + } +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ + + /* set Multiple BSSID Beacon number */ + if (NumOfBcns > 1) + { +#ifdef SPECIFIC_BCN_BUF_SUPPORT + if (NumOfBcns > 8) + regValue |= (((NumOfBcns - 1) >> 3) << 23); +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ + 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); + + +} + + +/* + ========================================================================== + Description: + Pre-build All BEACON frame in the shared memory + ========================================================================== +*/ +VOID APUpdateAllBeaconFrame( + IN PRTMP_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/mt7620/src/ap/ap_data.c b/mt7620/src/ap/ap_data.c new file mode 100644 index 0000000..e29b518 --- /dev/null +++ b/mt7620/src/ap/ap_data.c @@ -0,0 +1,5783 @@ +/* + *************************************************************************** + * 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 + -------- ---------- ---------------------------------------------- + Paul Lin 08-01-2002 created + Paul Lin 07-01-2003 add encryption/decryption data flow + John Chang 08-05-2003 modify 802.11 header for AP purpose + John Chang 12-20-2004 modify for 2561/2661. merge into STA driver + Jan Lee 1-20-2006 modify for 2860. +*/ +#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)) + + +static VOID APFindCipherAlgorithm( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk); + +#ifdef DOT11_N_SUPPORT +VOID RTMP_BASetup( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pMacEntry, + IN UINT8 UserPriority) +{ + if (pMacEntry && (pMacEntry->NoBADataCountDown == 0) && IS_HT_STA(pMacEntry)) + { + /* Don't care the status of the portSecured status. */ + if (((pMacEntry->TXBAbitmap & (1<PortSecured == WPA_802_1X_PORT_SECURED)*/ + /* + For IOT compatibility, BA session can be bulit when following conditions matched + 1. It is Ralink chip or + 2. It is OPEN or AES mode, + */ + && ((IS_ENTRY_CLIENT(pMacEntry) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) || + IS_ENTRY_MESH(pMacEntry) || IS_ENTRY_WDS(pMacEntry) || + (IS_ENTRY_APCLI(pMacEntry) && (pAd->MlmeAux.APRalinkIe != 0x0) && (pMacEntry->PortSecured == WPA_802_1X_PORT_SECURED)) || + (pMacEntry->WepStatus == Ndis802_11WEPDisabled || + pMacEntry->WepStatus == Ndis802_11Encryption3Enabled +#ifdef WAPI_SUPPORT + || pMacEntry->WepStatus == Ndis802_11EncryptionSMS4Enabled +#endif /* WAPI_SUPPORT */ + )) + ) + { + BAOriSessionSetUp(pAd, pMacEntry, UserPriority, 0, 10, FALSE); + } + } +} +#endif /* DOT11_N_SUPPORT */ + +static inline BOOLEAN ApAllowToSendPacket( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + OUT UCHAR *pWcid) +{ + PACKET_INFO PacketInfo; + PUCHAR pSrcBufVA; + UINT SrcBufLen; + PMAC_TABLE_ENTRY pEntry = NULL; + SST Sst; + USHORT Aid; + UCHAR PsMode, Rate; + BOOLEAN allowed; + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); +#ifdef CLIENT_WDS + { + PUCHAR pEntryAddr; + pEntry = APSsPsInquiry(pAd, pSrcBufVA, &Sst, &Aid, &PsMode, &Rate); + if ((pEntry == NULL) + && (pEntryAddr = CliWds_ProxyLookup(pAd, pSrcBufVA)) != NULL) + { + pEntry = APSsPsInquiry(pAd, pEntryAddr, &Sst, &Aid, &PsMode, &Rate); + } + } +#else + pEntry = APSsPsInquiry(pAd, pSrcBufVA, &Sst, &Aid, &PsMode, &Rate); +#endif /* CLIENT_WDS */ + + + if ((pEntry && (Sst == SST_ASSOC)) || (*pSrcBufVA & 0x01)) + { + /* + Record that orignal packet source is from NDIS layer,so that + later on driver knows how to release this NDIS PACKET + */ + *pWcid = (UCHAR)Aid; /*RTMP_SET_PACKET_WCID(pPacket, (UCHAR)Aid); */ + allowed = TRUE; + } + else + { + allowed = FALSE; + } + + return allowed; + +} + + + +/* +======================================================================== +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 APSendPackets( + IN NDIS_HANDLE MiniportAdapterContext, + IN PPNDIS_PACKET ppPacketArray, + IN UINT NumberOfPackets) +{ + UINT Index; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext; + PNDIS_PACKET pPacket; + BOOLEAN allowToSend; + UCHAR wcid = MCAST_WCID; + + + for (Index = 0; Index < NumberOfPackets; Index++) + { + pPacket = ppPacketArray[Index]; + + 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_RADIO_OFF)) + { + /* Drop send request since hardware is in reset state */ + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + continue; + } + + /* The following code do comparison must base on the following sequence: + MIN_NET_DEVICE_FOR_APCLI> MIN_NET_DEVICE_FOR_WDS > Normal + */ +#ifdef P2P_SUPPORT + if (RTMP_GET_PACKET_NET_DEVICE(pPacket) >= MIN_NET_DEVICE_FOR_P2P_GO) + allowToSend = ApAllowToSendPacket(pAd, pPacket, &wcid); + else +#endif /* P2P_SUPPORT */ +#ifdef MESH_SUPPORT + if (RTMP_GET_PACKET_NET_DEVICE(pPacket) >= MIN_NET_DEVICE_FOR_MESH) + allowToSend = MeshAllowToSendPacket(pAd, pPacket, &wcid); + else +#endif /* MESH_SUPPORT */ +#ifdef APCLI_SUPPORT + if (RTMP_GET_PACKET_NET_DEVICE(pPacket) >= MIN_NET_DEVICE_FOR_APCLI) + allowToSend = ApCliAllowToSendPacket(pAd, pPacket, &wcid); + else +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (RTMP_GET_PACKET_NET_DEVICE(pPacket) >= MIN_NET_DEVICE_FOR_WDS) + allowToSend = ApWdsAllowToSendPacket(pAd, pPacket, &wcid); + else +#endif /* WDS_SUPPORT */ + allowToSend = ApAllowToSendPacket(pAd, pPacket, &wcid); + + if (allowToSend) + { + /* For packet send from OS, we need to set the wcid here, it will used directly in APSendPacket. */ + RTMP_SET_PACKET_WCID(pPacket, wcid); + RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS); + NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING); + pAd->RalinkCounters.PendingNdisPacketCount++; + + APSendPacket(pAd, pPacket); + } + else + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + } + + /* Dequeue outgoing frames from TxSwQueue0..3 queue and process it */ + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + +} + + +/* + ======================================================================== + 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 TxSwQueue 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 TxSwQueue. + 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. + + +======================================================================== +*/ +NDIS_STATUS APSendPacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket) +{ + PACKET_INFO PacketInfo; + PUCHAR pSrcBufVA; + UINT SrcBufLen; + UINT AllowFragSize; + UCHAR NumberOfFrag; + UCHAR RTSRequired; + UCHAR QueIdx, UserPriority, apidx = MAIN_MBSSID; + SST Sst = SST_ASSOC; + UCHAR PsMode = PWR_ACTIVE, Rate; + USHORT Wcid; + MAC_TABLE_ENTRY *pMacEntry = NULL; + unsigned long IrqFlags; +#ifdef IGMP_SNOOP_SUPPORT + INT InIgmpGroup = IGMP_NONE; + PMULTICAST_FILTER_TABLE_ENTRY pGroupEntry = NULL; +#endif /* IGMP_SNOOP_SUPPORT */ + MULTISSID_STRUCT *pMbss = NULL; + + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + + if (pSrcBufVA == NULL) + { + /* + 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,("APSendPacket --> Ndis Packet buffer error !!!\n")); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return (NDIS_STATUS_FAILURE); + } + + Wcid = RTMP_GET_PACKET_WCID(pPacket); + pMacEntry = &pAd->MacTab.Content[Wcid]; + + /* + 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; + if (RTMPCheckEtherType(pAd, pPacket, pMacEntry, OPMODE_AP, &UserPriority, &QueIdx) == FALSE) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + +#ifdef MESH_SUPPORT + if (IS_ENTRY_MESH(pMacEntry)) + { + Rate = pMacEntry->CurrTxRate; + if ((pMacEntry->AuthMode >= Ndis802_11AuthModeWPA) + && (pMacEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED) + && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return (NDIS_STATUS_FAILURE); + } + } + else +#endif /* MESH_SUPPORT */ +#ifdef APCLI_SUPPORT + if(IS_ENTRY_APCLI(pMacEntry)) + { + Rate = pMacEntry->CurrTxRate; + if ((pMacEntry->AuthMode >= Ndis802_11AuthModeWPA) + && (pMacEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED) + && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)) + { + 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 +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (IS_ENTRY_WDS(pMacEntry)) + { + /*b7 as WDS bit, b0-6 as WDS index when b7==1 */ + Rate = pMacEntry->CurrTxRate; + } + else +#endif /* WDS_SUPPORT */ + if (IS_ENTRY_CLIENT(pMacEntry) || (Wcid == MCAST_WCID)) + { + /*USHORT Aid; */ + PsMode = pMacEntry->PsMode; + Rate = pMacEntry->CurrTxRate; + Sst = pMacEntry->Sst; + + if (Wcid == MCAST_WCID) + { + /* if (pAd->MacTab.Size == 0) */ + if (pAd->ApCfg.EntryClientCount == 0) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + + apidx = RTMP_GET_PACKET_NET_DEVICE_MBSSID(pPacket); +#ifdef P2P_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_P2P_GO) + apidx = apidx - MIN_NET_DEVICE_FOR_P2P_GO; +#endif /* P2P_SUPPORT */ + MBSS_MR_APIDX_SANITY_CHECK(pAd, apidx); + pMbss = &pAd->ApCfg.MBSSID[apidx]; + } + else + { + apidx = pMacEntry->apidx; + pMbss = pMacEntry->pMbss; + } + + /* AP does not send packets before port secured. */ + if (pMbss != NULL) + { + if (((pMbss->AuthMode >= Ndis802_11AuthModeWPA) +#ifdef DOT1X_SUPPORT + || (pMbss->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) && (pMbss->PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + + /* Process for unicast frame */ + if ((Wcid != MCAST_WCID) && pMacEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + } + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("I/F(ra%d) APSendPacket --> Drop unknow packet !!!\n", apidx)); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + + if (pMbss == NULL) + pMbss = &pAd->ApCfg.MBSSID[apidx]; + +#ifdef IGMP_SNOOP_SUPPORT + if (pAd->ApCfg.IgmpSnoopEnable) + { + UCHAR FromWhichBSSID, checkIgmpPkt = TRUE; + + if (IS_ENTRY_WDS(pMacEntry)) + FromWhichBSSID = pMacEntry->MatchWDSTabIdx + MIN_NET_DEVICE_FOR_WDS; + else if ((Wcid == MCAST_WCID) || IS_ENTRY_CLIENT(pMacEntry)) + FromWhichBSSID = apidx; + else + checkIgmpPkt = FALSE; + + if (checkIgmpPkt) + { + if (IgmpPktInfoQuery(pAd, pSrcBufVA, pPacket, FromWhichBSSID, + &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 ((*pSrcBufVA & 0x01) /* fragmentation not allowed on multicast & broadcast */ +#ifdef IGMP_SNOOP_SUPPORT + /* multicast packets in IgmpSn table should never send to Power-Saving queue. */ + && (!InIgmpGroup) +#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); + + /* + 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; + + /* RTS/CTS may also be required in order to protect OFDM frame */ + if ((Rate >= RATE_FIRST_OFDM_RATE) && + (Rate <= RATE_LAST_OFDM_RATE) && + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) + RTSRequired = 1; + + /* Save RTS requirement to Ndis packet reserved field */ + RTMP_SET_PACKET_RTS(pPacket, RTSRequired); + RTMP_SET_PACKET_TXRATE(pPacket, Rate); + + + + /* detect AC Category of tx packets to tune AC0(BE) TX_OP (MAC reg 0x1300) */ +#ifdef APCLI_CERT_SUPPORT + if (pAd->bApCliCertTest == 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 and ApClient 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 */ + + if (pAd->TxSwQueue[QueIdx].Number >= pAd->TxSwQMaxLen) + { +#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 ((*pSrcBufVA & 0x01) && pAd->MacTab.fAnyStationInPsm +#ifdef IGMP_SNOOP_SUPPORT + /* multicast packets in IgmpSn table should never send to Power-Saving queue. */ + && (!InIgmpGroup) +#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(=%ld) full, drop it!\n", pAd->MacTab.McastPsQueue.Number)); + return NDIS_STATUS_FAILURE; + } + else + { + 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) && (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 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, GET_OS_PKT_NETDEV(pPacket)); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + if (PktCloneResult != NDIS_STATUS_SUCCESS) + return NDIS_STATUS_FAILURE; + } + else +#endif /* IGMP_SNOOP_SUPPORT */ + { + + if (pAd->TxSwQueue[QueIdx].Number >= pAd->TxSwQMaxLen) + { + +#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 */ + +/* TODO: for debug only. to be removed */ +#ifdef APCLI_CERT_SUPPORT + pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; +#endif /* APCLI_CERT_SUPPORT */ +/* pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; */ + 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_11Encryption1Enabled but the key will use PairwiseKey + Instead of the SharedKey, SharedKey Length may be Zero. +*/ +static inline VOID APFindCipherAlgorithm( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + + PCIPHER_KEY pKey = NULL; + UCHAR CipherAlg = CIPHER_NONE; /* cipher alogrithm */ + UCHAR apidx; + UCHAR RAWcid; + PMAC_TABLE_ENTRY pMacEntry; + UCHAR KeyIdx = 0; + MULTISSID_STRUCT *pMbss; + + apidx = pTxBlk->apidx; + RAWcid = pTxBlk->Wcid; + pMacEntry = pTxBlk->pMacEntry; + pMbss = &pAd->ApCfg.MBSSID[apidx]; + +#ifdef MESH_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry)) + { + 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; + } + } + else if (pMacEntry->WepStatus == Ndis802_11Encryption1Enabled) + { + CipherAlg = pAd->MeshTab.SharedKey.CipherAlg; + if (CipherAlg) + pKey = &pAd->MeshTab.SharedKey; + } + else if (pMacEntry->WepStatus == Ndis802_11Encryption2Enabled || + pMacEntry->WepStatus == Ndis802_11Encryption3Enabled) + { + CipherAlg = pMacEntry->PairwiseKey.CipherAlg; + if (CipherAlg) + pKey = &pMacEntry->PairwiseKey; + } + else + { + CipherAlg = CIPHER_NONE; + pKey = NULL; + } + } + else +#endif /* MESH_SUPPORT */ +#ifdef APCLI_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bApCliPacket)) + { + PAPCLI_STRUCT pApCliEntry; + + pApCliEntry = pTxBlk->pApCliEntry; + + 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 APCLI_WPA_SUPPLICANT_SUPPORT + else if ( pApCliEntry->WpaSupplicantUP && + (pMacEntry->WepStatus == Ndis802_11Encryption1Enabled) && + (pApCliEntry->IEEE8021X == TRUE) && + (pMacEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + { + CipherAlg = CIPHER_NONE; + } +#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ + else if (pMacEntry->WepStatus == Ndis802_11Encryption1Enabled) + { + CipherAlg = pApCliEntry->SharedKey[pApCliEntry->DefaultKeyId].CipherAlg; + if (CipherAlg) + pKey = &pApCliEntry->SharedKey[pApCliEntry->DefaultKeyId]; + } + else if (pMacEntry->WepStatus == Ndis802_11Encryption2Enabled || + pMacEntry->WepStatus == Ndis802_11Encryption3Enabled) + { + 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)) + { + if (pAd->WdsTab.WdsEntry[pMacEntry->MatchWDSTabIdx].WepStatus == Ndis802_11Encryption1Enabled || + pAd->WdsTab.WdsEntry[pMacEntry->MatchWDSTabIdx].WepStatus == Ndis802_11Encryption2Enabled || + pAd->WdsTab.WdsEntry[pMacEntry->MatchWDSTabIdx].WepStatus == Ndis802_11Encryption3Enabled) + { + CipherAlg = pAd->WdsTab.WdsEntry[pMacEntry->MatchWDSTabIdx].WdsKey.CipherAlg; + if (CipherAlg) + pKey = &pAd->WdsTab.WdsEntry[pMacEntry->MatchWDSTabIdx].WdsKey; + } + else + { + CipherAlg = CIPHER_NONE; + pKey = NULL; + } + } + else +#endif /* WDS_SUPPORT */ +#ifdef WAPI_SUPPORT + if (pMbss->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->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 + ((pMbss->WepStatus == Ndis802_11Encryption1Enabled) && (pMbss->IEEE8021X == TRUE)) || +#endif /* DOT1X_SUPPORT */ + (pMbss->WepStatus == Ndis802_11Encryption2Enabled) || + (pMbss->WepStatus == Ndis802_11Encryption3Enabled) || + (pMbss->WepStatus == Ndis802_11Encryption4Enabled)) + { + 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 = pMbss->DefaultKeyId; +#ifdef P2P_APCLI_SUPPORT + if (P2P_INF_ON(pAd) && P2P_GO_ON(pAd)) + CipherAlg = pAd->SharedKey[apidx+1][KeyIdx].CipherAlg; + else +#endif /* P2P_APCLI_SUPPORT */ + 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 (pMbss->WepStatus == Ndis802_11Encryption1Enabled) /* WEP always uses shared key table */ + { + KeyIdx = pMbss->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 */ +#ifdef MESH_SUPPORT + if(IS_ENTRY_MESH(pMacEntry)) + { /* The addr3 of WDS packet is Destination Mac address and Addr4 is the Source Mac address. */ + PNDIS_PACKET pPacket = pTxBlk->pPacket; + COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pMeshDA); + if (RTMP_GET_MESH_SOURCE(pPacket) == MESH_PROXY) + COPY_MAC_ADDR(pHeader80211->Octet, pAd->MeshTab.CurrentAddress); + else + COPY_MAC_ADDR(pHeader80211->Octet, pTxBlk->pSrcBufHeader + MAC_ADDR_LEN); + pTxBlk->MpduHeaderLen += MAC_ADDR_LEN; + } + else +#endif /* MESH_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 */ + ) + { /* 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 APCLI_SUPPORT + if(IS_ENTRY_APCLI(pMacEntry)) + { /* 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); + } + + +} +#endif /* DOT11_N_SUPPORT */ + +static inline VOID APBuildCommon802_11Header( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + + HEADER_802_11 *pHeader_802_11; + UINT8 TXWISize = pAd->chipCap.TXWISize; + + /* + MAKE A COMMON 802.11 HEADER + */ + + /* normal wlan header size : 24 octets */ + pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11); + + pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]; + + NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11)); + + pHeader_802_11->FC.FrDs = 1; + pHeader_802_11->FC.Type = BTYPE_DATA; + pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA); + + if (pTxBlk->pMacEntry) + { + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS)) + { + pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq; + pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ; + } + else + { + pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]; + pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ; + } + } + else + { + pHeader_802_11->Sequence = pAd->Sequence; + pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; /* next sequence */ + } + + pHeader_802_11->Frag = 0; + + pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); + +#ifdef MESH_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry)) + { + PNDIS_PACKET pPacket = pTxBlk->pPacket; + pHeader_802_11->FC.ToDs = 1; + COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pMacEntry->Addr); /* to AP2 */ + COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->MeshTab.CurrentAddress); /* from AP1 */ + COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pMeshDA); + if (RTMP_GET_MESH_SOURCE(pPacket) == MESH_PROXY) + COPY_MAC_ADDR(&pHeader_802_11->Octet[0], pAd->MeshTab.CurrentAddress); + else + COPY_MAC_ADDR(&pHeader_802_11->Octet[0], pTxBlk->pSrcBufHeader + MAC_ADDR_LEN); /* ADDR4 = SA */ + pTxBlk->MpduHeaderLen += MAC_ADDR_LEN; + } + else +#endif /* MESH_SUPPORT */ +#ifdef APCLI_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bApCliPacket)) + { + pHeader_802_11->FC.ToDs = 1; + pHeader_802_11->FC.FrDs = 0; + COPY_MAC_ADDR(pHeader_802_11->Addr1, APCLI_ROOT_BSSID_GET(pAd, pTxBlk->Wcid)); /* to AP2 */ +#ifdef MAC_REPEATER_SUPPORT + if (pTxBlk->pMacEntry && (pTxBlk->pMacEntry->bReptCli == TRUE)) + COPY_MAC_ADDR(pHeader_802_11->Addr2, pTxBlk->pMacEntry->ReptCliAddr); + else +#endif /* MAC_REPEATER_SUPPORT */ + COPY_MAC_ADDR(pHeader_802_11->Addr2, pTxBlk->pApCliEntry->CurrentAddress); /* from AP1 */ + COPY_MAC_ADDR(pHeader_802_11->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 */ + ) + { + pHeader_802_11->FC.ToDs = 1; + if (pTxBlk->pMacEntry == NULL) + DBGPRINT(RT_DEBUG_ERROR, ("%s pTxBlk->pMacEntry == NULL!\n", __FUNCTION__)); + else + COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pMacEntry->Addr); /* to AP2 */ + + COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress); /* from AP1 */ + COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader); /* DA */ + COPY_MAC_ADDR(&pHeader_802_11->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(pHeader_802_11->Addr1, pTxBlk->pMacEntry->Addr); /* DA */ + } + else +#endif /* IGMP_SNOOP_SUPPORT */ + { + COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader); /* DA */ + } + COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->ApCfg.MBSSID[pTxBlk->apidx].Bssid); /* BSSID */ + COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader + MAC_ADDR_LEN); /* SA */ + } + +#ifdef P2P_SUPPORT + /* To not disturb the Opps test, set psm bit if I use power save mode. */ + /* P2P Test case 7.1.3 */ + if (P2P_INF_ON(pAd) && P2P_CLI_ON(pAd) && + (P2P_TEST_BIT(pAd->P2pCfg.CTWindows, P2P_OPPS_BIT )) + && (pAd->P2pCfg.bP2pCliPmEnable)) + pHeader_802_11->FC.PwrMgmt = 1; +#endif /* P2P_SUPPORT */ + if (pTxBlk->CipherAlg != CIPHER_NONE) + pHeader_802_11->FC.Wep = 1; +} + + +static inline PUCHAR AP_Build_ARalink_Frame_Header( + IN RTMP_ADAPTER *pAd, + IN 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) +{ + PUCHAR pHeaderBufPtr;/*, pSaveBufPtr; */ + HEADER_802_11 *pHeader_802_11; + 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; + + /* 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; + + } + 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; + + /* hex_dump("HT_Ctrl Field", pHeaderBufPtr, 4); */ + pHeaderBufPtr += 4; + pTxBlk->MpduHeaderLen += 4; + } + } +#endif /* TXBF_SUPPORT */ + + /* pSaveBufPtr = pHeaderBufPtr;*/ + + /* + 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; + +} + + +VOID AP_AMPDU_Frame_Tx( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + HEADER_802_11 *pHeader_802_11; + PUCHAR pHeaderBufPtr; +/* UCHAR QueIdx = pTxBlk->QueIdx; */ + USHORT FreeNumber = 1; /* no use */ + MAC_TABLE_ENTRY *pMacEntry; + PQUEUE_ENTRY pQEntry; + BOOLEAN bHTCPlus = FALSE; + 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 ++; +#endif /* STATS_COUNT_SUPPORT */ + + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + + pMacEntry = pTxBlk->pMacEntry; + if ((pMacEntry->isCached) +#ifdef TXBF_SUPPORT + && (pMacEntry->TxSndgType == SNDG_TYPE_DISABLE) +#endif /* TXBF_SUPPORT */ + ) + { + /* It should be cleared!!! */ + /*NdisZeroMemory((PUCHAR)(&pTxBlk->HeaderBuf[0]), sizeof(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 = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]); + 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[TXINFO_SIZE + TXWISize]; + } + +#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 MESH_SUPPORT + && !TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry) +#endif /* MESH_SUPPORT */ +#ifdef SOFT_ENCRYPT + && !TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt) +#endif /* SOFT_ENCRYPT */ +#ifdef TXBF_SUPPORT + && (pMacEntry->TxSndgType == 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 */ +#ifdef MESH_SUPPORT + && (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry) == FALSE) +#endif /* MESH_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 */ +#ifdef MESH_SUPPORT + && (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry) == FALSE) +#endif /* MESH_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+ + HTC control filed following QoS field + */ + if ((pAd->CommonCfg.bRdg == TRUE) + && (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)) +#ifdef TXBF_SUPPORT + && (pMacEntry->TxSndgType != 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 (pMacEntry->TxSndgType >= SNDG_TYPE_SOUNDING) + { + if (bHTCPlus == FALSE) + { + NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL)); + bHTCPlus = TRUE; + } + + 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; + + } + 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; + 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; + + /* hex_dump("HT_Ctrl Field", pHeaderBufPtr, 4);*/ + 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 + @@@ 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 */ + { + +#ifdef MESH_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry)) + InsertPktMeshHeader(pAd, pTxBlk, &pHeaderBufPtr); +#endif /* MESH_SUPPORT */ + + /* 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, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + } + else + { + RTMPWriteTxWI_Data(pAd, (PTXWI_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; + } + + /* calculate Tx count and ByteCount per BSS */ +#ifdef WAPI_SUPPORT + if (IS_ENTRY_CLIENT(pMacEntry)) +#endif /* WAPI_SUPPORT */ + { + MULTISSID_STRUCT *pMbss = pTxBlk->pMbss; + +#ifdef WAPI_SUPPORT + if (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 += pTxBlk->SrcBufLen; + pMbss->TxCount ++; + +#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; + } + } + +#ifdef WDS_SUPPORT + if (pMacEntry && IS_ENTRY_WDS(pMacEntry)) + { + INC_COUNTER64(pAd->WdsTab.WdsEntry[pMacEntry->MatchWDSTabIdx].WdsCounter.TransmittedFragmentCount); + pAd->WdsTab.WdsEntry[pMacEntry->MatchWDSTabIdx].WdsCounter.TransmittedByteCount+= pTxBlk->SrcBufLen; + } +#endif /* WDS_SUPPORT */ +#endif /* STATS_COUNT_SUPPORT */ + + /*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 */ + + /* + Kick out Tx + */ + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + +} + + +VOID AP_AMSDU_Frame_Tx( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + PUCHAR pHeaderBufPtr; +/* UCHAR QueIdx = pTxBlk->QueIdx; */ + USHORT FreeNumber = 1; /* no use */ + USHORT subFramePayloadLen = 0; /* AMSDU Subframe length without AMSDU-Header / Padding. */ + USHORT totalMPDUSize=0; + UCHAR *subFrameHeader; + 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 */ + + + 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++; +#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->MPDUtotalByteCount will be updated after final frame was handled. */ + RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + } + else + { + pHeaderBufPtr = &pTxBlk->HeaderBuf[0]; + padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen); + NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD); + 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->MatchAPCLITabIdx].RepeaterCli[pTxBlk->pMacEntry->MatchReptCliIdx]; + if (pReptEntry->CliValid) + NdisMoveMemory(&subFrameHeader[6] , pReptEntry->CurrentAddress, 6); + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pApCliEntry = &pAd->ApCfg.ApCliTab[pTxBlk->pMacEntry->MatchAPCLITabIdx]; + if (pApCliEntry->Valid) + NdisMoveMemory(&subFrameHeader[6] , pApCliEntry->CurrentAddress, 6); + } + } +#endif /* APCLI_SUPPORT */ + +#ifdef MESH_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry)) + { + if (RTMP_GET_MESH_SOURCE(pTxBlk->pPacket) == MESH_PROXY) + COPY_MAC_ADDR(&subFrameHeader[6], pAd->MeshTab.CurrentAddress); + else + COPY_MAC_ADDR(&subFrameHeader[6], pTxBlk->pSrcBufHeader + MAC_ADDR_LEN); /* ADDR4 = SA */ + } +#endif /* MESH_SUPPORT */ + + pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD; + pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD; + + +#ifdef MESH_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry)) + subFramePayloadLen += InsertPktMeshHeader(pAd, pTxBlk, &pHeaderBufPtr); +#endif /* MESH_SUPPORT */ + + /* 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; + + + /*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */ + + 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++; + +#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 += totalMPDUSize; + pMbss->TxCount ++; + +#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; + } + } + +#ifdef WDS_SUPPORT + if (pTxBlk->pMacEntry && IS_ENTRY_WDS(pTxBlk->pMacEntry)) + { + INC_COUNTER64(pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->MatchWDSTabIdx].WdsCounter.TransmittedFragmentCount); + pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->MatchWDSTabIdx].WdsCounter.TransmittedByteCount+= pTxBlk->SrcBufLen; + } +#endif /* WDS_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 */ + + +VOID AP_Legacy_Frame_Tx( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + HEADER_802_11 *pHeader_802_11; + PUCHAR pHeaderBufPtr; +/* UCHAR QueIdx = pTxBlk->QueIdx; */ + USHORT FreeNumber = 1; /* no use */ + 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) + { +#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); + 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; + + /*DBGPRINT(RT_DEBUG_TRACE, ("Dump Original packet: Len=%d!\n", GET_OS_PKT_LEN(pTxBlk->pTxPacket))); */ + /*hex_dump("Pkt:", GET_OS_PKT_DATAPTR(pTxBlk->pTxPacket), GET_OS_PKT_LEN(pTxBlk->pTxPacket)); */ + + /* skip vlan tag */ + 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]; + 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) | (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx]<<5)); +#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 */ +#ifdef MESH_SUPPORT + && (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry) == FALSE) +#endif /* MESH_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 (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; + + } + 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; + 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 + + /* + 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 */ + pHeader_802_11->FC.Order = 1; + + /* hex_dump("HT_Ctrl Field", pHeaderBufPtr, 4); */ + 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)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 */ + { +#ifdef MESH_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry)) + InsertPktMeshHeader(pAd, pTxBlk, &pHeaderBufPtr); +#endif /* MESH_SUPPORT */ + + /* + 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 */ +#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 */ + + if (pMbss != NULL) + { + pMbss->TransmittedByteCount += pTxBlk->SrcBufLen; + pMbss->TxCount ++; + +#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; + } + } + +#ifdef WDS_SUPPORT + if (pTxBlk->pMacEntry && IS_ENTRY_WDS(pTxBlk->pMacEntry)) + { + INC_COUNTER64(pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->MatchWDSTabIdx].WdsCounter.TransmittedFragmentCount); + pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->MatchWDSTabIdx].WdsCounter.TransmittedByteCount+= pTxBlk->SrcBufLen; + } +#endif /* WDS_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, (PTXWI_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++; + + /* + Kick out Tx + */ + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); + + +} + + +VOID AP_Fragment_Frame_Tx( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk) +{ + HEADER_802_11 *pHeader_802_11; + PUCHAR pHeaderBufPtr; +/* UCHAR QueIdx = pTxBlk->QueIdx; */ + USHORT FreeNumber = 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 + PUCHAR tmp_ptr = NULL; + UINT32 buf_offset = 0; +#endif /* SOFT_ENCRYPT */ + HTTRANSMIT_SETTING *pTransmit; + 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++; +#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 */ + { +#ifdef MESH_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry)) + InsertPktMeshHeader(pAd, pTxBlk, &pHeaderBufPtr); +#endif /* MESH_SUPPORT */ + + /* + 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); + /*skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8); */ + pTxBlk->SrcBufLen += 8; + pTxBlk->TotalFrameLen += 8; + } + +#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 */ + + if (pMbss != NULL) + { + pMbss->TransmittedByteCount += pTxBlk->SrcBufLen; + pMbss->TxCount ++; + +#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; + } + } + +#ifdef WDS_SUPPORT + if (pTxBlk->pMacEntry && IS_ENTRY_WDS(pTxBlk->pMacEntry)) + { + INC_COUNTER64(pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->MatchWDSTabIdx].WdsCounter.TransmittedFragmentCount); + pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->MatchWDSTabIdx].WdsCounter.TransmittedByteCount+= pTxBlk->SrcBufLen; + } +#endif /* WDS_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); + } + /*DBGPRINT(RT_DEBUG_INFO, ("!!!%s : Frag#%d !!!\n", __FUNCTION__, pHeader_802_11->Frag)); */ + + 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, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + + /*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */ + + HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &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++; + +#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( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + PUCHAR pHeaderBufPtr; +/* UCHAR QueIdx = pTxBlk->QueIdx; */ + USHORT FreeNumber = 1; /* no use */ + 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) + { +#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); + continue; + } + + /*pTxBlk->bVLANPkt = RTMP_GET_PACKET_VLAN(pTxBlk->pPacket); */ + 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 = AP_Build_ARalink_Frame_Header(pAd, pTxBlk); + + /* + It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount + will be updated after final frame was handled. + */ + RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + +#ifdef MESH_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry)) + InsertPktMeshHeader(pAd, pTxBlk, &pHeaderBufPtr); +#endif /* MESH_SUPPORT */ + + /* 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 = LENGTH_ARALINK_SUBFRAMEHEAD; + } + + totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + + /*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */ + 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.OneSecTxAggregationCount++; + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + +#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 += totalMPDUSize; +#endif /* WAPI_SUPPORT */ + + if (pMbss != NULL) + { + pMbss->TransmittedByteCount += totalMPDUSize; + pMbss->TxCount ++; + +#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; + } + + } + +#ifdef WDS_SUPPORT + if (pTxBlk->pMacEntry && IS_ENTRY_WDS(pTxBlk->pMacEntry)) + { + INC_COUNTER64(pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->MatchWDSTabIdx].WdsCounter.TransmittedFragmentCount); + pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->MatchWDSTabIdx].WdsCounter.TransmittedByteCount+= pTxBlk->SrcBufLen; + } +#endif /* WDS_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); + +} + + +/* + ======================================================================== + 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 + ======================================================================== +*/ +NDIS_STATUS APHardTransmit( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR QueIdx) +{ + PQUEUE_ENTRY pQEntry; + PNDIS_PACKET pPacket; + UCHAR apidx; + +/* PQUEUE_HEADER pQueue; */ + + 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; + } + + apidx = RTMP_GET_PACKET_NET_DEVICE_MBSSID(pTxBlk->pPacket); + if (apidx < pAd->ApCfg.BssidNum) + { + /* carry VLAN in the air */ + if (pAd->ApCfg.MBSSID[apidx].bVLAN_Tag == TRUE) + { + RTMP_SET_PACKET_VLAN(pTxBlk->pPacket, FALSE); + } + } + + + switch (pTxBlk->TxFrameType) + { +#ifdef DOT11_N_SUPPORT + case TX_AMPDU_FRAME: + AP_AMPDU_Frame_Tx(pAd, pTxBlk); + break; +#endif /* DOT11_N_SUPPORT */ + case TX_LEGACY_FRAME: + case TX_MCAST_FRAME: + AP_Legacy_Frame_Tx(pAd, pTxBlk); + 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 + ======================================================================== +*/ +NDIS_STATUS APCheckRxError( + IN PRTMP_ADAPTER pAd, + IN PRT28XX_RXD_STRUC pRxD, + IN UCHAR Wcid) +{ + if (pRxD->Crc || pRxD->CipherErr) + { + /* + WCID equ 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 ((pRxD->U2M) + && (pRxD->CipherErr) + && (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 + return NDIS_STATUS_FAILURE; + } + else + { + 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 APCheckClass2Class3Error( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN PHEADER_802_11 pHeader) +{ + /* 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) + { + APCls2errAction(pAd, MAX_LEN_OF_MAC_TABLE, pHeader); + 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, pHeader); + return TRUE; + } + else + { + APCls2errAction(pAd, Wcid, pHeader); + return TRUE; + } + return FALSE; +} + +/* + ======================================================================== + 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 APHandleRxPsPoll( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN USHORT Aid, + IN BOOLEAN isActive) +{ + PQUEUE_ENTRY pEntry; + PMAC_TABLE_ENTRY pMacEntry; + unsigned long IrqFlags; + + /*DBGPRINT(RT_DEBUG_TRACE,("rcv PS-POLL (AID=%d) from %02x:%02x:%02x:%02x:%02x:%02x\n", */ + /* Aid, pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5])); */ + + pMacEntry = &pAd->MacTab.Content[Aid]; + if (RTMPEqualMemory(pMacEntry->Addr, pAddr, MAC_ADDR_LEN)) + { + /* + 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 */ + } /* End of if */ +#endif /* UAPSD_SUPPORT */ + + /*NdisAcquireSpinLock(&pAd->MacTabLock); */ + /*NdisAcquireSpinLock(&pAd->TxSwQueueLock); */ + 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 */ + + pEntry = RemoveHeadQueue(&pMacEntry->PsQueue); + if ( pMacEntry->PsQueue.Number >=1 ) + RTMP_SET_PACKET_MOREDATA(RTPKT_TO_OSPKT(pEntry), TRUE); + InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QID_AC_BE], pEntry); + +#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(pEntry)) || + RTMP_GET_PACKET_EAPOL(RTPKT_TO_OSPKT(pEntry)) || + RTMP_GET_PACKET_WAI(RTPKT_TO_OSPKT(pEntry))) + { + /* + 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; + + ApEnqueueNullFrame(pAd, pMacEntry->Addr, pMacEntry->CurrTxRate, + 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) + { + pEntry = RemoveHeadQueue(&pMacEntry->PsQueue); + InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QID_AC_BE], pEntry); + } /* End of while */ + } /* End of if */ + + /*NdisReleaseSpinLock(&pAd->TxSwQueueLock); */ + /*NdisReleaseSpinLock(&pAd->MacTabLock); */ + + if ((Aid > 0) && (Aid < MAX_LEN_OF_MAC_TABLE) && + (pMacEntry->PsQueue.Number == 0)) + { + /* clear corresponding TIM bit because no any PS packet */ + WLAN_MR_TIM_BIT_CLEAR(pAd, pMacEntry->apidx, Aid); + 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", + Aid, pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5])); + + } +} + + + +/* + detect AC Category of trasmitting packets + to turn AC0(BE) TX_OP (MAC reg 0x1300) +*/ +/*static UCHAR is_on; */ +VOID detect_wmm_traffic( + IN PRTMP_ADAPTER pAd, + IN UCHAR UserPriority, + IN UCHAR FlgIsOutput) +{ + /* 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 (MapUserPriorityToAccessCategory[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( + IN PRTMP_ADAPTER pAd, + IN 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) + { + /* enable AC0(BE) TX_OP */ + UCHAR txop_value_burst = 0x20; /* default txop for Tx-Burst */ + UCHAR txop_value; + +#ifdef LINUX +#ifdef RTMP_RBUS_SUPPORT + if (pAd->infType == RTMP_DEV_INF_RBUS) + { +#ifdef CONFIG_RAETH_ROUTER + txop_value_burst = 0x10; +#endif /* CONFIG_RAETH_ROUTER */ +#ifdef CONFIG_MAC_TO_MAC_MODE + txop_value_burst = 0x30; +#endif /* CONFIG_MAC_TO_MAC_MODE */ + } +#endif /* RTMP_RBUS_SUPPORT */ +#endif /* LINUX */ + + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &RegValue); + + 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->CommonCfg.bEnableTxBurst) + txop_value = txop_value_burst; + else + txop_value = 0; + + 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 APRxDErrorHandle( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + MAC_TABLE_ENTRY *pEntry; + PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + PCIPHER_KEY pWpaKey; + UCHAR FromWhichBSSID = BSS0; + UCHAR Wcid; + PHEADER_802_11 pHeader = pRxBlk->pHeader; +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + if (pRxD->CipherErr) + INC_COUNTER64(pAd->WlanCounters.WEPUndecryptableCount); + + if (/*pRxD->U2M && */pRxD->CipherErr) + { + if (pRxWI->WirelessCliID < MaxWcidNum) + { +#ifdef APCLI_SUPPORT +//#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + + Wcid = pRxWI->WirelessCliID; + if (VALID_WCID(Wcid)) + pEntry = ApCliTableLookUpByWcid(pAd, Wcid, pHeader->Addr2); + else + pEntry = MacTableLookup(pAd, pHeader->Addr2); + + if (pEntry && IS_ENTRY_APCLI(pEntry)) + { + FromWhichBSSID = pEntry->MatchAPCLITabIdx + MIN_NET_DEVICE_FOR_APCLI; + + + + if (pRxD->CipherErr == 2) + { + pWpaKey = &pEntry->PairwiseKey; +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + if (pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].WpaSupplicantUP) + WpaSendMicFailureToWpaSupplicant(pAd->net_dev, + (pWpaKey->Type == + PAIRWISEKEY) ? TRUE : + FALSE); + if (((pRxD->CipherErr & 2) == 2) && INFRA_ON(pAd)) + RTMPSendWirelessEvent(pAd, IW_MIC_ERROR_EVENT_FLAG, pEntry->Addr, FromWhichBSSID, 0); +#else + ApCliRTMPReportMicError(pAd, pWpaKey, pEntry->MatchAPCLITabIdx); +#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ + DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n")); + } + } + else +//#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + if (pRxD->U2M) + { + pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID]; + + /* + MIC error + Before verifying the MIC, the receiver shall check FCS, ICV and TSC. + This avoids unnecessary MIC failure events. + */ + if ((pEntry->WepStatus == Ndis802_11Encryption2Enabled) + && (pRxD->CipherErr == 2)) + { +#ifdef HOSTAPD_SUPPORT + if(pAd->ApCfg.MBSSID[pEntry->apidx].Hostapd == TRUE) + { + ieee80211_notify_michael_failure(pAd, pRxBlk->pHeader, (UINT32) pRxWI->KeyIndex, 0); + } + else +#endif/*HOSTAPD_SUPPORT*/ + { + RTMP_HANDLE_COUNTER_MEASURE(pAd, pEntry); + } + + } + + /* send wireless event - for icv error */ + if ((pRxD->CipherErr & 1) == 1) + RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG, pEntry->Addr, 0, 0); + } + } + DBGPRINT(RT_DEBUG_TRACE, ("Rx u2me Cipher Err(MPDUsize=%d, WCID=%d, CipherErr=%d)\n", + pRxWI->MPDUtotalByteCount, pRxWI->WirelessCliID, pRxD->CipherErr)); + + } + + pAd->Counters8023.RxErrors++; + DBGPRINT(RT_DEBUG_TRACE, ("APCheckRxError\n")); + +} + + +BOOLEAN APCheckVaildDataFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PHEADER_802_11 pHeader = pRxBlk->pHeader; + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; + + BOOLEAN isVaild = FALSE; + + do + { +#ifndef APCLI_SUPPORT + /* should not drop Ap-Client packet. */ + if (pHeader->FC.ToDs == 0) + break; /* give up this frame */ +#endif /* APCLI_SUPPORT */ + + /* check if Class2 or 3 error */ + if ((pHeader->FC.FrDs == 0) && (APCheckClass2Class3Error(pAd, pRxWI->WirelessCliID, pHeader))) + break; /* give up this frame */ + + if(pAd->ApCfg.BANClass3Data == TRUE) + break; /* give up this frame */ + + 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_WPA_SUPPLICANT_SUPPORT + if (IS_ENTRY_APCLI(pEntry) && pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].WpaSupplicantUP) + { + WpaSendMicFailureToWpaSupplicant(pAd->net_dev, + (pWpaKey->Type == + PAIRWISEKEY) ? TRUE : + FALSE); + } + else +#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ + { + RTMP_HANDLE_COUNTER_MEASURE(pAd, pEntry); + } + + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return FALSE; + } + + return TRUE; +} + + +VOID APHandleRxMgmtFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; + PHEADER_802_11 pHeader = pRxBlk->pHeader; + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + BOOLEAN bPassTheBcastPkt = FALSE; + + do + { +#ifdef MESH_SUPPORT + if (pHeader->FC.SubType == SUBTYPE_MULTIHOP) + { + MlmeHandleRxMeshFrame(pAd, pRxBlk); + break; + } +#endif /* MESH_SUPPORT */ + + +#ifdef IDS_SUPPORT + /* Check if a rogue AP impersonats our mgmt frame to spoof clients */ + if (RTMPSpoofedMgmtDetection(pAd, pHeader, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2)) + { + /* This is a spoofed frame, so give up it. */ + break; + } +#endif /* IDS_SUPPORT */ + +#ifdef IDS_SUPPORT + /* update sta statistics for traffic flooding detection later */ + RTMPUpdateStaMgmtCounter(pAd, pHeader->FC.SubType); +#endif /* IDS_SUPPORT */ + + if (!pRxD->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 + INT i; + if (pAd->bApCliCertTest == TRUE) + { + for (i = 0; i < MAX_APCLI_NUM; i++) + { + if (MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[i].CurrentAddress, pHeader->Addr1)) + bPassTheBcastPkt = TRUE; /* Let this Action Frame pass */ + } + } +#endif /* APCLI_CERT_SUPPOR */ +#endif /* APCLI_SUPPORT */ + + if (!bPassTheBcastPkt) + break; /* Skip this packet */ + } + else + break; /* 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")); + break; + } + } + + /* Software decrypts WEP data during shared WEP negotiation */ + if ((pHeader->FC.SubType == SUBTYPE_AUTH) && + (pHeader->FC.Wep == 1) && (pRxD->Decrypted == 0)) + { + PUCHAR pMgmt = (PUCHAR)pHeader; + UINT16 mgmt_len = pRxWI->MPDUtotalByteCount; + PMAC_TABLE_ENTRY pEntry = NULL; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + + /* Skip 802.11 headre */ + pMgmt += LENGTH_802_11; + mgmt_len -= LENGTH_802_11; + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + if (pRxWI->WirelessCliID < MaxWcidNum) + pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID]; + + if (pEntry == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: SW decrypt WEP data fails - the Entry is empty.\n")); + break; + } + + /* handle WEP decryption */ + if (RTMPSoftDecryptWEP(pAd, + &pAd->SharedKey[pEntry->apidx][pRxWI->KeyIndex], + pMgmt, + &mgmt_len) == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: SW decrypt WEP data fails.\n")); + /* give up this frame */ + break; + } +#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 */ + pRxWI->MPDUtotalByteCount -= (LEN_WEP_IV_HDR + LEN_ICV); + } + + 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); + break; + } + + if (pHeader->FC.SubType == SUBTYPE_ACTION) + { + /* only PM bit of ACTION frame can be set */ + MAC_TABLE_ENTRY *pEntry = NULL; + + pEntry = PACInquiry(pAd, pRxWI->WirelessCliID); + if (pEntry != NULL) + APPsIndicate(pAd, pHeader->Addr2, pEntry->Aid, 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 */ + } + + REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, + pRxWI->MPDUtotalByteCount, + pRxWI->RSSI0, pRxWI->RSSI1, + pRxWI->RSSI2, 0, OPMODE_AP); + +#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 */ + } while (0); + + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); + return; +} + +VOID APHandleRxControlFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PHEADER_802_11 pHeader = pRxBlk->pHeader; + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + + switch (pHeader->FC.SubType) + { +#ifdef DOT11_N_SUPPORT + case SUBTYPE_BLOCK_ACK_REQ: + { + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; + CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader); + } + break; +#endif /* DOT11_N_SUPPORT */ + /* handle PS-POLL here */ + case SUBTYPE_PS_POLL: + { + USHORT Aid = pHeader->Duration & 0x3fff; + PUCHAR pAddr = pHeader->Addr2; + + if (Aid < MAX_LEN_OF_MAC_TABLE) + APHandleRxPsPoll(pAd, pAddr, Aid, FALSE); + } + break; +#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); + return; +} + +VOID APRxEAPOLFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + /*PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); */ /* not used */ + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; + BOOLEAN CheckPktSanity = TRUE; + UCHAR *pTmpBuf; +#ifdef APCLI_SUPPORT +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + INT eapcode; +#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + do + { +#ifdef P2P_SUPPORT + if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_P2P_GO) + { + break; + } +#endif /* P2P_SUPPORT */ +#ifdef MESH_SUPPORT + if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_MESH) + { + UINT mesh_header_len = GetMeshHederLen(pRxBlk->pData); + + /* skip mesh header */ + pRxBlk->pData += mesh_header_len; + pRxBlk->DataSize -= mesh_header_len; + break; + } +#endif /* MESH_SUPPORT */ + } 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 EASY_CONFIG_SETUP + if (pEntry && + (pAd->ApCfg.MBSSID[pEntry->apidx].EasyConfigInfo.bEnable) && + (pEntry->bRaAutoWpsCapable) +#ifdef WSC_AP_SUPPORT + && (pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscConfMode == WSC_DISABLE) +#endif /* WSC_AP_SUPPORT */ + ) + { + PSTRING pData; + PEAP_FRAME pEapFrame = NULL; + + /* Skip the EAP LLC header */ + pData = (PSTRING) (pRxBlk->pData + LENGTH_802_1_H); + if (pData) + pEapFrame = (PEAP_FRAME)(pData + sizeof(IEEE8021X_FRAME)); + pData += (sizeof(IEEE8021X_FRAME) + sizeof(EAP_FRAME)); + + if ((pData != NULL) && + (pEapFrame != NULL) && + (pEapFrame->Code == EAP_CODE_RSP) && + (pEapFrame->Type == EAP_TYPE_WSC)) + { + if (WscCheckWSCHeader((PUCHAR) pData)) + { + /* EAP-Rsp (Messages) */ + pData += sizeof(WSC_FRAME); + if (pData && (pData + 9)) + { + UCHAR MsgType = *(pData + 9); + if (MsgType == 0x04) /* M1 */ + { + if (pEntry) + { + AutoProvisionDecodeExtData(pAd, pEntry->apidx, pEntry->Addr, pRxBlk->pData + (pRxBlk->DataSize -15)); + } + } + } + } + } + } +#endif /* EASY_CONFIG_SETUP */ + + +#ifdef HOSTAPD_SUPPORT + if ((pEntry) && pAd->ApCfg.MBSSID[pEntry->apidx].Hostapd == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Indicate_Legacy_Packet\n")); + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + return; + } +#endif/*HOSTAPD_SUPPORT*/ + + +#ifdef APCLI_SUPPORT +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { + eapcode=ApcliWpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H); + printk("eapcode=%d\n",eapcode); + if ( pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].WpaSupplicantUP && + pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].IEEE8021X == TRUE && + (EAP_CODE_SUCCESS == eapcode)) + { + PUCHAR Key; + UCHAR CipherAlg; + int idx = 0; + int BssIdx = pAd->ApCfg.BssidNum + MAX_MESH_NUM + pEntry->MatchAPCLITabIdx; + + 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 (pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].IEEE8021x_required_keys == FALSE) + { + idx = pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].DesireSharedKeyId; + CipherAlg = pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].DesireSharedKey[idx].CipherAlg; + Key = pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].DesireSharedKey[idx].Key; + + if (pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].DesireSharedKey[idx].KeyLen > 0) + { + /* Set key material and cipherAlg to Asic */ + RTMP_ASIC_SHARED_KEY_TABLE(pAd,BssIdx, idx, &pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].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->Aid, SHAREDKEYTABLE); + + /* RTMP_IndicateMediaState(pAd, NdisMediaStateConnected); */ + /* pAd->ExtraInfo = GENERAL_LINK_UP; */ + + /* For Preventing ShardKey Table is cleared by remove key procedure. */ + pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].SharedKey[idx].CipherAlg = CipherAlg; + pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].SharedKey[idx].KeyLen = pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].DesireSharedKey[idx].KeyLen; + NdisMoveMemory(pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].SharedKey[idx].Key, + pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].DesireSharedKey[idx].Key, + pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].DesireSharedKey[idx].KeyLen); + } + } + } + + if(pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].WpaSupplicantUP && + ((pEntry->AuthMode == Ndis802_11AuthModeWPA) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2) || pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].IEEE8021X == TRUE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Indicate_Legacy_Packet\n")); + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + return; + } + } +#endif/*APCLI_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].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); + REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, 0, OPMODE_AP); + 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); + REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, 0, OPMODE_AP); + } + +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); + } +} + + +VOID APRxDataFrameAnnounce( + 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)) + { +#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 */ + + /* + 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 MESH_SUPPORT + if (pEntry && IS_ENTRY_MESH(pEntry)) + { + UINT32 MeshSeq = GetMeshSeq(pRxBlk->pData); + PHEADER_802_11 pHeader = pRxBlk->pHeader; + PUCHAR pMeshDA = pHeader->Addr3; + PUCHAR pMeshSA = (PUCHAR)(pHeader->Octet); + PUCHAR pSA = GetMeshAddr6(pRxBlk->pData); + + if (PktSigCheck(pAd, pHeader->Addr2, pMeshDA, pMeshSA, MeshSeq, BTYPE_DATA) == FALSE) + { + /* signature exist, it means it's a duplicate packet. drop it. */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + if ((pMeshSA != NULL) && (pSA != NULL) && (pAd->MeshTab.OpMode & MESH_AP)) + { + if (!MAC_ADDR_EQUAL(pMeshSA, pSA)) + { + PMESH_PROXY_ENTRY pMeshProxyEntry; + + pMeshProxyEntry = MeshProxyEntryTableLookUp(pAd, pSA); + if (!pMeshProxyEntry) + MeshProxyEntryTableInsert(pAd, pMeshSA, pSA); + } + } + } +#endif /* MESH_SUPPORT */ + +#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))); + + 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(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 */ + { + /* Determin the destination of the EAP frame */ + /* to WPA state machine or upper layer */ + APRxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); + } + } +} + + + +/* + 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( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; + PHEADER_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) + BOOLEAN bWdsPacket = FALSE; +#endif /* WDS_SUPPORT || CLIENT_WDS */ +#ifdef MESH_SUPPORT + BOOLEAN bMeshPacket = FALSE; +#endif /* MESH_SUPPORT */ + FRAME_CONTROL *pFmeCtrl = &pHeader->FC; + COUNTER_RALINK *pCounter = &pAd->RalinkCounters; + + + 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, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2) == 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 += pRxWI->MPDUtotalByteCount; + pMbss->RxCount ++; + } + } + RX_BLK_SET_FLAG(pRxBlk, fRX_WDS); + bWdsPacket = TRUE; + CliWds_ProxyTabUpdate(pAd, pEntry->Aid, pHeader->Octet); + break; + } +#endif /* CLIENT_WDS */ + +#ifdef MESH_SUPPORT + /* handle MESH */ + if (VALID_WCID(pRxWI->WirelessCliID) + && IS_ENTRY_MESH(&pAd->MacTab.Content[pRxWI->WirelessCliID])) + { + bMeshPacket = TRUE; + pEntry = FindMeshEntry(pAd, pRxWI->WirelessCliID, pHeader->Addr2); + + /* No valid mesh entry exist, so discard the incoming packet. */ + if (!(pEntry && MESH_ON(pAd))) + { /* drop the packet. */ + pEntry = NULL; + break; + } + + RX_BLK_SET_FLAG(pRxBlk, fRX_MESH); + FromWhichBSSID = pEntry->MatchMeshTabIdx + MIN_NET_DEVICE_FOR_MESH; + break; + } + + if (MeshLinkLookUp(pAd, pHeader->Addr2) != NULL) + { + /* Drop all packets for invaild Mesh Link. */ + pEntry = NULL; + break; + } +#endif /* MESH_SUPPORT */ + +#ifdef WDS_SUPPORT + /* handle WDS */ + { + bWdsPacket = TRUE; + if (MAC_ADDR_EQUAL(pHeader->Addr1, pAd->CurrentAddress)) + pEntry = FindWdsEntry(pAd, pRxWI->WirelessCliID, pHeader->Addr2, pRxWI->PHYMODE); + else + pEntry = NULL; + + + /* have no valid wds entry exist, then discard the incoming packet.*/ + if (!(pEntry && WDS_IF_UP_CHECK(pAd, pEntry->MatchWDSTabIdx))) + { + /* drop the packet */ + 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; + } + + RX_BLK_SET_FLAG(pRxBlk, fRX_WDS); + FromWhichBSSID = pEntry->MatchWDSTabIdx + 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(pRxWI->WirelessCliID)) + pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID]; + else + pEntry = MacTableLookup(pAd, pHeader->Addr2); + + if (pEntry && IS_ENTRY_APCLI(pEntry)) + { + if (!(pEntry && APCLI_IF_UP_CHECK(pAd, pEntry->MatchAPCLITabIdx))) + { + goto err; + } + + FromWhichBSSID = pEntry->MatchAPCLITabIdx + MIN_NET_DEVICE_FOR_APCLI; + RX_BLK_SET_FLAG(pRxBlk, fRX_APCLI); + + /* Process broadcast packets */ + if (pRxD->Mcast || pRxD->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, pRxWI->WirelessCliID); + + /* 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 && + pRxD->U2M && + FromWhichBSSID < pAd->ApCfg.BssidNum) + { + MULTISSID_STRUCT *pMbss = pEntry->pMbss; + if (pMbss != NULL) + { + pMbss->ReceivedByteCount += pRxWI->MPDUtotalByteCount; + pMbss->RxCount ++; + } + } + + /* update multicast counter */ + if (IS_MULTICAST_MAC_ADDR(pHeader->Addr3)) + INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount); +#endif /* STATS_COUNT_SUPPORT */ +#ifdef P2P_SUPPORT + if (IS_P2P_GO_ENTRY(pEntry)) + { + FromWhichBSSID = pEntry->apidx + MIN_NET_DEVICE_FOR_P2P_GO; + } +#endif /* P2P_SUPPORT */ + } + + ASSERT(pEntry->Aid == pRxWI->WirelessCliID); + + + + + /* update rssi sample */ + Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI); + + if (pRxD->U2M) + { + pEntry->LastRxRate = (ULONG)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8) + (pRxWI->STBC <<9) + (pRxWI->PHYMODE <<14)); + +#ifdef TXBF_SUPPORT + if (pRxWI->ShortGI) + pEntry->OneSecRxSGICount++; + else + pEntry->OneSecRxLGICount++; +#endif // TXBF_SUPPORT // + } + + pAd->ApCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0); + pAd->ApCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1); +#ifdef DOT11N_SS3_SUPPORT + pAd->ApCfg.LastSNR2 = (UCHAR)(pRxWI->SNR2); +#endif /* DOT11N_SS3_SUPPORT */ + pEntry->freqOffset = (CHAR)(pRxWI->FOFFSET); + pEntry->freqOffsetValid = TRUE; + +#if defined(RT2883) || defined (RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + { + pEntry->BF_SNR[0] = BF_SNR_OFFSET + pRxWI->BF_SNR0; + pEntry->BF_SNR[1] = BF_SNR_OFFSET + pRxWI->BF_SNR1; + pEntry->BF_SNR[2] = BF_SNR_OFFSET + pRxWI->BF_SNR2; + } +#endif /* defined(RT2883) || defined (RT3883) */ + + /* 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 = APPsIndicate(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 = (*(pRxBlk->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 && + pRxD->U2M && + pRxWI->BSSID < pAd->ApCfg.BssidNum) + { + pAd->ApCfg.MBSSID[pRxWI->BSSID].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) + if (FALSE +#if defined(WDS_SUPPORT) || defined(CLIENT_WDS) + || bWdsPacket +#endif /* WDS_SUPPORT || CLIENT_WDS */ +#ifdef MESH_SUPPORT + || bMeshPacket +#endif /* MESH_SUPPORT */ + ) + { + pRxBlk->pData += LENGTH_802_11_WITH_ADDR4; + pRxBlk->DataSize -= LENGTH_802_11_WITH_ADDR4; + } + else +#endif /* WDS_SUPPORT || CLIENT_WDS || MESH_SUPPORT */ + { + pRxBlk->pData += LENGTH_802_11; + pRxBlk->DataSize -= LENGTH_802_11; + } + + /* 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) +#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 ++; + +#if defined(WDS_SUPPORT) || defined(CLIENT_WDS) || defined(MESH_SUPPORT) + if (FALSE +#if defined(WDS_SUPPORT) || defined(CLIENT_WDS) + || bWdsPacket +#endif /* WDS_SUPPORT || CLIENT_WDS*/ +#ifdef MESH_SUPPORT + || bMeshPacket +#endif /* MESH_SUPPORT */ + ) + { + pCounter->ReceivedOctesInAMSDUCount.QuadPart += (pRxBlk->DataSize + LENGTH_802_11_WITH_ADDR4); + } + else +#endif /* WDS_SUPPORT || CLIENT_WDS || MESH_SUPPORT */ + { + pCounter->ReceivedOctesInAMSDUCount.QuadPart += (pRxBlk->DataSize + LENGTH_802_11); + } + } + + /* 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 + (pRxWI->PHYMODE < 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 (pRxD->L2PAD) + { + /* just move pData pointer */ + /* because DataSize excluding HW padding */ + RX_BLK_SET_FLAG(pRxBlk, fRX_PAD); + pRxBlk->pData += 2; + } + + if (pRxD->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) && (pRxD->Decrypted == 0)) + { + if (RTMPSoftDecryptionAction(pAd, + (PUCHAR)pHeader, + UserPriority, + &pEntry->PairwiseKey, + pRxBlk->pData, + &(pRxBlk->DataSize)) != NDIS_STATUS_SUCCESS) + { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + /* Record the Decrypted bit as 1 */ + pRxD->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_11Encryption2Enabled)) + { + /* Minus MIC length */ + pRxBlk->DataSize -= 8; + + /* For TKIP frame, calculate the MIC value */ + if (APCheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE) + { + return; + } + } + + if (pEntry) + { + pEntry->RxBytes+=pRxWI->MPDUtotalByteCount; + 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, pRxWI->WirelessCliID); +#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 && + pRxD->U2M && + pRxWI->BSSID < pAd->ApCfg.BssidNum) + { + pAd->ApCfg.MBSSID[pRxWI->BSSID].RxDropCount ++; + pAd->ApCfg.MBSSID[pRxWI->BSSID].RxErrorCount ++; + } + + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + +} + +/* + ======================================================================== + 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 (32) + +BOOLEAN APRxDoneInterruptHandle( + IN PRTMP_ADAPTER pAd) +{ + UINT32 RxProcessed, RxPending; + BOOLEAN bReschedule = FALSE; + RT28XX_RXD_STRUC *pRxD; + UCHAR *pData; + PRXWI_STRUC pRxWI; + PNDIS_PACKET pRxPacket; + PHEADER_802_11 pHeader; + RX_BLK RxCell, *pRxCell; + MULTISSID_STRUCT *pMbss; + UINT8 RXWISize = pAd->chipCap.RXWISize; +#ifdef WDS_SUPPORT + MAC_TABLE_ENTRY *pEntry = NULL; +#endif + +#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)) || + !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP)) + { + break; + } + +#ifdef UAPSD_SUPPORT + UAPSD_TIMING_RECORD_INDEX(RxProcessed); +#endif /* UAPSD_SUPPORT */ + +#ifdef RTMP_MAC_PCI + if (RxProcessed++ > MAX_RX_PROCESS_CNT) + { + bReschedule = TRUE; + 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 */ + +#ifdef VENDOR_FEATURE1_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 >= 4) + { + NICUpdateFifoStaCounters(pAd); + pAd->FifoUpdateDone = 0; + } +#else + NICUpdateFifoStaCounters(pAd); +#endif /* VENDOR_FEATURE1_SUPPORT */ +#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 + */ + + pRxCell = &RxCell; + pRxPacket = GetPacketFromRxRing(pAd, &(pRxCell->RxD), &bReschedule, &RxPending); + if (pRxPacket == NULL) + break; + + /* get rx descriptor and data buffer */ + pRxD = &(pRxCell->RxD); + pData = GET_OS_PKT_DATAPTR(pRxPacket); + pRxWI = (PRXWI_STRUC)pData; + pHeader = (PHEADER_802_11)(pData + RXWISize); + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHeader, DIR_READ, TRUE); + RTMPWIEndianChange(pAd , (PUCHAR)pRxWI, TYPE_RXWI); +#endif + +#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 RxCell */ + pRxCell->pRxWI = pRxWI; + pRxCell->pHeader = pHeader; + pRxCell->pRxPacket = pRxPacket; + pRxCell->pData = (UCHAR *) pHeader; + pRxCell->DataSize = pRxWI->MPDUtotalByteCount; + pRxCell->Flags = 0; + SET_OPMODE_AP(&RxCell); + + /* Increase Total receive byte counter after real data received no mater any error or not */ + pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount; + pAd->RalinkCounters.OneSecReceivedByteCount += pRxWI->MPDUtotalByteCount; + 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, pRxD, pHeader); + } + +#ifdef TXBF_SUPPORT + /* Check sounding frame */ + if ((pAd->chipCap.FlgHwTxBfCap) && (pHeader->FC.Type == BTYPE_MGMT)) + { + RX_BLK *pRxBlk = &RxCell; + + 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 */ + /*printk("Receive sounding response\n"); */ + 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])); + } + } +#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 WDS_SUPPORT + if ((pHeader->FC.FrDs == 1) && (pHeader->FC.ToDs == 1)) + { + if (MAC_ADDR_EQUAL(pHeader->Addr1, pAd->CurrentAddress)) + pEntry = FindWdsEntry(pAd, pRxWI->WirelessCliID, pHeader->Addr2, pRxWI->PHYMODE); + +#ifdef STATS_COUNT_SUPPORT + if(pEntry) + { + pAd->WdsTab.WdsEntry[pEntry->MatchWDSTabIdx].WdsCounter.ReceivedByteCount += pRxWI->MPDUtotalByteCount; + INC_COUNTER64(pAd->WdsTab.WdsEntry[pEntry->MatchWDSTabIdx].WdsCounter.ReceivedFragmentCount); + + if(IS_MULTICAST_MAC_ADDR(pHeader->Addr3)) + INC_COUNTER64(pAd->WdsTab.WdsEntry[pEntry->MatchWDSTabIdx].WdsCounter.MulticastReceivedFrameCount); + + } +#endif /* STATS_COUNT_SUPPORT */ + } +#endif /* WDS_SUPPORT */ + + /* Check for all RxD errors */ + if (APCheckRxError(pAd, pRxD, pRxWI->WirelessCliID) != NDIS_STATUS_SUCCESS) + { + APRxDErrorHandle(pAd, &RxCell); + + /* Increase received error packet counter per BSS */ + if (pHeader->FC.FrDs == 0 && + pRxD->U2M && + pRxWI->BSSID < pAd->ApCfg.BssidNum) + { + pMbss = &pAd->ApCfg.MBSSID[pRxWI->BSSID]; + pMbss->RxDropCount ++; + pMbss->RxErrorCount ++; + } + +#ifdef WDS_SUPPORT +#ifdef STATS_COUNT_SUPPORT + if ((pHeader->FC.FrDs == 1) && (pHeader->FC.ToDs == 1)) + { + if (MAC_ADDR_EQUAL(pHeader->Addr1, pAd->CurrentAddress)) + pEntry = FindWdsEntry(pAd, pRxWI->WirelessCliID, pHeader->Addr2, pRxWI->PHYMODE); + if(pEntry) + pAd->WdsTab.WdsEntry[pEntry->MatchWDSTabIdx].WdsCounter.RxErrors++; + } +#endif /* STATS_COUNT_SUPPORT */ +#endif /* WDS_SUPPORT */ + /* discard this frame */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + continue; + } + + /* + All frames to AP are directed except probe_req. IEEE 802.11/1999 - p.463 + Do this before checking "duplicate frame". + 2003-08-20 accept BEACON to decide if OLBC (Overlapping Legacy BSS Condition) happens + TODO: consider move this code to be inside "APCheckRxError()" + */ + switch (pHeader->FC.Type) + { + case BTYPE_DATA: + if (pRxD->U2M) + { + Update_Rssi_Sample(pAd, &pAd->ApCfg.RssiSample, pRxWI); + pAd->ApCfg.NumOfAvgRssiSample ++; +#ifdef DBG_DIAGNOSE + if (pRxWI->MCS < 24) /* 3*3 */ + { + pAd->DiagStruct.RxDataCnt[pAd->DiagStruct.ArrayCurIdx]++; + pAd->DiagStruct.RxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pRxWI->MCS]++; + } +#endif /* DBG_DIAGNOSE */ + } + APHandleRxDataFrame(pAd, &RxCell); + break; + + case BTYPE_MGMT: + APHandleRxMgmtFrame(pAd, &RxCell); + break; + + case BTYPE_CNTL: + APHandleRxControlFrame(pAd, &RxCell); + break; + + default: + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + break; + } + } + +#ifdef UAPSD_SUPPORT + /* dont remove the function or UAPSD will fail */ + UAPSD_MR_SP_RESUME(pAd); + UAPSD_SP_CloseInRVDone(pAd); +#endif /* UAPSD_SUPPORT */ + + return bReschedule; +} + + +#define AP_MAX_RX_PROCESS_CNT (32) +BOOLEAN APHandleRxDonePacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pRxPacket, + IN RX_BLK *pRxCell) +{ + RT28XX_RXD_STRUC *pRxD; + PRXWI_STRUC pRxWI; + PHEADER_802_11 pHeader; + MULTISSID_STRUCT *pMbss; +#ifdef WDS_SUPPORT + MAC_TABLE_ENTRY *pEntry = NULL; +#endif /* WDS_SUPPORT */ + BOOLEAN bReschedule = FALSE; + + + SET_OPMODE_AP(pRxCell); + /*pRxCell->OpMode = OPMODE_AP;*/ + /* get rx ring descriptor */ + pRxD = &(pRxCell->RxD); + pHeader = pRxCell->pHeader; + pRxWI = pRxCell->pRxWI; + +#ifdef WDS_SUPPORT + if ((pHeader->FC.FrDs == 1) && (pHeader->FC.ToDs == 1)) + { + if (MAC_ADDR_EQUAL(pHeader->Addr1, pAd->CurrentAddress)) + pEntry = FindWdsEntry(pAd, pRxWI->WirelessCliID, pHeader->Addr2, pRxWI->PHYMODE); + +#ifdef STATS_COUNT_SUPPORT + if(pEntry) + { + pAd->WdsTab.WdsEntry[pEntry->MatchWDSTabIdx].WdsCounter.ReceivedByteCount += pRxWI->MPDUtotalByteCount; + INC_COUNTER64(pAd->WdsTab.WdsEntry[pEntry->MatchWDSTabIdx].WdsCounter.ReceivedFragmentCount); + + if(IS_MULTICAST_MAC_ADDR(pHeader->Addr3)) + INC_COUNTER64(pAd->WdsTab.WdsEntry[pEntry->MatchWDSTabIdx].WdsCounter.MulticastReceivedFrameCount); + } +#endif /* STATS_COUNT_SUPPORT */ + } +#endif /* WDS_SUPPORT */ + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + pAd->ate.RxCntPerSec++; + ATESampleRssi(pAd, pRxWI); +#ifdef RALINK_QA + if (pAd->ate.bQARxStart == TRUE) + { + /* GetPacketFromRxRing() has copy the endian-changed RxD if it is necessary. */ + ATE_QA_Statistics(pAd, pRxWI, pRxD, pHeader); + } + +#ifdef TXBF_SUPPORT + /* Check sounding frame */ + if ((pAd->chipCap.FlgHwTxBfCap) && (pHeader->FC.Type == BTYPE_MGMT)) + { + RX_BLK *pRxBlk = pRxCell; + + 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 */ + /*printk("Receive sounding response\n"); */ + 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; i < pRxBlk->DataSize && i < MAX_SOUNDING_RESPONSE_SIZE; i++) + pAd->ate.soundingResp[i] = pRxBlk->pData[i]; + } + } + 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])); + } + } +#endif /* TXBF_SUPPORT */ +#endif /* RALINK_QA */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); + return bReschedule; + } +#endif /* RALINK_ATE */ + + /* Check for all RxD errors */ + if (APCheckRxError(pAd, pRxD, pRxWI->WirelessCliID) != NDIS_STATUS_SUCCESS) + { + APRxDErrorHandle(pAd, pRxCell); + + /* Increase received error packet counter per BSS */ + if ((pHeader->FC.FrDs == 0) && + pRxD->U2M && + (pRxWI->BSSID < pAd->ApCfg.BssidNum)) + { + pMbss = &pAd->ApCfg.MBSSID[pRxWI->BSSID]; + pMbss->RxDropCount ++; + pMbss->RxErrorCount ++; + } + +#ifdef WDS_SUPPORT +#ifdef STATS_COUNT_SUPPORT + if ((pHeader->FC.FrDs == 1) && (pHeader->FC.ToDs == 1)) + { + if (MAC_ADDR_EQUAL(pHeader->Addr1, pAd->CurrentAddress)) + pEntry = FindWdsEntry(pAd, pRxWI->WirelessCliID, pHeader->Addr2, pRxWI->PHYMODE); + if(pEntry) + pAd->WdsTab.WdsEntry[pEntry->MatchWDSTabIdx].WdsCounter.RxErrors++; + } +#endif /* STATS_COUNT_SUPPORT */ +#endif /* WDS_SUPPORT */ + + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return bReschedule; + } + + /* + All frames to AP are directed except probe_req. IEEE 802.11/1999 - p.463 + Do this before checking "duplicate frame". + 2003-08-20 accept BEACON to decide if OLBC (Overlapping Legacy BSS Condition) happens + TODO: consider move this code to be inside "APCheckRxError()" + */ + switch (pHeader->FC.Type) + { + case BTYPE_DATA: + if (pRxD->U2M) + { + Update_Rssi_Sample(pAd, &pAd->ApCfg.RssiSample, pRxWI); + pAd->ApCfg.NumOfAvgRssiSample++; +#ifdef DBG_DIAGNOSE + if (pRxWI->MCS < 24) + { + pAd->DiagStruct.RxDataCnt[pAd->DiagStruct.ArrayCurIdx]++; + pAd->DiagStruct.RxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pRxWI->MCS]++; + } +#endif /* DBG_DIAGNOSE */ + } + APHandleRxDataFrame(pAd, pRxCell); + break; + + case BTYPE_MGMT: + APHandleRxMgmtFrame(pAd, pRxCell); + break; + + case BTYPE_CNTL: + APHandleRxControlFrame(pAd, pRxCell); + break; + + default: + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + break; + } + + return bReschedule; +} + + +BOOLEAN APFowardWirelessStaToWirelessSta( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN ULONG FromWhichBSSID) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + BOOLEAN bAnnounce, bDirectForward; + UCHAR *pHeader802_3; + PNDIS_PACKET pForwardPacket; +#ifdef MESH_SUPPORT + BOOLEAN bMeshPacket = FALSE; + PNDIS_PACKET pMeshForwardPacket = NULL; +#endif /* MESH_SUPPORT */ + +#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 P2P_SUPPORT + if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_P2P_GO) + { + FromWhichBSSID = FromWhichBSSID - MIN_NET_DEVICE_FOR_P2P_GO; + } + else +#endif /* P2P_SUPPORT */ +#ifdef MESH_SUPPORT + if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_MESH) + { + bMeshPacket = TRUE; + } + else +#endif /* MESH_SUPPORT */ +#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); + +#ifdef MESH_SUPPORT + if (bMeshPacket) + { + MeshDataPktProcess(pAd, pPacket, (FromWhichBSSID - MIN_NET_DEVICE_FOR_MESH), + &pMeshForwardPacket, &bDirectForward, &bAnnounce); + } + else +#endif /* MESH_SUPPORT */ + 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 ( +#ifdef P2P_SUPPORT + (pAd->P2pCfg.bSigmaEnabled == TRUE) || +#endif /* P2P_SUPPORT */ + ((FromWhichBSSID < MAX_MBSSID_NUM(pAd)) && + (FromWhichBSSID < HW_BEACON_MAX_NUM) && + (pAd->ApCfg.MBSSID[FromWhichBSSID].StaCount > 1))) + 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; + bAnnounce = FALSE; + + if (FromWhichBSSID == pEntry->apidx) + {/* STAs in same SSID */ + if ((pAd->ApCfg.MBSSID[pEntry->apidx].IsolateInterStaTraffic == 1)) + { + /* release the packet */ + bDirectForward = FALSE; + bAnnounce = FALSE; + } + } + else + {/* STAs in different SSID */ + if (pAd->ApCfg.IsolateInterStaTrafficBTNBSSID == 1 || + ((FromWhichBSSID < MAX_MBSSID_NUM(pAd)) && + (FromWhichBSSID < HW_BEACON_MAX_NUM) && + (pAd->ApCfg.MBSSID[pEntry->apidx].VLAN_VID != pAd->ApCfg.MBSSID[FromWhichBSSID].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 to do + bridge. + */ + bDirectForward = FALSE; + bAnnounce = FALSE; + } + } + } + else + { + /* announce this packet to upper layer (bridge) */ + bDirectForward = FALSE; + bAnnounce = TRUE; + } + } + + if (bDirectForward) + { + /* build an NDIS packet */ +#ifdef MESH_SUPPORT + if ((bMeshPacket == TRUE) && (bDirectForward == TRUE) && (bAnnounce == TRUE)) + pForwardPacket = pMeshForwardPacket; + else +#endif /* MESH_SUPPORT */ + pForwardPacket = RTMP_DUPLICATE_PACKET(pAd, pPacket, FromWhichBSSID); + + if (pForwardPacket == NULL) + { + return bAnnounce; + } + +#ifdef MESH_SUPPORT + if (bMeshPacket) + { + LONG RouteId = PathRouteIDSearch(pAd, pHeader802_3); + + if (RouteId == BMCAST_ROUTE_ID) + { + MeshClonePacket(pAd, pForwardPacket, MESH_FORWARD, (FromWhichBSSID - MIN_NET_DEVICE_FOR_MESH)); + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pForwardPacket, NDIS_STATUS_SUCCESS); + } + else if (RouteId >= 0) + { + INT LinkId; + + LinkId = PathMeshLinkIDSearch(pAd, RouteId); + if ((LinkId >= 0) && VALID_MESH_LINK_ID(LinkId)) + { + RTMP_SET_PACKET_NET_DEVICE_MESH(pForwardPacket, 0); + RTMP_SET_PACKET_SOURCE(pForwardPacket, PKTSRC_NDIS); + RTMP_SET_PACKET_MOREDATA(pForwardPacket, FALSE); + RTMP_SET_PACKET_WCID(pForwardPacket, + pAd->MeshTab.MeshLink[LinkId].Entry.MacTabMatchWCID); + RTMP_SET_MESH_ROUTE_ID(pForwardPacket, RouteId); + RTMP_SET_MESH_SOURCE(pForwardPacket, MESH_FORWARD); + APSendPacket(pAd, pForwardPacket); + } + else + { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pForwardPacket, NDIS_STATUS_FAILURE); + } + } + else + { + /* entity is not exist. */ + /* start path discovery. */ + MeshCreatePreqAction(pAd, NULL, pHeader802_3); + + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pForwardPacket, NDIS_STATUS_FAILURE); + } + } + else +#endif /* MESH_SUPPORT */ + { + /* 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); + + /* send bc/mc frame back to the same bss */ + if (!pEntry) + RTMP_SET_PACKET_NET_DEVICE_MBSSID(pForwardPacket, FromWhichBSSID); + + RTMP_SET_PACKET_WCID(pForwardPacket, pEntry ? pEntry->Aid : MCAST_WCID); + RTMP_SET_PACKET_SOURCE(pForwardPacket, PKTSRC_NDIS); + RTMP_SET_PACKET_MOREDATA(pForwardPacket, FALSE); +#ifdef P2P_SUPPORT + RTMP_SET_PACKET_OPMODE(pForwardPacket, OPMODE_AP); +#endif /* P2P_SUPPORT */ +#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 */ + + APSendPacket(pAd, pForwardPacket); + } + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); /* Dequeue outgoing frames from TxSwQueue0..3 queue and process it */ + } + + 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) +{ + UCHAR NullFrame[48]; + ULONG Length; + PHEADER_802_11 pHeader_802_11; + PAPCLI_STRUCT pApCliEntry = NULL; + + pApCliEntry = &pAd->ApCfg.ApCliTab[pMacEntry->MatchAPCLITabIdx]; + + /* WPA 802.1x secured port control */ + if (((pApCliEntry->AuthMode == Ndis802_11AuthModeWPA) || + (pApCliEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || + (pApCliEntry->AuthMode == Ndis802_11AuthModeWPA2) || + (pApCliEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + || (pApCliEntry->IEEE8021X == TRUE) +#endif /*APCLI_WPA_SUPPLICANT_SUPPORT*/ +#ifdef WAPI_SUPPORT + || (pApCliEntry->AuthMode == Ndis802_11AuthModeWAICERT) + || (pApCliEntry->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 = BTYPE_DATA; + pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC; + pHeader_802_11->FC.ToDs = 1; +/* + printk("pHeader_802_11->Addr1 = %02x:%02x:%02x:%02x:%02x:%02x\n",PRINT_MAC(pMacEntry->Addr)); + printk("pHeader_802_11->Addr2 = %02x:%02x:%02x:%02x:%02x:%02x\n",PRINT_MAC(pApCliEntry->CurrentAddress)); + printk("pHeader_802_11->Addr3 = %02x:%02x:%02x:%02x:%02x:%02x\n",PRINT_MAC(pMacEntry->Addr)); +*/ + 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->CurrentAddress); + 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 = 0; + } + 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/mt7620/src/ap/ap_dls.c b/mt7620/src/ap/ap_dls.c new file mode 100644 index 0000000..fb5ab9a --- /dev/null +++ b/mt7620/src/ap/ap_dls.c @@ -0,0 +1,348 @@ +/**************************************************************************** + * 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; + + /* + 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].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, +#ifdef P2P_SUPPORT + pAd->ApCfg.MBSSID[pSAEntry->apidx].Bssid, +#endif /* P2P_SUPPORT */ + pAd->ApCfg.MBSSID[pSAEntry->apidx].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].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].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/mt7620/src/ap/ap_ids.c b/mt7620/src/ap/ap_ids.c new file mode 100644 index 0000000..8706da3 --- /dev/null +++ b/mt7620/src/ap/ap_ids.c @@ -0,0 +1,455 @@ +/**************************************************************************** + * 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; + + 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 PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHeader, + IN CHAR Rssi0, + IN CHAR Rssi1, + IN CHAR Rssi2) +{ + INT i; + + for (i = 0; i < pAd->ApCfg.BssidNum; i++) + { + /* Spoofed BSSID detection */ + if (NdisEqualMemory(pHeader->Addr2, pAd->ApCfg.MBSSID[i].Bssid, MAC_ADDR_LEN)) + { + CHAR RcvdRssi; + + RcvdRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Rssi0, RSSI_0), ConvertToRssi(pAd, Rssi1, RSSI_1), ConvertToRssi(pAd, Rssi2, 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; + + 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 PRTMP_ADAPTER pAd, + IN PUCHAR pAddr2, + IN CHAR Rssi0, + IN CHAR Rssi1, + IN CHAR Rssi2) +{ + INT i; + + for (i = 0; i < pAd->ApCfg.BssidNum; i++) + { + /* Conflict SSID detection */ + if (NdisEqualMemory(pAddr2, pAd->ApCfg.MBSSID[i].Bssid, MAC_ADDR_LEN)) + { + CHAR RcvdRssi; + + RcvdRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Rssi0, RSSI_0), ConvertToRssi(pAd, Rssi1, RSSI_1), ConvertToRssi(pAd, Rssi2, 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)); + } +} + +#endif /* IDS_SUPPORT */ diff --git a/mt7620/src/ap/ap_mbss.c b/mt7620/src/ap/ap_mbss.c new file mode 100644 index 0000000..a75eebb --- /dev/null +++ b/mt7620/src/ap/ap_mbss.c @@ -0,0 +1,379 @@ +/**************************************************************************** + * 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 + MBSS_VirtualIF_PacketSend() 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 + +#define MODULE_MBSS +#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( + IN PRTMP_ADAPTER pAd, + IN RTMP_OS_NETDEV_OP_HOOK *pNetDevOps) +{ +#define MBSS_MAX_DEV_NUM 32 + PNET_DEV pDevNew; + INT32 IdBss, MaxNumBss; + INT status; + RTMP_OS_NETDEV_OP_HOOK netDevHook; + + /* sanity check to avoid redundant virtual interfaces are created */ + if (pAd->FlgMbssInit != FALSE) + return; + /* End of if */ + + + /* init */ + MaxNumBss = pAd->ApCfg.BssidNum; + if (MaxNumBss > MAX_MBSSID_NUM(pAd)) + MaxNumBss = MAX_MBSSID_NUM(pAd); + /* End of if */ + + + /* first IdBss must not be 0 (BSS0), must be 1 (BSS1) */ + for(IdBss=FIRST_MBSSID; IdBssApCfg.MBSSID[IdBss].MSSIDDev = NULL; + /* End of for */ + + /* create virtual network interface */ + for(IdBss=FIRST_MBSSID; IdBssMC_RowID; +#endif /* MULTIPLE_CARD_SUPPORT */ +#ifdef HOSTAPD_SUPPORT + IoctlIF = pAd->IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + pDevNew = RtmpOSNetDevCreate(MC_RowID, &IoctlIF, INT_MBSSID, IdBss, sizeof(PRTMP_ADAPTER), INF_MBSSID_DEV_NAME); +#ifdef HOSTAPD_SUPPORT + pAd->IoctlIF = IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + if (pDevNew == NULL) + { + /* allocation fail, exit */ + pAd->ApCfg.BssidNum = IdBss; /* re-assign new MBSS number */ + DBGPRINT(RT_DEBUG_ERROR, + ("Allocate network device fail (MBSS)...\n")); + break; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Register MBSSID IF (%s)\n", RTMP_OS_NETDEV_GET_DEVNAME(pDevNew))); + } + + RTMP_OS_NETDEV_SET_PRIV(pDevNew, pAd); + + /* init operation functions and flags */ + NdisCopyMemory(&netDevHook, pNetDevOps, sizeof(netDevHook)); + + netDevHook.priv_flags = INT_MBSSID; /* We are virtual interface */ + netDevHook.needProtcted = TRUE; + + /* Init MAC address of virtual network interface */ + NdisMoveMemory(&netDevHook.devAddr[0], &pAd->ApCfg.MBSSID[IdBss].Bssid[0], MAC_ADDR_LEN); + + /* backup our virtual network interface */ + pAd->ApCfg.MBSSID[IdBss].MSSIDDev = pDevNew; + + /* register this device to OS */ + status = RtmpOSNetDevAttach(pAd->OpMode, pDevNew, &netDevHook); + + } + + 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( + IN PRTMP_ADAPTER pAd) +{ + MULTISSID_STRUCT *pMbss; + UINT IdBss; + + + + for(IdBss=FIRST_MBSSID; IdBssApCfg.MBSSID[IdBss]; + + if (pMbss->MSSIDDev) + { + RtmpOSNetDevDetach(pMbss->MSSIDDev); + RtmpOSNetDevFree(pMbss->MSSIDDev); + + /* clear it as NULL to prevent latter access error */ + pMbss->MSSIDDev = NULL; + } + } +} /* End of RT28xx_MBSS_Remove */ + + +/* +======================================================================== +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( + IN PRTMP_ADAPTER pAd, + IN PNET_DEV pDev) +{ + INT32 BssId = -1; + INT32 IdBss; + + + for(IdBss=0; IdBssApCfg.BssidNum; IdBss++) + { + if (pAd->ApCfg.MBSSID[IdBss].MSSIDDev == 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( + IN 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; + + pAd->ApCfg.MBSSID[BssId].bBcnSntReq = TRUE; + return 0; +} /* End of MBSS_Open */ + + +/* +======================================================================== +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( + IN 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); + +#ifdef MESH_SUPPORT + MeshMakeBeacon(pAd, MESH_BEACON_IDX(pAd)); + MeshUpdateBeaconFrame(pAd, MESH_BEACON_IDX(pAd)); +#endif /* MESH_SUPPORT */ + return 0; +} /* End of MBSS_Close */ + + +/* +======================================================================== +Routine Description: + Send a packet to WLAN. + +Arguments: + pPktSrc points to our adapter + pDev which WLAN network interface + +Return Value: + 0: transmit successfully + otherwise: transmit fail + +Note: +======================================================================== +*/ +int MBSS_PacketSend( + IN PNDIS_PACKET pPktSrc, + IN PNET_DEV pDev, + IN RTMP_NET_PACKET_TRANSMIT Func) +{ + RTMP_ADAPTER *pAd; + MULTISSID_STRUCT *pMbss; + PNDIS_PACKET pPkt = (PNDIS_PACKET)pPktSrc; + INT IdBss; + + + pAd = RTMP_OS_NETDEV_GET_PRIV(pDev); + ASSERT(pAd); + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + RELEASE_NDIS_PACKET(pAd, pPkt, NDIS_STATUS_FAILURE); + return 0; + } /* End of if */ +#endif /* RALINK_ATE */ + + if ((RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))) + { + /* wlan is scanning/disabled/reset */ + RELEASE_NDIS_PACKET(pAd, pPkt, NDIS_STATUS_FAILURE); + return 0; + } /* End of if */ + + + /* 0 is main BSS, dont handle it here */ + /* FIRST_MBSSID = 1 */ + pMbss = pAd->ApCfg.MBSSID; + + for(IdBss=FIRST_MBSSID; IdBssApCfg.BssidNum; IdBss++) + { + /* find the device in our MBSS list */ + if (pMbss[IdBss].MSSIDDev == pDev) + { +/* NdisZeroMemory((PUCHAR)&(RTPKT_TO_OSPKT(pPktSrc))->cb[CB_OFF], 15); */ + NdisZeroMemory((PUCHAR)(GET_OS_PKT_CB(pPktSrc) + CB_OFF), 15); + RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPktSrc, IdBss); +/* SET_OS_PKT_NETDEV(pPktSrc, pDev); */ + + + /* transmit the packet */ + return Func(pPktSrc); + } + } + + /* can not find the BSS so discard the packet */ + RELEASE_NDIS_PACKET(pAd, pPkt, NDIS_STATUS_FAILURE); + + return 0; +} /* End of MBSS_PacketSend */ + + +#endif /* MBSS_SUPPORT */ + +/* End of ap_mbss.c */ diff --git a/mt7620/src/ap/ap_mbss_inf.c b/mt7620/src/ap/ap_mbss_inf.c new file mode 100644 index 0000000..756d19d --- /dev/null +++ b/mt7620/src/ap/ap_mbss_inf.c @@ -0,0 +1,276 @@ +/**************************************************************************** + * 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 + MBSS_VirtualIF_PacketSend() 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 + +#define MODULE_MBSS +/*#include "rt_config.h" */ +#include "rtmp_comm.h" +#include "rt_os_util.h" +#include "rt_os_net.h" + + +/* --------------------------------- Public -------------------------------- */ +NET_DEV_STATS *RT28xx_get_ether_stats( + IN PNET_DEV net_dev); + +/* +======================================================================== +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( + IN VOID *pAd, + IN 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 = MBSS_VirtualIF_PacketSend; /* hard transmit hook point */ + netDevHook.ioctl = MBSS_VirtualIF_Ioctl; /* ioctl hook point */ + netDevHook.get_stats = RT28xx_get_ether_stats; + + 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( + IN VOID *pAd) +{ + + RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_MBSS_REMOVE, 0, NULL, 0); + +} /* End of RT28xx_MBSS_Remove */ + + + +/* --------------------------------- 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( + IN 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; +} /* End of MBSS_VirtualIF_Open */ + + +/* +======================================================================== +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( + IN 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; +} /* End of MBSS_VirtualIF_Close */ + + +/* +======================================================================== +Routine Description: + Send a packet to WLAN. + +Arguments: + pPktSrc points to our adapter + pDev which WLAN network interface + +Return Value: + 0: transmit successfully + otherwise: transmit fail + +Note: +======================================================================== +*/ +INT MBSS_VirtualIF_PacketSend( + IN PNDIS_PACKET pPktSrc, + IN PNET_DEV pDev) +{ + + MEM_DBG_PKT_ALLOC_INC(pPktSrc); + + if(!(RTMP_OS_NETDEV_STATE_RUNNING(pDev))) + { + /* the interface is down */ + RELEASE_NDIS_PACKET(NULL, pPktSrc, NDIS_STATUS_FAILURE); + return 0; + } /* End of if */ + + return MBSS_PacketSend(pPktSrc, pDev, rt28xx_packet_xmit); +} /* End of MBSS_VirtualIF_PacketSend */ + + +/* +======================================================================== +Routine Description: + IOCTL to WLAN. + +Arguments: + pDev which WLAN network interface + pIoCtrl command information + Command command ID + +Return Value: + 0: IOCTL successfully + otherwise: IOCTL fail + +Note: + SIOCETHTOOL 8946 New drivers use this ETHTOOL interface to + report link failure activity. +======================================================================== +*/ +INT MBSS_VirtualIF_Ioctl( + IN PNET_DEV pDev, + IN OUT VOID *pIoCtrl, + IN INT Command) +{ + VOID *pAd; + + pAd = RTMP_OS_NETDEV_GET_PRIV(pDev); + ASSERT(pAd); + + if (!pAd) + return -EINVAL; + +/* if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) */ + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + return -ENETDOWN; + /* End of if */ + + /* do real IOCTL */ + return rt28xx_ioctl(pDev, pIoCtrl, Command); +} /* End of MBSS_VirtualIF_Ioctl */ + +#endif /* MBSS_SUPPORT */ + +/* End of ap_mbss_inf.c */ diff --git a/mt7620/src/ap/ap_mlme.c b/mt7620/src/ap/ap_mlme.c new file mode 100644 index 0000000..70067a8 --- /dev/null +++ b/mt7620/src/ap/ap_mlme.c @@ -0,0 +1,821 @@ +/**************************************************************************** + * 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 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 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 + { + printk("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 */ + + /* BBP TUNING: dynamic tune BBP R66 to find a balance between sensibility + and noise isolation */ +/* AsicBbpTuning2(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); + RTMPMaintainPMKIDCache(pAd); + +#ifdef WDS_SUPPORT + WdsTableMaintenance(pAd); +#endif /* WDS_SUPPORT */ + +#ifdef MESH_SUPPORT + if(MESH_ON(pAd)) + { + LONG idx; + /* period update Neighbor table. */ + NeighborTableUpdate(pAd); + /* update Mesh Link */ + MeshLinkTableMaintenace(pAd); + /* update Mesh multipath entry. */ + for (idx = 0; idx < MAX_MESH_LINKS; idx ++) + { + if (PeerLinkValidCheck(pAd, idx)) + MultipathEntryMaintain(pAd, idx); + } + } +#endif /* MESH_SUPPORT */ + +#ifdef CLIENT_WDS + CliWds_ProxyTabMaintain(pAd); +#endif /* CLIENT_WDS */ + } + +#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; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; +#ifdef APCLI_CERT_SUPPORT + BOOLEAN IsUseBA = TRUE; +#endif /* APCLI_CERT_SUPPORT */ +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + { + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; + RTMPRepeaterReconnectionCheck(pAd); + } +#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 < MaxWcidNum)) + { + /* 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]; + if (pEntry->RXBAbitmap == 0 && pEntry->TXBAbitmap == 0) + IsUseBA = FALSE; + + if((IS_RT5392(pAd) || IS_RT5592(pAd)) && + pApCliEntry->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); + printk("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); + printk("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 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); +#ifdef APCLI_SUPPORT +#ifdef APCLI_CERT_SUPPORT +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + /* Before scan, reset trigger event table. */ + TriEventInit(pAd); +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ +#endif /* APCLI_CERT_SUPPORT */ +#endif /*APCLI_SUPPORT */ + + 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 */ + + /* resume Improved Scanning*/ + if ((pAd->ApCfg.bImprovedScan) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) && + (pAd->Mlme.ApSyncMachine.CurrState == AP_SCAN_PENDING)) + { + MLME_SCAN_REQ_STRUCT ScanReq; + + AsicDisableSync(pAd); + + RTMPZeroMemory(ScanReq.Ssid, MAX_LEN_OF_SSID); + ScanReq.SsidLen = pAd->MlmeAux.SsidLen; + NdisMoveMemory(ScanReq.Ssid, pAd->MlmeAux.Ssid, ScanReq.SsidLen); + + ScanReq.BssType = BSS_ANY; + ScanReq.ScanType = SCAN_ACTIVE; + MlmeEnqueue(pAd, AP_SYNC_STATE_MACHINE, APMT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0); + RTMP_MLME_HANDLER(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("bImprovedScan ............. Resume for bImprovedScan, SCAN_PENDING .............. \n")); + } + +} + + +/*! \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 == BTYPE_DATA) + { +#ifdef WSC_AP_SUPPORT + /*WSC EAPOL PACKET */ + pEntry = MacTableLookup(pAd, pFrame->Hdr.Addr2); + if (pEntry && + ((pEntry->bWscCapable) || + (pAd->ApCfg.MBSSID[pEntry->apidx].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. + */ + if ((MAC_ADDR_EQUAL(pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EntryAddr, pEntry->Addr) || + MAC_ADDR_EQUAL(pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EntryAddr, ZERO_MAC_ADDR)) && + IS_ENTRY_CLIENT(pEntry) && + (pAd->ApCfg.MBSSID[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); + } + } +#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 != BTYPE_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; +/* test for 40Mhz intolerant */ + /* + 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 */ +#ifdef P2P_SUPPORT + /* Vendor specific usage. */ + if ((pFrame->Octet[0] & 0x7F) == MT2_ACT_VENDOR) /* Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support */ + { + UCHAR P2POUIBYTE[4] = {0x50, 0x6f, 0x9a, 0x9}; + + DBGPRINT(RT_DEBUG_ERROR, ("Vendor Action frame OUI= 0x%x\n", *(PULONG)&pFrame->Octet[1])); + /* Now support WFA P2P */ + if (RTMPEqualMemory(&pFrame->Octet[1], P2POUIBYTE, 4) && (P2P_INF_ON(pAd))) + { + DBGPRINT(RT_DEBUG_TRACE, ("Vendor Action frame P2P OUI= 0x%x\n", *(PULONG)&pFrame->Octet[1])); + *Machine = P2P_ACTION_STATE_MACHINE; + if (pFrame->Octet[5] <= MT2_MAX_PEER_SUPPORT) + { + *MsgType = pFrame->Octet[5]; /* subtype. */ + } + else + return FALSE; + } + else + { + return FALSE; + } + } + else +#endif /* P2P_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) +{ + UCHAR BBPR3 = 0; + 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 TXBF_SUPPORT + /* TODO: we didn't do RxAnt evaluate for 3x3 chips */ + if (IS_RT3883(pAd) || IS_RT2883(pAd)) + return; +#endif /* TXBF_SUPPORT */ + + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); + BBPR3 &= (~0x18); + if((pAd->Antenna.field.RxPath == 3) +#ifdef DOT11_N_SUPPORT +#ifdef GREENAP_SUPPORT + && (pAd->ApCfg.bGreenAPActive == FALSE) +#endif /* GREENAP_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + ) + { + BBPR3 |= (0x10); + } + else if((pAd->Antenna.field.RxPath == 2) +#ifdef DOT11_N_SUPPORT +#ifdef GREENAP_SUPPORT + && (pAd->ApCfg.bGreenAPActive == FALSE) +#endif /* GREENAP_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + ) + { + BBPR3 |= (0x8); + } + else if(pAd->Antenna.field.RxPath == 1) + { + BBPR3 |= (0x0); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); + + 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( + PRTMP_ADAPTER pAd) +{ + UCHAR BBPR3 = 0; + CHAR larger = -127, 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; + } + + if(pAd->Antenna.field.RxPath == 3) + { + larger = max(rssi0, rssi1); +#ifdef DOT11N_SS3_SUPPORT + if (pAd->CommonCfg.RxStream >= 3) + pAd->Mlme.RealRxPath = 3; + else +#endif /* DOT11N_SS3_SUPPORT */ + { + if (larger > (rssi2 + 20)) + pAd->Mlme.RealRxPath = 2; + else + pAd->Mlme.RealRxPath = 3; + } + } + /* Disable the below to fix 1T/2R issue. It's suggested by Rory at 2007/7/11. */ + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); + BBPR3 &= (~0x18); + if((pAd->Mlme.RealRxPath == 3) +#ifdef DOT11_N_SUPPORT +#ifdef GREENAP_SUPPORT + && (pAd->ApCfg.bGreenAPActive == FALSE) +#endif /* GREENAP_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + ) + { + BBPR3 |= (0x10); + } + else if((pAd->Mlme.RealRxPath == 2) +#ifdef DOT11_N_SUPPORT +#ifdef GREENAP_SUPPORT + && (pAd->ApCfg.bGreenAPActive == FALSE) +#endif /* GREENAP_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + ) + { + BBPR3 |= (0x8); + } + else if(pAd->Mlme.RealRxPath == 1) + { + BBPR3 |= (0x0); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); + +} + +/* + ======================================================================== + 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; +} + + + +/* End of ap_mlme.c */ diff --git a/mt7620/src/ap/ap_nintendo.c b/mt7620/src/ap/ap_nintendo.c new file mode 100644 index 0000000..fcd7c34 --- /dev/null +++ b/mt7620/src/ap/ap_nintendo.c @@ -0,0 +1,450 @@ +/* + *************************************************************************** + * 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_nintendo.c + + Abstract: + Miniport Query information related subroutines + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + JuemingChen 12-28-2006 created + +*/ +#include "rt_config.h" + +#ifdef NINTENDO_AP + +#define CAPABILITY_PRIVACY 0x0010 + +/*static RT_NINTENDO_TABLE DS_TABLE; */ + +#ifdef CHIP25XX +/* +static spinlock_t NINTENDO_TABLE_Lock; +static spinlock_t NINTENDO_TABLE_Lock; +*/ +#define TEMP_SEM_LOCK(__lock, __irqflag) spin_lock_bh(__lock) +#define TEMP_SEM_UNLOCK(__lock, __irqflag) spin_unlock_bh(__lock) +#else /*CHIP25XX */ +/*static NDIS_SPIN_LOCK NINTENDO_TABLE_Lock; //os_lock */ +#define TEMP_SEM_LOCK(__lock, __irqflag) RTMP_SEM_LOCK(__lock) +#define TEMP_SEM_UNLOCK(__lock, __irqflag) RTMP_SEM_UNLOCK(__lock) +#endif /*CHIP25XX */ + +/* +static UCHAR NINTENDO_UP_BUFFER[512]; +static UCHAR Local_KeyIdx = 0; +static CIPHER_KEY Local_SharedKey; +static UCHAR Local_bHideSsid; +static UCHAR Local_AuthMode; +static UCHAR Local_WepStatus; +static USHORT Local_CapabilityInfo; +*/ + +#define NINTO_INFO pAd->nindo_ctrl_block + +static int MakeUsbWepKey(const unsigned char wepseed[20], unsigned char wepkey[13]) +{ + int i=0; + const char* MASKkey0 = "gwi'6&fs=0Nf~"; + const char* MASKkey1 = "%(egEr)ag(s&m"; + const unsigned char wepkeylength = 13; + const unsigned char ttable[16] = {10,13,14,8,9,3,6,0,12,5,2,7,11,1,15,4 }; + const unsigned char ctable[13] = {5,1,12,4,2,3,10,0,11,7,9,8,6 }; + unsigned char keytemp[wepkeylength]; + + for( i =0; i < wepkeylength; i ++ ){ + wepkey[i] = wepseed[i] ^ wepseed[wepkeylength + i % 7]; + } + for( i =0; i < 7; i ++ ){ + wepkey[3 + i]=wepkey[3 + i]^ wepseed[wepkeylength + i]; + } + + for( i =0; i < wepkeylength; i ++ ){ + wepkey[i] = wepkey[i] ^ MASKkey0[i]; + } + + memcpy(keytemp, wepkey, wepkeylength); + for( i =0; i < wepkeylength; i ++ ){ + wepkey[ctable[i]] = keytemp[i]; + } + + for ( i =0; i < wepkeylength; i ++ ){ + wepkey[i] = wepkey[i] ^ MASKkey1[i]; + } + + for( i =0; i < wepkeylength; i ++ ){ + wepkey[i] = ttable[(wepkey[i] >> 4) & 0x0F] <<4 | ttable[wepkey[i] & 0x0F]; + } + + for( i =0; i < 3; i ++ ){ + wepkey[i] = wepkey[i] ^ wepkey[i + 6]; + wepkey[i + 3]=wepkey[i + 3]^ wepkey[i + 9]; + wepkey[i + 6]=wepkey[i + 6]^ wepkey[i + 3]; + wepkey[i + 9]=wepkey[i + 9]^ wepkey[i]; + wepkey[12] =wepkey[12] ^ wepkey[i]; + } + return 0; +} + +static VOID NintendoEnable( + IN PRTMP_ADAPTER pAd) +{ + NINTO_INFO.Local_KeyIdx = pAd->ApCfg.MBSSID[BSS0].DefaultKeyId; + + if(0 == pAd->bNintendoCapable) + { + NINTO_INFO.Local_bHideSsid = pAd->ApCfg.MBSSID[BSS0].bHideSsid; + NINTO_INFO.Local_AuthMode = pAd->ApCfg.MBSSID[BSS0].AuthMode; + NINTO_INFO.Local_WepStatus = pAd->ApCfg.MBSSID[BSS0].WepStatus; + NINTO_INFO.Local_CapabilityInfo = pAd->ApCfg.MBSSID[BSS0].CapabilityInfo; + NdisMoveMemory(NINTO_INFO.Local_SharedKey.Key, pAd->SharedKey[BSS0][NINTO_INFO.Local_KeyIdx].Key, NINTENDO_WEPKEY_LN); + NINTO_INFO.Local_SharedKey.KeyLen = pAd->SharedKey[BSS0][NINTO_INFO.Local_KeyIdx].KeyLen; + NINTO_INFO.Local_SharedKey.CipherAlg = pAd->SharedKey[BSS0][NINTO_INFO.Local_KeyIdx].CipherAlg; + } + + pAd->ApCfg.MBSSID[BSS0].bHideSsid = 1; + pAd->ApCfg.MBSSID[BSS0].AuthMode = Ndis802_11AuthModeShared; + pAd->ApCfg.MBSSID[BSS0].WepStatus = Ndis802_11WEPEnabled; + pAd->ApCfg.MBSSID[BSS0].CapabilityInfo |= CAPABILITY_PRIVACY; +/* + pAd->ApCfg.MBSSID[BSS0].GroupKeyWepStatus = Ndis802_11WEPEnabled; + pAd->CommonCfg.GroupKeyWepStatus = Ndis802_11WEPEnabled; +*/ + NdisMoveMemory(pAd->SharedKey[BSS0][NINTO_INFO.Local_KeyIdx].Key, pAd->NINTENDO_WEP_KEY, NINTENDO_WEPKEY_LN); + pAd->SharedKey[BSS0][NINTO_INFO.Local_KeyIdx].KeyLen = (UCHAR) NINTENDO_WEPKEY_LN; + pAd->SharedKey[BSS0][NINTO_INFO.Local_KeyIdx].CipherAlg = CIPHER_WEP128; + pAd->bNintendoCapable = 1; +} + +static VOID NintendoDisable( + IN PRTMP_ADAPTER pAd) +{ + if(1 == pAd->bNintendoCapable) + { + UINT8 Wcid; + + pAd->ApCfg.MBSSID[BSS0].bHideSsid = NINTO_INFO.Local_bHideSsid; + pAd->ApCfg.MBSSID[BSS0].AuthMode = NINTO_INFO.Local_AuthMode; + pAd->ApCfg.MBSSID[BSS0].WepStatus = NINTO_INFO.Local_WepStatus; + pAd->ApCfg.MBSSID[BSS0].CapabilityInfo = NINTO_INFO.Local_CapabilityInfo; + NdisMoveMemory(pAd->SharedKey[BSS0][NINTO_INFO.Local_KeyIdx].Key, NINTO_INFO.Local_SharedKey.Key, NINTENDO_WEPKEY_LN); + pAd->SharedKey[BSS0][NINTO_INFO.Local_KeyIdx].KeyLen = (UCHAR) NINTO_INFO.Local_SharedKey.KeyLen; + pAd->SharedKey[BSS0][NINTO_INFO.Local_KeyIdx].CipherAlg = NINTO_INFO.Local_SharedKey.CipherAlg; + + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); + APUpdateCapabilityAndErpIe(pAd); + RTMP_ASIC_SHARED_KEY_TABLE(pAd, + BSS0, + (UCHAR) NINTO_INFO.Local_KeyIdx, + &NINTO_INFO.Local_SharedKey); + + GET_GroupKey_WCID(pAd, Wcid, BSS0); + RTMPSetWcidSecurityInfo(pAd, BSS0, + NINTO_INFO.Local_KeyIdx, + NINTO_INFO.Local_SharedKey.CipherAlg, + Wcid, + SHAREDKEYTABLE); + } + pAd->bNintendoCapable = 0; +} + +extern VOID InitNINTENDO_TABLE( + IN PRTMP_ADAPTER pAd) +{ + memset(&NINTO_INFO.DS_TABLE, 0 , sizeof(NINTO_INFO.DS_TABLE)); + NdisAllocateSpinLock(pAd, &NINTO_INFO.NINTENDO_TABLE_Lock); + memcpy(pAd->NINTENDO_WEP_SEED, "zzzzzzzzzzzzzzzzzzzzzzzzzz", NINTENDO_SSID_NICKNAME_LN); + MakeUsbWepKey(pAd->NINTENDO_WEP_SEED, pAd->NINTENDO_WEP_KEY); + + pAd->bNintendoCapable = 0; + return; +} + +static UCHAR AddNINTENDO_ENTRY(PRTMP_ADAPTER pAd, PRT_NINTENDO_SSID ptmp, UCHAR * pDS_Addr) +{ + int loopi; + ULONG IrqFlags; + + TEMP_SEM_LOCK(&NINTO_INFO.NINTENDO_TABLE_Lock, IrqFlags) + for(loopi = 0; (loopi < NINTO_INFO.DS_TABLE.number) && (loopi < NINTENDO_MAX_ENTRY); loopi++) + { + if(!memcmp(pDS_Addr, NINTO_INFO.DS_TABLE.entry[loopi].DS_Addr, ETH_LENGTH_OF_ADDRESS)) + { + DBGPRINT(RT_DEBUG_TRACE, ("same MAC %02x%02x%02x%02x%02x%02x\n",pDS_Addr[0],pDS_Addr[1],pDS_Addr[2],pDS_Addr[3],pDS_Addr[4],pDS_Addr[5])); + break; + } + } + + if (loopi >= NINTO_INFO.DS_TABLE.number) + { + DBGPRINT(RT_DEBUG_TRACE, ("add MAC %02x%02x%02x%02x%02x%02x\n",pDS_Addr[0],pDS_Addr[1],pDS_Addr[2],pDS_Addr[3],pDS_Addr[4],pDS_Addr[5])); + memcpy(NINTO_INFO.DS_TABLE.entry[NINTO_INFO.DS_TABLE.number].NICKname, ptmp->NICKname, NINTENDO_SSID_NICKNAME_LN); + memcpy(NINTO_INFO.DS_TABLE.entry[NINTO_INFO.DS_TABLE.number].DS_Addr, pDS_Addr, ETH_LENGTH_OF_ADDRESS); + NINTO_INFO.DS_TABLE.number++; + } + TEMP_SEM_UNLOCK(&NINTO_INFO.NINTENDO_TABLE_Lock, IrqFlags); + IrqFlags = 0; + return 0; +} + +extern UCHAR DelNINTENDO_ENTRY(PRTMP_ADAPTER pAd, UCHAR * pDS_Addr) +{ + int loopi; + ULONG IrqFlags; + + TEMP_SEM_LOCK(&NINTO_INFO.NINTENDO_TABLE_Lock, IrqFlags) + for(loopi = 0; loopi < NINTO_INFO.DS_TABLE.number && loopi < NINTENDO_MAX_ENTRY; loopi++) + { + if(!memcmp(pDS_Addr, NINTO_INFO.DS_TABLE.entry[loopi].DS_Addr, ETH_LENGTH_OF_ADDRESS)) + { + DBGPRINT(RT_DEBUG_TRACE, ("DelNINTENDO_ENTRY loopi %d\n",loopi)); + if(loopi < (NINTO_INFO.DS_TABLE.number - 1) ) + { + memcpy(NINTO_INFO.DS_TABLE.entry[loopi].NICKname, NINTO_INFO.DS_TABLE.entry[NINTO_INFO.DS_TABLE.number].NICKname, NINTENDO_SSID_NICKNAME_LN); + memcpy(NINTO_INFO.DS_TABLE.entry[loopi].DS_Addr, NINTO_INFO.DS_TABLE.entry[NINTO_INFO.DS_TABLE.number].DS_Addr, ETH_LENGTH_OF_ADDRESS); + } + memset(&NINTO_INFO.DS_TABLE.entry[NINTO_INFO.DS_TABLE.number],0,sizeof(RT_NINTENDO_ENTRY)); + NINTO_INFO.DS_TABLE.number--; + break; + } + } + TEMP_SEM_UNLOCK(&NINTO_INFO.NINTENDO_TABLE_Lock, IrqFlags); + IrqFlags = 0; + return 0; +} + +extern VOID RTMPIoctlNintendoCapable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + if(1 == wrq->u.data.length) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlNintendoCapable No parameter\n")); + } + else if(2 == wrq->u.data.length) + { + UCHAR temp[2]; + INT Status; + + Status = copy_from_user(temp, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlNintendoCapable %02x %02x\n",temp[0],temp[1])); + if(0x30 == temp[0]) + { + NintendoDisable(pAd); + } + else if(0x31 == temp[0]) + { + UINT Wcid; + + NintendoEnable(pAd); + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); + APUpdateCapabilityAndErpIe(pAd); + RTMP_ASIC_SHARED_KEY_TABLE(pAd, + BSS0, + (UCHAR) NINTO_INFO.Local_KeyIdx, + &pAd->SharedKey[BSS0][NINTO_INFO.Local_KeyIdx]); + + GET_GroupKey_WCID(pAd, Wcid, BSS0); + RTMPSetWcidSecurityInfo(pAd, BSS0, NINTO_INFO.Local_KeyIdx, + CIPHER_WEP128, Wcid, SHAREDKEYTABLE); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("iwpriv ra0 nintendocapable 0/1\n")); + } + + return; +} + +extern VOID RTMPIoctlNintendoGetTable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + ULONG IrqFlags; + int Status; + + wrq->u.data.length = sizeof(RT_NINTENDO_TABLE); + TEMP_SEM_LOCK(&NINTO_INFO.NINTENDO_TABLE_Lock, IrqFlags) + memcpy(NINTO_INFO.NINTENDO_UP_BUFFER,&NINTO_INFO.DS_TABLE,sizeof(RT_NINTENDO_TABLE)); + TEMP_SEM_UNLOCK(&NINTO_INFO.NINTENDO_TABLE_Lock, IrqFlags); + IrqFlags = 0; + Status = copy_to_user(wrq->u.data.pointer, NINTO_INFO.NINTENDO_UP_BUFFER, wrq->u.data.length); + return; +} + +extern VOID RTMPIoctlNintendoSetTable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + int loopi; + int length; + PRT_NINTENDO_TABLE pset = NULL; + ULONG IrqFlags; + INT Status; + + length = sizeof(RT_NINTENDO_TABLE); + if(1 == wrq->u.data.length) + { + DBGPRINT(RT_DEBUG_TRACE, (" wrq->u.data.length %02x Use iwprive?\n",wrq->u.data.length)); + for(loopi=0; loopiu.data.length) + { + DBGPRINT(RT_DEBUG_TRACE, (" NINTENDO_TABLE size not match %02x %02x\n",length,wrq->u.data.length)); + return; + } +/* pset = (PRT_NINTENDO_TABLE) kmalloc(sizeof(RT_NINTENDO_TABLE), MEM_ALLOC_FLAG); */ + os_alloc_mem(pAd, (UCHAR **)&pset, sizeof(RT_NINTENDO_TABLE)); + if (pset == NULL) + { + DBGPRINT(RT_DEBUG_ERROR,("%s():alloc memory failed\n", __FUNCTION__)); + return; + } + Status = copy_from_user(pset, wrq->u.data.pointer, wrq->u.data.length); + + TEMP_SEM_LOCK(&NINTO_INFO.NINTENDO_TABLE_Lock, IrqFlags) + if(pset->number != NINTO_INFO.DS_TABLE.number) + { + DBGPRINT(RT_DEBUG_TRACE, (" NINTENDO_TABLE number not match %02x %02x\n",pset->number,NINTO_INFO.DS_TABLE.number)); + goto out; + } + for(loopi = 0; loopi < NINTO_INFO.DS_TABLE.number && loopi < NINTENDO_MAX_ENTRY; loopi++) + { + if(!memcmp(NINTO_INFO.DS_TABLE.entry[loopi].DS_Addr, pset->entry[loopi].DS_Addr, ETH_LENGTH_OF_ADDRESS)) + { + DBGPRINT(RT_DEBUG_TRACE, (" NINTENDO_TABLE entry[%d].registe %d \n",loopi,pset->entry[loopi].registe)); + NINTO_INFO.DS_TABLE.entry[loopi].registe = pset->entry[loopi].registe; + } + } +out: + TEMP_SEM_UNLOCK(&NINTO_INFO.NINTENDO_TABLE_Lock, IrqFlags); + IrqFlags = 0; + if(pset) +/* kfree(pset); */ + os_free_mem(NULL, pset); + return; +} + +extern UCHAR CheckNINTENDO_TABLE( + IN PRTMP_ADAPTER pAd, + PCHAR pDS_Ssid, + UCHAR DS_SsidLen, + PUCHAR pDS_Addr) +{ + int loopi; + UCHAR ErrorAck = 1; + ULONG IrqFlags; + PRT_NINTENDO_SSID pNINTENDOSSID_REQ = (PRT_NINTENDO_SSID)pDS_Ssid; + PRT_NINTENDO_SSID pNINTENDOSSID_RSP = (PRT_NINTENDO_SSID)pAd->ApCfg.MBSSID[MAIN_MBSSID].Ssid; + + pAd->ApCfg.MBSSID[MAIN_MBSSID].SsidLen = MAX_LEN_OF_SSID; + memset(pNINTENDOSSID_RSP, 0, MAX_LEN_OF_SSID); + memcpy(pNINTENDOSSID_RSP->NINTENDOFixChar, NINTENDO_SSID_NAME, NINTENDO_SSID_NAME_LN); + + if (32 == DS_SsidLen) + { + if ((pNINTENDOSSID_REQ->zero1 == 0) + && (pNINTENDOSSID_REQ->ID == 0) + && (pNINTENDOSSID_REQ->zero2 == 0)) + { + if (NINTENDO_PROBE_REQ_ON & pNINTENDOSSID_REQ->registe) + { + DBGPRINT(RT_DEBUG_TRACE, ("DS login on\n")); + AddNINTENDO_ENTRY(pAd, pNINTENDOSSID_REQ, pDS_Addr); + pNINTENDOSSID_RSP->registe |= NINTENDO_PROBE_RSP_ON; + ErrorAck = 0; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("DS login off\n")); + } + if (NINTENDO_PROBE_REQ_SIGNAL & pNINTENDOSSID_REQ->registe) + { + DBGPRINT(RT_DEBUG_TRACE, ("DS SIGNAL\n")); + } + } + } + else + { + TEMP_SEM_LOCK(&NINTO_INFO.NINTENDO_TABLE_Lock, IrqFlags) + for(loopi = 0; loopi < NINTO_INFO.DS_TABLE.number && loopi < NINTENDO_MAX_ENTRY; loopi++) + { + if(!memcmp(pDS_Addr, NINTO_INFO.DS_TABLE.entry[loopi].DS_Addr, ETH_LENGTH_OF_ADDRESS)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CheckNINTENDO_TABLE DS_TABLE.entry[%d].registe %d\n",loopi,NINTO_INFO.DS_TABLE.entry[loopi].registe)); + if (0 != NINTO_INFO.DS_TABLE.entry[loopi].registe) + { + memcpy(pNINTENDOSSID_RSP->NICKname, pAd->NINTENDO_WEP_SEED, NINTENDO_SSID_NICKNAME_LN); + pNINTENDOSSID_RSP->registe |= NINTENDO_PROBE_RSP_ON; + DBGPRINT(RT_DEBUG_TRACE, ("\n pAd->NINTENDO_WEP_KEY = ")); + for(loopi=0;loopiNINTENDO_WEP_KEY[loopi])); + DBGPRINT(RT_DEBUG_TRACE, ("\n")); + ErrorAck = 0; + } + } + } + TEMP_SEM_UNLOCK(&NINTO_INFO.NINTENDO_TABLE_Lock, IrqFlags); + IrqFlags = 0; + } + return ErrorAck; +} + +int Set_NintendiCapable_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + RTMP_IOCTL_INPUT_STRUCT wrq; + + wrq.u.data.pointer = arg; + wrq.u.data.length = 2; + RTMPIoctlNintendoCapable(pAd, &wrq); + return TRUE; +} + +INT Set_NintendoGet_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + RTMP_IOCTL_INPUT_STRUCT wrq; + + wrq.u.data.pointer = arg; + wrq.u.data.length = 2; + RTMPIoctlNintendoGetTable(pAd, &wrq); + return TRUE; +} + +INT Set_NintendoSet_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + RTMP_IOCTL_INPUT_STRUCT wrq; + + wrq.u.data.pointer = arg; + wrq.u.data.length = 1; + RTMPIoctlNintendoSetTable(pAd, &wrq); + return TRUE; +} + +#endif /* NINTENDO_AP */ diff --git a/mt7620/src/ap/ap_qload.c b/mt7620/src/ap/ap_qload.c new file mode 100644 index 0000000..945960d --- /dev/null +++ b/mt7620/src/ap/ap_qload.c @@ -0,0 +1,932 @@ +/**************************************************************************** + * 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 { + + 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->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; + /* End of if */ + + if (pEntry->Sst != SST_ASSOC) + continue; + /* End of if */ + + if (pEntry->BSS2040CoexistenceMgmtSupport) + bDisconnectSta = TRUE; + /* End of if */ + + 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, +#ifdef P2P_SUPPORT + pAd->ApCfg.MBSSID[pEntry->apidx].Bssid, +#endif /* P2P_SUPPORT */ + pAd->ApCfg.MBSSID[pEntry->apidx].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", + pEntry->Addr[0], pEntry->Addr[1], + pEntry->Addr[2], pEntry->Addr[3], + pEntry->Addr[4], pEntry->Addr[5])); + + MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr); + continue; + } /* End of if */ + } /* End of for */ + + /* 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->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); + } /* End of if */ +} /* End of QBSS_LoadAlarm */ + + +/* +======================================================================== +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->QloadBusyTimeThreshold = TimePeriod; + pAd->QloadBusyTimeThreshold *= pAd->QloadAlarmBusyTimeThreshold; + pAd->QloadBusyTimeThreshold /= 100; + pAd->QloadBusyTimeThreshold <<= 10; /* translate mini-sec to micro-sec */ +} /* End of QBSS_LoadAlarmBusyTimeThresholdReset */ +#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].bWmmCapable) + ) + { + pAd->FlgQloadEnable = TRUE; + break; + } /* End of if */ + } /* End of for */ + + if (pAd->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); + + /* default value is 50, please reference to IEEE802.11e 2005 Annex D */ + pAd->QloadChanUtilBeaconInt = 50; + } + else + { + /* no any WMM is enabled */ + RTMP_IO_WRITE32(pAd, CH_TIME_CFG, 0x00000000); + } /* End of if */ + + pAd->QloadChanUtilTotal = 0; + pAd->QloadUpTimeLast = 0; + +#ifdef QLOAD_FUNC_BUSY_TIME_STATS + /* clear busy time statistics */ + NdisZeroMemory(pAd->QloadBusyCountPri, sizeof(pAd->QloadBusyCountPri)); + NdisZeroMemory(pAd->QloadBusyCountSec, sizeof(pAd->QloadBusyCountSec)); +#endif /* QLOAD_FUNC_BUSY_TIME_STATS */ + +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM + /* init threshold before QBSS_LoadAlarmReset */ + pAd->QloadAlarmBusyTimeThreshold = QBSS_LOAD_ALRAM_BUSY_TIME_THRESHOLD; + pAd->QloadAlarmBusyNumThreshold = QBSS_LOAD_ALRAM_BUSY_NUM_THRESHOLD; + + QBSS_LoadAlarmReset(pAd); +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ +} /* End of QBSS_LoadInit */ + + +/* +======================================================================== +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->FlgQloadAlarm = FALSE; + pAd->QloadAlarmDuration = 0; + pAd->QloadAlarmNumber = 0; + + pAd->FlgQloadAlarmIsSuspended = FALSE; + + QBSS_LoadAlarmBusyTimeThresholdReset(pAd, pAd->CommonCfg.BeaconPeriod); +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ +} /* End of QBSS_LoadAlarmReset */ + + +/* +======================================================================== +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->FlgQloadAlarmIsSuspended = FALSE; +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ +} /* End of QBSS_LoadAlarmResume */ + + +/* +======================================================================== +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->FlgQloadAlarmIsSuspended = TRUE; +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ +} /* End of QBSS_LoadAlarmSuspend */ + + +/* +======================================================================== +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->QloadChanUtilBeaconCnt == 0) + return pAd->QloadChanUtilTotal; + /* End of if */ + + return (pAd->QloadChanUtilTotal / pAd->QloadChanUtilBeaconCnt); +} /* End of QBSS_LoadBusyTimeGet */ + + +/* +======================================================================== +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->FlgQloadAlarm; + + pAd->FlgQloadAlarm = FALSE; + return FlgQloadAlarm; +#else + + return FALSE; +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ +} /* End of QBSS_LoadIsAlarmIssued */ + + +/* +======================================================================== +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->QloadAlarmBusyTimeThreshold == 0) + return TRUE; /* always ok */ + /* End of if */ + + if (BusyTime >= pAd->QloadBusyTimeThreshold) + return FALSE; + /* End of if */ +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ + + return TRUE; +} /* End of QBSS_LoadIsAlarmIssued */ + + +/* +======================================================================== +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->FlgQloadEnable == 0) + return 0; + /* End of if */ + + /* init */ + pLoad->ElementId = ELM_QBSS_LOAD_ID; + pLoad->Length = ELM_QBSS_LOAD_LEN; + + pLoad->StationCount = le2cpu16(MacTableAssocStaNumGet(pAd)); + pLoad->ChanUtil = pAd->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; +} /* End of QBSS_LoadElementAppend */ + + + + +/* +======================================================================== +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->FlgQloadEnable == 0) || + (pAd->FlgQloadAlarmIsSuspended == TRUE)) + { + return; + } /* End of if */ + + /* calculate new time period if needed */ + if ((UpTime > 0) && + (pAd->QloadUpTimeLast > 0) && + (UpTime > pAd->QloadUpTimeLast)) + { + /* re-calculate time period */ + TimePeriod = (UINT32)(UpTime - pAd->QloadUpTimeLast); + + /* translate to mini-second */ + TimePeriod = (TimePeriod*1000)/OS_HZ; + +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM + /* re-calculate QloadBusyTimeThreshold */ + if (TimePeriod != pAd->QloadTimePeriodLast) + QBSS_LoadAlarmBusyTimeThresholdReset(pAd, TimePeriod); + /* End of if */ + + pAd->QloadTimePeriodLast = TimePeriod; +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ + } /* End of if */ + + /* update up time */ + pAd->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->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; + /* End of if */ + pAd->QloadBusyCountSec[BusyTimeId] ++; +#endif /* QLOAD_FUNC_BUSY_TIME_STATS */ + +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM + if ((pAd->FlgQloadAlarmIsSuspended == FALSE) && + (pAd->QloadAlarmBusyTimeThreshold > 0)) + { + /* Alarm is not suspended and is enabled */ + + if ((pAd->QloadBusyTimeThreshold != 0) && + (BusyTime >= pAd->QloadBusyTimeThreshold)) + { + FlgIsBusyOverThreshold = TRUE; + } /* End of if */ + } /* End of if */ +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ + } /* End of if */ +#endif /* DOT11_N_SUPPORT */ + + /* do busy time statistics for primary channel */ + RTMP_IO_READ32(pAd, CH_BUSY_STA, &BusyTime); + pAd->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; + /* End of if */ + pAd->QloadBusyCountPri[BusyTimeId] ++; +#endif /* QLOAD_FUNC_BUSY_TIME_STATS */ + +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM + if ((pAd->FlgQloadAlarmIsSuspended == FALSE) && + (pAd->QloadAlarmBusyTimeThreshold > 0)) + { + /* Alarm is not suspended and is enabled */ + + if ((pAd->QloadBusyTimeThreshold != 0) && + (BusyTime >= pAd->QloadBusyTimeThreshold)) + { + FlgIsBusyOverThreshold = TRUE; + } /* End of if */ + } /* End of if */ +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ + + /* accumulate channel busy time for primary channel */ + pAd->QloadChanUtilTotal += BusyTime; + + /* update new channel utilization for primary channel */ + if (++pAd->QloadChanUtilBeaconCnt >= pAd->QloadChanUtilBeaconInt) + { + ChanUtilNu = pAd->QloadChanUtilTotal; + ChanUtilNu *= 255; + + ChanUtilDe = pAd->QloadChanUtilBeaconInt; + + /* + Still use pAd->CommonCfg.BeaconPeriod. + Because we change QloadChanUtil not every TBTT. + */ + ChanUtilDe *= pAd->CommonCfg.BeaconPeriod; + + ChanUtilDe <<= 10; /* ms to us */ + + pAd->QloadChanUtil = (UINT8)(ChanUtilNu/ChanUtilDe); + + /* re-accumulate channel busy time */ + pAd->QloadChanUtilBeaconCnt = 0; + pAd->QloadChanUtilTotal = 0; + } /* End of if */ + +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM + /* check if alarm function is enabled */ + if ((pAd->FlgQloadAlarmIsSuspended == FALSE) && + (pAd->QloadAlarmBusyTimeThreshold > 0)) + { + /* Alarm is not suspended and is enabled */ + + /* check if we need to issue a alarm */ + if (FlgIsBusyOverThreshold == TRUE) + { + if (pAd->QloadAlarmDuration == 0) + { + /* last alarm ended so we can check new alarm */ + + pAd->QloadAlarmBusyNum ++; + + if (pAd->QloadAlarmBusyNum >= pAd->QloadAlarmBusyNumThreshold) + { + /* + The continued number of busy time >= threshold is larger + than number threshold so issuing a alarm. + */ + FlgIsAlarmNeeded = TRUE; + pAd->QloadAlarmDuration ++; + } /* End of if */ + } /* End of if */ + } + else + pAd->QloadAlarmBusyNum = 0; + /* End of if */ + + if (pAd->QloadAlarmDuration > 0) + { + /* + New alarm occurs so we can not re-issue new alarm during + QBSS_LOAD_ALARM_DURATION * TBTT. + */ + if (++pAd->QloadAlarmDuration >= QBSS_LOAD_ALARM_DURATION) + { + /* can re-issue next alarm */ + pAd->QloadAlarmDuration = 0; + pAd->QloadAlarmBusyNum = 0; + } /* End of if */ + } /* End of if */ + + if (FlgIsAlarmNeeded == TRUE) + QBSS_LoadAlarm(pAd); + /* End of if */ + } + else + { + /* clear statistics counts */ + pAd->QloadAlarmBusyNum = 0; + pAd->QloadAlarmDuration = 0; + pAd->FlgQloadAlarm = FALSE; + } /* End of if */ +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ +} /* End of QBSS_LoadUpdate */ + + +/* +======================================================================== +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->QloadBusyCountPri, sizeof(pAd->QloadBusyCountPri)); + NdisZeroMemory(pAd->QloadBusyCountSec, sizeof(pAd->QloadBusyCountSec)); +#endif /* QLOAD_FUNC_BUSY_TIME_STATS */ + +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM + /* clear alarm function variables */ + pAd->QloadChanUtilTotal = 0; + pAd->FlgQloadAlarm = FALSE; + pAd->QloadAlarmBusyNum = 0; +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ +} /* End of QBSS_LoadStatusClear */ + + +/* +======================================================================== +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; + + printk("\n\tPrimary Busy Time\tTimes\n"); + + for(BusyTimeId=0; BusyTimeIdQloadBusyCountPri[BusyTimeId]); + } /* End of for */ + + printk("\n\tSecondary Busy Time\tTimes\n"); + + for(BusyTimeId=0; BusyTimeIdQloadBusyCountSec[BusyTimeId]); + } /* End of for */ +#else + + printk("\tBusy time statistics is not included into the driver!\n"); +#endif /* QLOAD_FUNC_BUSY_TIME_STATS */ + + printk("\n"); + return TRUE; +} /* End of Show_QoSLoad_Proc */ + + +/* +======================================================================== +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; +} /* End of Set_QloadClr_Proc */ + + +/* +======================================================================== +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->QloadAlarmBusyTimeThreshold = (UCHAR)simple_strtol(Arg, 0, 10); + + QBSS_LoadAlarmReset(pAd); + + pAd->QloadTimePeriodLast = pAd->CommonCfg.BeaconPeriod; +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ + + return TRUE; +} /* End of Set_QloadAlarmTimeThreshold_Proc */ + + +/* +======================================================================== +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->QloadAlarmBusyNumThreshold = (UCHAR)simple_strtol(Arg, 0, 10); +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ + + return TRUE; +} /* End of Set_QloadAlarmNumThreshold_Proc */ + +#endif /* AP_QLOAD_SUPPORT */ + +/* End of ap_qload.c */ diff --git a/mt7620/src/ap/ap_repeater.c b/mt7620/src/ap/ap_repeater.c new file mode 100644 index 0000000..209c84b --- /dev/null +++ b/mt7620/src/ap/ap_repeater.c @@ -0,0 +1,783 @@ +/* + *************************************************************************** + * 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 PRTMP_ADAPTER pAd, + IN BOOLEAN bRealMAC, + IN PUCHAR pAddr) +{ + ULONG HashIdx; + UCHAR tempMAC[6]; + REPEATER_CLIENT_ENTRY *pEntry = NULL; + REPEATER_CLIENT_ENTRY_MAP *pMapEntry = NULL; + + NdisAcquireSpinLock(&pAd->ApCfg.ReptCliEntryLock); + COPY_MAC_ADDR(tempMAC, pAddr); + HashIdx = MAC_ADDR_HASH_INDEX(tempMAC); + + if (bRealMAC == TRUE) + { + pMapEntry = pAd->ApCfg.ReptMapHash[HashIdx]; + while (pMapEntry) + { + pEntry = pMapEntry->pReptCliEntry; + + if (pEntry->CliValid && MAC_ADDR_EQUAL(pEntry->OriginalAddress, tempMAC)) + break; + else + { + pEntry = NULL; + pMapEntry = pMapEntry->pNext; + } + } + } + else + { + pEntry = pAd->ApCfg.ReptCliHash[HashIdx]; + while (pEntry) + { + if (pEntry->CliValid && MAC_ADDR_EQUAL(pEntry->CurrentAddress, tempMAC)) + break; + else + pEntry = pEntry->pNext; + } + } + NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); + + return pEntry; +} + +VOID RTMPInsertRepeaterAsicEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR CliIdx, + IN PUCHAR pAddr) +{ + ULONG offset, Addr; + UCHAR tempMAC[ETH_LENGTH_OF_ADDRESS]; + + 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[ETH_LENGTH_OF_ADDRESS]; + 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}}; + + DBGPRINT(RT_DEBUG_TRACE, (" %s.\n", __FUNCTION__)); + + 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); + + 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); + } + else + { + NdisCopyMemory(tempMAC, pAd->ApCfg.ApCliTab[apidx].CurrentAddress, 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; + + DBGPRINT(RT_DEBUG_ERROR, (" %s.\n", __FUNCTION__)); + + RTMPRemoveRepeaterAsicEntry(pAd, CliIdx); + + NdisAcquireSpinLock(&pAd->ApCfg.ReptCliEntryLock); + pEntry = &pAd->ApCfg.ApCliTab[apidx].RepeaterCli[CliIdx]; + + HashIdx = MAC_ADDR_HASH_INDEX(pEntry->CurrentAddress); + + pPrevEntry = NULL; + pProbeEntry = pAd->ApCfg.ReptCliHash[HashIdx]; + ASSERT(pProbeEntry); + 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); + + 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); + + pAd->ApCfg.ApCliTab[apidx].RepeaterCli[CliIdx].CliConnectState = 0; + NdisZeroMemory(pAd->ApCfg.ApCliTab[apidx].RepeaterCli[CliIdx].OriginalAddress, MAC_ADDR_LEN); + + pAd->ApCfg.RepeaterCliSize--; + NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); + + return; +} + +MAC_TABLE_ENTRY *RTMPInsertRepeaterMacEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + 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_MAC_TABLE_SIZE_WITH_REPEATER) + return NULL; + + /* allocate one MAC entry*/ + NdisAcquireSpinLock(&pAd->MacTabLock); + + i = (MAX_LEN_OF_MAC_TABLE + ((MAX_EXT_MAC_ADDR_SIZE + 1) * (apidx - MIN_NET_DEVICE_FOR_APCLI))); + + if (cliIdx != 0xFF) + i = i + cliIdx + 1; + + pEntry = &pAd->MacTab.Content[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->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].AuthMode; + pEntry->WepStatus = pAd->ApCfg.ApCliTab[pEntry->apidx].WepStatus; + pEntry->MatchAPCLITabIdx = 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); + + 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); + + 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 */ + + DBGPRINT(RT_DEBUG_TRACE, ("%s - allocate entry #%d, Aid = %d, Total= %d\n",__FUNCTION__, i, pEntry->Aid, 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) + { + 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; + + if (pAd->ApCfg.bMACRepeaterEn && + pAd->ApCfg.MACRepeaterOuiMode == 2 && + 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 % 23 == 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 */ +} + +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; + } + } + + /* 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, (" Save Need Skip MAC Address = %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; + ULONG 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_LEN_OF_MAC_TABLE; i < MAX_MAC_TABLE_SIZE_WITH_REPEATER; i++) + { + PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i]; + if (pEntry && IS_ENTRY_APCLI(pEntry)&& (pEntry->Sst == SST_ASSOC) && (pEntry->bReptCli)) + { + DataRate=0; + getRate(pEntry->HTPhyMode, &DataRate); + + 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", GetPhyMode(pEntry->HTPhyMode.field.MODE)); + printk("%-6s", GetBW(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; +} +#endif /* MAC_REPEATER_SUPPORT */ + diff --git a/mt7620/src/ap/ap_sanity.c b/mt7620/src/ap/ap_sanity.c new file mode 100644 index 0000000..a8c32f2 --- /dev/null +++ b/mt7620/src/ap/ap_sanity.c @@ -0,0 +1,523 @@ +/**************************************************************************** + * 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 BROADCOM_OUI[]; +extern UCHAR WPS_OUI[]; + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== + */ + +BOOLEAN PeerAssocReqCmmSanity( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN isReassoc, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pListenInterval, + OUT PUCHAR pApAddr, + OUT UCHAR *pSsidLen, + OUT char *Ssid, + OUT UCHAR *pRatesLen, + OUT UCHAR Rates[], + OUT UCHAR *RSN, + OUT UCHAR *pRSNLen, + OUT BOOLEAN *pbWmmCapable, +#ifdef WSC_AP_SUPPORT + OUT BOOLEAN *pWscCapable, +#endif /* WSC_AP_SUPPORT */ + OUT ULONG *pRalinkIe, + OUT EXT_CAP_INFO_ELEMENT *pExtCapInfo, +#ifdef P2P_SUPPORT + OUT ULONG *P2PSubelementLen, + OUT PUCHAR pP2pSubelement, +#endif /* P2P_SUPPORT */ + OUT UCHAR *pHtCapabilityLen, + OUT HT_CAPABILITY_IE *pHtCapability) +{ + CHAR *Ptr; + 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 }; + MAC_TABLE_ENTRY *pEntry = (MAC_TABLE_ENTRY *)NULL; +#ifdef P2P_SUPPORT + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + UCHAR P2POUIBYTE[4] = {0x50, 0x6f, 0x9a, 0x9}; +#endif /* P2P_SUPPORT */ + + /* to prevent caller from using garbage output value */ + *pSsidLen = 0; + *pRatesLen = 0; + *pRSNLen = 0; + *pbWmmCapable = FALSE; + *pRalinkIe = 0; + *pHtCapabilityLen= 0; + + COPY_MAC_ADDR(pAddr2, &Fr->Hdr.Addr2); + + pEntry = MacTableLookup(pAd, pAddr2); + if (pEntry == NULL) + return FALSE; + + + + + Ptr = (PCHAR)Fr->Octet; + + NdisMoveMemory(pCapabilityInfo, &Fr->Octet[0], 2); + NdisMoveMemory(pListenInterval, &Fr->Octet[2], 2); + + if (isReassoc) + { + NdisMoveMemory(pApAddr, &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(Ssid, eid_ptr->Octet, eid_ptr->Len); + *pSsidLen = eid_ptr->Len; + DBGPRINT(RT_DEBUG_TRACE, + ("PeerAssocReqSanity - SsidLen = %d \n", *pSsidLen)); + } + 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(Rates, eid_ptr->Octet, eid_ptr->Len); + + DBGPRINT(RT_DEBUG_TRACE, + ("PeerAssocReqSanity - 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 + { + 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; + *pRatesLen = 8; + NdisMoveMemory(Rates, 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 + *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, 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 */ + + *pHtCapabilityLen = 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 >= sizeof(EXT_CAP_INFO_ELEMENT)) + { + NdisMoveMemory(pExtCapInfo, eid_ptr->Octet, sizeof(EXT_CAP_INFO_ELEMENT)); + DBGPRINT(RT_DEBUG_WARN, ("PeerAssocReqSanity - IE_EXT_CAPABILITY!\n")); + } + + break; + + case IE_WPA: /* same as IE_VENDOR_SPECIFIC */ + case IE_WPA2: + +#ifdef P2P_SUPPORT + if (NdisEqualMemory(eid_ptr->Octet, P2POUIBYTE, sizeof(P2POUIBYTE)) && (eid_ptr->Len >= 4)) + { + if (*P2PSubelementLen == 0) + { + RTMPMoveMemory(pP2pSubelement, &eid_ptr->Eid, (eid_ptr->Len+2)); + *P2PSubelementLen = (eid_ptr->Len+2); + } + else if (*P2PSubelementLen > 0) + { + RTMPMoveMemory(pP2pSubelement + *P2PSubelementLen, &eid_ptr->Eid, (eid_ptr->Len+2)); + *P2PSubelementLen += (eid_ptr->Len+2); + } + + DBGPRINT(RT_DEBUG_TRACE, (" ! ===>P2P - PeerAssocReqSanity P2P IE Len becomes = %d. %s\n", *P2PSubelementLen, decodeP2PState(pP2PCtrl->P2PConnectState))); + break; + } +#endif /* P2P_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 */ + *pWscCapable = TRUE; +#endif /* WSC_AP_SUPPORT */ +#ifdef EASY_CONFIG_SETUP + AutoProvisionCheckEntry(pAd, pEntry, eid_ptr); +#endif /* EASY_CONFIG_SETUP */ + break; + } + + /* 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 */ + + *pHtCapabilityLen = SIZE_HT_CAP_IE; + } + break; + + default: + /* ignore other cases */ + break; + } + } + + if (NdisEqualMemory(eid_ptr->Octet, RALINK_OUI, 3) && (eid_ptr->Len == 7)) + { + /**pRalinkIe = eid_ptr->Octet[3]; */ + if (eid_ptr->Octet[3] != 0) + *pRalinkIe = eid_ptr->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. */ + break; + } + + /* WMM_IE */ + if (NdisEqualMemory(eid_ptr->Octet, WME_INFO_ELEM, 6) && (eid_ptr->Len == 7)) + { + *pbWmmCapable = 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].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")); + break; + } + + 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(RSN, eid_ptr, eid_ptr->Len + 2); + *pRSNLen=eid_ptr->Len + 2; + + } + else + { + *pRSNLen=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].AuthMode != Ndis802_11AuthModeWAICERT) && + (pAd->ApCfg.MBSSID[pEntry->apidx].AuthMode != Ndis802_11AuthModeWAIPSK)) + break; + + /* Sanity check the validity of WIE */ + /* Todo - AlbertY */ + + /* Copy whole WAPI-IE context */ + NdisMoveMemory(RSN, eid_ptr, eid_ptr->Len + 2); + *pRSNLen=eid_ptr->Len + 2; + DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - IE_WAPI(%d)\n",eid_ptr->Len)); + break; +#endif /* WAPI_SUPPORT */ + + + + default: + break; + } + + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + if ((Sanity&0x3) != 0x03) + { + DBGPRINT(RT_DEBUG_WARN, ("PeerAssocReqSanity - missing mandatory field\n")); + return FALSE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - success\n")); + 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 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 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 + ) +{ + 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; + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("APPeerAuthSanity fail - wrong algorithm (=%d)\n", *Alg)); + return FALSE; + } + + return TRUE; +} + + diff --git a/mt7620/src/ap/ap_sync.c b/mt7620/src/ap/ap_sync.c new file mode 100644 index 0000000..b43ca34 --- /dev/null +++ b/mt7620/src/ap/ap_sync.c @@ -0,0 +1,1996 @@ +/**************************************************************************** + * 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" +#ifdef MESH_SUPPORT +#include "mesh_sanity.h" +#endif /* MESH_SUPPORT */ + +#define OBSS_BEACON_RSSI_THRESHOLD (-85) + +#ifdef DOT11_N_SUPPORT +void build_ext_channel_switch_ie( + IN PRTMP_ADAPTER pAd, + IN HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE *pIE); +#endif /* DOT11_N_SUPPORT */ + +#ifdef P2P_SUPPORT +extern UCHAR WILDP2PSSID[]; +extern UCHAR WILDP2PSSIDLEN; +#endif /* P2P_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 PRTMP_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); +#ifdef P2P_SUPPORT + StateMachineSetAction(Sm, AP_SYNC_IDLE, APMT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)APPeerBeaconAtScanAction); +#endif /* P2P_SUPPORT */ +#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); + + /* resume scanning for fast-roaming */ + StateMachineSetAction(Sm, AP_SCAN_PENDING, APMT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)APMlmeScanReqAction); + StateMachineSetAction(Sm, AP_SCAN_PENDING, APMT2_PEER_BEACON, (STATE_MACHINE_FUNC)APPeerBeaconAtScanAction); + StateMachineSetAction(Sm, AP_SCAN_PENDING, APMT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)APPeerBeaconAtScanAction); + + RTMPInitTimer(pAd, &pAd->MlmeAux.APScanTimer, GET_TIMER_FUNCTION(APScanTimeout), pAd, FALSE); +#endif /* AP_SCAN_SUPPORT */ +} + +/* + ========================================================================== + 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) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + CHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SsidLen; /*, Rates[MAX_LEN_OF_SUPPORTED_RATES], RatesLen; */ + HEADER_802_11 ProbeRspHdr; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0, TmpLen; + LARGE_INTEGER FakeTimestamp; + UCHAR DsLen = 1;/*, IbssLen = 2, TimLen=1, */ + /*BitmapControl=0, VirtualBitmap=0; */ + UCHAR ErpIeLen = 1; + UCHAR apidx = 0, PhyMode, SupRateLen; + UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2;/*, RSN_Len=22; */ + BOOLEAN bRequestRssi=FALSE; + +#ifdef WSC_AP_SUPPORT + UCHAR Addr3[MAC_ADDR_LEN]; + PFRAME_802_11 pFrame = (PFRAME_802_11)Elem->Msg; + + COPY_MAC_ADDR(Addr3, pFrame->Hdr.Addr3); +#endif /* WSC_AP_SUPPORT */ + +#ifdef WDS_SUPPORT + /* if in bridge mode, no need to reply probe req. */ + if (pAd->WdsTab.Mode == WDS_BRIDGE_MODE) + return; +#endif /* WDS_SUPPORT */ +#ifdef P2P_SUPPORT + /* When enable P2P scan, there driver alway sent probe request. + But when user enter main page, LG request not sent probe response. */ + if ( pAd->P2pCfg.bSentProbeRSP != TRUE ) + return; +#endif /* P2P_SUPPORT */ + + if (! PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen, &bRequestRssi)) + return; + +#ifdef NINTENDO_AP + if ((NdisEqualMemory(NINTENDO_SSID_NAME, Ssid, NINTENDO_SSID_NAME_LN)) && (0 == pAd->bNintendoCapable)) + DBGPRINT(RT_DEBUG_TRACE, ("iwpriv ra0 nintendocapable 0 (Not Enable)\n")); + if (0 == pAd->bNintendoCapable) +#endif /* NINTENDO_AP */ + for(apidx=0; apidxApCfg.BssidNum; apidx++) + { + RSNIe = IE_WPA; + + if ((pAd->ApCfg.MBSSID[apidx].MSSIDDev != NULL) && + !(RTMP_OS_NETDEV_STATE_RUNNING(pAd->ApCfg.MBSSID[apidx].MSSIDDev))) + { + /* the interface is down, so we can not send probe response */ + continue; + } /* End of if */ + + PhyMode = pAd->ApCfg.MBSSID[apidx].PhyMode; + + if (((SsidLen == 0) && (! pAd->ApCfg.MBSSID[apidx].bHideSsid)) || +#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 */ + ((SsidLen == 32) && MAC_ADDR_EQUAL(Addr3, pAd->ApCfg.MBSSID[apidx].Bssid) && (pAd->ApCfg.MBSSID[apidx].bHideSsid == 0)) || +#endif /* WSC_AP_SUPPORT */ +#ifdef P2P_SUPPORT + (NdisEqualMemory(Ssid, &WILDP2PSSID[0], WILDP2PSSIDLEN)) || +#endif /* P2P_SUPPORT */ + ((SsidLen == pAd->ApCfg.MBSSID[apidx].SsidLen) && NdisEqualMemory(Ssid, pAd->ApCfg.MBSSID[apidx].Ssid, (ULONG) SsidLen))) + ; + else + continue; /* check next BSS */ + +#ifdef BAND_STEERING + BND_STRG_CHECK_CONNECTION_REQ( pAd, + NULL, + Addr2, + Elem->MsgType, + Elem->Rssi0, + Elem->Rssi1, + Elem->Rssi2, + NULL); +#endif /* BAND_STEERING */ + +#ifdef NINTENDO_AP + if (NdisEqualMemory(NINTENDO_SSID_NAME, Ssid, NINTENDO_SSID_NAME_LN)) + if(1 == pAd->bNintendoCapable) + if(CheckNINTENDO_TABLE(pAd, Ssid, SsidLen, Addr2)) + return; +#endif /* NINTENDO_AP */ + /* allocate and send out ProbeRsp frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + MgtMacHeaderInit(pAd, &ProbeRspHdr, SUBTYPE_PROBE_RSP, 0, Addr2, +#ifdef P2P_SUPPORT + pAd->ApCfg.MBSSID[apidx].Bssid, +#endif /* P2P_SUPPORT */ + pAd->ApCfg.MBSSID[apidx].Bssid); + + if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA) || + (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPAPSK)) + RSNIe = IE_WPA; + else if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA2PSK)) + RSNIe = IE_WPA2; +#ifdef WAPI_SUPPORT + else if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWAICERT) || + (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWAIPSK)) + RSNIe = IE_WAPI; +#endif /* WAPI_SUPPORT */ + +#ifdef P2P_SUPPORT + if (P2P_GO_ON(pAd)) + { + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateIe = IE_SUPP_RATES; + UCHAR SupRateLen = 0; + UCHAR Channel = pAd->CommonCfg.Channel; + + if (IS_P2P_LISTEN(pAd)) + Channel = pAd->P2pCfg.ListenChannel; + + 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; + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &ProbeRspHdr, + TIMESTAMP_LEN, &FakeTimestamp, + 2, &pAd->CommonCfg.BeaconPeriod, + 2, &pAd->ApCfg.MBSSID[apidx].CapabilityInfo, + 1, &SsidIe, + 1, &pAd->ApCfg.MBSSID[apidx].SsidLen, + pAd->ApCfg.MBSSID[apidx].SsidLen, pAd->ApCfg.MBSSID[apidx].Ssid, + 1, &SupRateIe, + 1, &SupRateLen, + SupRateLen, &SupRate, + 1, &DsIe, + 1, &DsLen, + 1, &Channel, + END_OF_ARGS); + + } + else +#endif /* P2P_SUPPORT */ + { + SupRateLen = pAd->CommonCfg.SupRateLen; + if (PhyMode == PHY_11B) + SupRateLen = 4; + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &ProbeRspHdr, + TIMESTAMP_LEN, &FakeTimestamp, + 2, &pAd->CommonCfg.BeaconPeriod, + 2, &pAd->ApCfg.MBSSID[apidx].CapabilityInfo, + 1, &SsidIe, + 1, &pAd->ApCfg.MBSSID[apidx].SsidLen, + pAd->ApCfg.MBSSID[apidx].SsidLen, pAd->ApCfg.MBSSID[apidx].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 != PHY_11B)) + { + 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)) + { + 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; + } +#endif /* A_BAND_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + if ((PhyMode >= PHY_11ABGN_MIXED) && + (pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo.bHtEnable)) + { + ULONG TmpLen; + UCHAR HtLen, AddHtLen, NewExtLen; +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; + ADD_HT_INFO_IE addHTInfoTmp; +#endif + +#ifdef A_BAND_SUPPORT + if (pAd->CommonCfg.bExtChannelSwitchAnnouncement && (pAd->CommonCfg.Channel > 14)) + { + 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 /* A_BAND_SUPPORT */ + + 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 */ +#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 (pAd->ApCfg.MBSSID[apidx].AuthMode < Ndis802_11AuthModeWPA) + ; /* enough information */ + else if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1WPA2) || + (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) + { + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &RSNIe, + 1, &pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0], + pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0], pAd->ApCfg.MBSSID[apidx].RSN_IE[0], + 1, &RSNIe2, + 1, &pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1], + pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1], pAd->ApCfg.MBSSID[apidx].RSN_IE[1], + END_OF_ARGS); + FrameLen += TmpLen; + } + else + { + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &RSNIe, + 1, &pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0], + pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0], pAd->ApCfg.MBSSID[apidx].RSN_IE[0], + END_OF_ARGS); + FrameLen += TmpLen; + } + + /* add WMM IE here */ + if (pAd->ApCfg.MBSSID[apidx].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], &pAd->ApCfg.MBSSID[apidx].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 AP_QLOAD_SUPPORT + if (pAd->FlgQloadEnable != 0) + { + FrameLen += QBSS_LoadElementAppend(pAd, pOutBuffer+FrameLen); + } +#endif /* AP_QLOAD_SUPPORT */ + + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + /* P802.11n_D3.03, 7.3.2.60 Overlapping BSS Scan Parameters IE */ + if ((PhyMode >= PHY_11ABGN_MIXED) && + (pAd->CommonCfg.Channel <= 14) && + (pAd->ApCfg.MBSSID[apidx].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 ((PhyMode >= PHY_11ABGN_MIXED) && (pAd->CommonCfg.Channel <= 14) && + (pAd->ApCfg.MBSSID[apidx].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 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 RSSI_FEEDBACK + if (bRequestRssi == TRUE) + { + MAC_TABLE_ENTRY *pEntry=NULL; + + DBGPRINT(RT_DEBUG_ERROR, ("SYNC - Send PROBE_RSP to %02x:%02x:%02x:%02x:%02x:%02x...\n", Addr2[0],Addr2[1],Addr2[2],Addr2[3],Addr2[4],Addr2[5] )); + + RalinkSpecificIe[5] |= 0x8; + pEntry = MacTableLookup(pAd, 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 RT3883 + if (IS_RT3883(pAd)) + FrameLen += RT3883_ext_pkt_len(pOutBuffer, FrameLen, RalinkSpecificIe, 9); +#endif /* RT3883 */ +} + +#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); + } +#endif /* DOT11_N_SUPPORT */ + FrameLen += TmpLen; + } +#endif /* A_BAND_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; + } +#endif /* A_BAND_SUPPORT */ + + NdisZeroMemory(TmpFrame, sizeof(TmpFrame)); + + /* prepare channel information */ + MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, + 1, &pAd->ChannelList[0].Channel, + 1, &pAd->ChannelListNum, + 1, &MaxTxPower, + END_OF_ARGS); + TmpLen2 += TmpLen; + + /* 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 DOT11_N_SUPPORT + if ((PhyMode >= PHY_11ABGN_MIXED) && + (pAd->ApCfg.MBSSID[apidx].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; + } + } +#endif /* DOT11_N_SUPPORT */ + + +#ifdef WSC_AP_SUPPORT + /* for windows 7 logo test */ + if ((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode != WSC_DISABLE) && +#ifdef DOT1X_SUPPORT + (pAd->ApCfg.MBSSID[apidx].IEEE8021X == FALSE) && +#endif /* DOT1X_SUPPORT */ + (pAd->ApCfg.MBSSID[apidx].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 ((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode > WSC_DISABLE) && (pAd->ApCfg.MBSSID[apidx].WscIEProbeResp.ValueLen)) + { + ULONG WscTmpLen = 0; + MakeOutgoingFrame(pOutBuffer+FrameLen, &WscTmpLen, + pAd->ApCfg.MBSSID[apidx].WscIEProbeResp.ValueLen, pAd->ApCfg.MBSSID[apidx].WscIEProbeResp.Value, + END_OF_ARGS); + FrameLen += WscTmpLen; + } +#endif /* WSC_AP_SUPPORT */ + +#ifdef WAC_SUPPORT + WAC_PeerProbeReq(pAd, apidx, Elem, Addr2, pOutBuffer, &FrameLen); + if (pAd->ApCfg.MBSSID[apidx].EasyConfigInfo.pVendorInfoForProbeRsp) + { + ULONG tmpWACLen = 0; + MakeOutgoingFrame(pOutBuffer+FrameLen, + &tmpWACLen, + pAd->ApCfg.MBSSID[apidx].EasyConfigInfo.VendorInfoForProbeRspLen, + pAd->ApCfg.MBSSID[apidx].EasyConfigInfo.pVendorInfoForProbeRsp, + END_OF_ARGS); + FrameLen += tmpWACLen; + } +#endif /* WAC_SUPPORT */ + + +#ifdef P2P_SUPPORT + if (P2P_GO_ON(pAd)) + { + ULONG Peerip, P2PSubelementLen = 0, WpsLen = 0; + UCHAR *P2pSubelement; + UCHAR *WpsIE; + + os_alloc_mem(NULL, (UCHAR **)&P2pSubelement, MAX_VIE_LEN); + os_alloc_mem(NULL, (UCHAR **)&WpsIE, MAX_VIE_LEN); + + /*PeerP2pProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen, &Peerip, &P2PSubelementLen, P2pSubelement, &WpsLen, WpsIE);*/ + /* Ralink Proprietary feature for IP */ +/* + P2pMakeProbeRspWSCIE(pAd, pOutBuffer + FrameLen, &TmpLen); + FrameLen += TmpLen; +*/ + /* APPeerProbeReqAction() is called when I am already GO. So doesn't use Is_P2P_on to check whether need to add P2P IE in response. */ + /*if (P2PSubelementLen > 0)*/ + if (PeerP2pProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen, &Peerip, &P2PSubelementLen, P2pSubelement, &WpsLen, WpsIE)) + { + ULONG P2PIeLen; + PUCHAR ptr; + ptr = pOutBuffer + FrameLen; + P2pMakeP2pIE(pAd, SUBTYPE_PROBE_RSP, ptr, &P2PIeLen); + FrameLen += P2PIeLen; + } + if (P2pSubelement) + os_free_mem(NULL, P2pSubelement); + if (WpsIE) + os_free_mem(NULL, WpsIE); + + } + +#endif /* P2P_SUPPORT */ + + /* 802.11n 11.1.3.2.2 active scanning. sending probe response with MCS rate is */ + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } +} + +/* + ========================================================================== + 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 Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; +/* CHAR Ssid[MAX_LEN_OF_SSID]; */ + CHAR *Ssid = NULL; + UCHAR SsidLen, MessageToMe=0, BssType, Channel; + UCHAR Rates[MAX_LEN_OF_SUPPORTED_RATES]; + PUCHAR pRates = NULL; + UCHAR RatesLen, DtimCount=0, DtimPeriod=0, BcastFlag=0; + USHORT CapabilityInfo, BeaconPeriod; + LARGE_INTEGER TimeStamp; + /*BOOLEAN ExtendedRateIeExist; */ + BOOLEAN LegacyBssExist; + UCHAR Erp; + CHAR RealRssi; + + UCHAR NewChannel; + CF_PARM CfParm; + USHORT AtimWin; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen, ExtRateLen; + UCHAR CkipFlag; + UCHAR AironetCellPowerLimit; + EDCA_PARM EdcaParm; + QBSS_LOAD_PARM QbssLoad; + QOS_CAPABILITY_PARM QosCapability; + ULONG RalinkIe; +/* UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 */ + UCHAR *VarIE = NULL; + USHORT LenVIE; + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; +/* HT_CAPABILITY_IE HtCapability; */ +/* ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE */ + HT_CAPABILITY_IE *pHtCapability = NULL; + ADD_HT_INFO_IE *pAddHtInfo = NULL; /* AP might use this additional ht info IE */ + UCHAR HtCapabilityLen; + UCHAR AddHtInfoLen; + UCHAR NewExtChannelOffset = 0xff; + UCHAR MaxSupportedRate = 0; +#ifdef CONFIG_STA_SUPPORT + UCHAR pPreNHtCapabilityLen = 0; +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef MESH_SUPPORT + UCHAR HostName[MAX_HOST_NAME_LEN] = {0}; + UCHAR HostNameLen = 0; + UCHAR MeshId[MAX_MESH_ID_LEN] = {0}; + UCHAR MeshIdLen = 0; + MESH_CONFIGURAION_IE MeshConfig = {0}; +#endif /* MESH_SUPPORT */ + EXT_CAP_INFO_ELEMENT ExtCapInfo; +#ifdef APCLI_SUPPORT + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; +#endif /* APCLI_SUPPORT */ + + /* 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; + } + os_alloc_mem(NULL, (UCHAR **)&pHtCapability, sizeof(HT_CAPABILITY_IE)); + if (pHtCapability == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + os_alloc_mem(NULL, (UCHAR **)&pAddHtInfo, sizeof(ADD_HT_INFO_IE)); + if (pAddHtInfo == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + os_alloc_mem(NULL, (UCHAR **)&Ssid, MAX_LEN_OF_SSID); + if (Ssid == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + + + /* init */ + RTMPZeroMemory(pHtCapability, sizeof(HT_CAPABILITY_IE)); + RTMPZeroMemory(pAddHtInfo, sizeof(ADD_HT_INFO_IE)); + + /* Init Variable IE structure */ + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + pRates = (PUCHAR)Rates; + + 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, + Addr2, + Bssid, + 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 + &pPreNHtCapabilityLen, +#endif /* CONFIG_STA_SUPPORT */ + pHtCapability, + &ExtCapInfo, + &AddHtInfoLen, + pAddHtInfo, + &NewExtChannelOffset, + &LenVIE, + pVIE)) + { +#ifdef MESH_SUPPORT + MeshPeerBeaconAndProbeSanity(pAd, Elem->Msg, Elem->MsgLen, HostName, &HostNameLen, MeshId, &MeshIdLen, &MeshConfig); + if(MESH_ON(pAd) && (MeshIdLen != 0)) + { + /*PMAC_TABLE_ENTRY pEntry = MacTableLookup(pAd, Addr2); */ + ULONG LinkIdx; + /*UCHAR MeshEncrypType = ENCRYPT_OPEN_NONE; */ + + /*MeshEncrypType = MeshCheckPeerMpCipher(CapabilityInfo, (PUCHAR)pVIE, LenVIE); */ + + InsertNeighborMP(pAd, RealRssi, Bssid, Channel, (UINT8)pAddHtInfo->AddHtInfo.RecomWidth, + (UINT8)pAddHtInfo->AddHtInfo.ExtChanOffset, HostName, MeshId, MeshIdLen, CapabilityInfo, (PUCHAR)pVIE, LenVIE, &MeshConfig); + + LinkIdx = GetMeshLinkId(pAd, (PCHAR)Addr2); + if(VALID_MESH_LINK_ID(LinkIdx)) + { + ULONG Now; + NdisGetSystemUpTime(&Now); + pAd->MeshTab.MeshLink[LinkIdx].Entry.LastBeaconTime = Now; + pAd->MeshTab.MeshLink[LinkIdx].Entry.OneSecBeaconCount++; + } + } +#endif /* MESH_SUPPORT */ + + /* ignore BEACON not in this channel */ + if (Channel != pAd->CommonCfg.Channel +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + && (pAd->CommonCfg.bOverlapScanning == FALSE) +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ +#ifdef P2P_SUPPORT + && (!P2P_CLI_ON(pAd)) +#endif /* P2P_SUPPORT */ + ) + { + goto __End_Of_APPeerBeaconAction; + } + +#ifdef IDS_SUPPORT + /* Conflict SSID detection */ + RTMPConflictSsidDetection(pAd, (PUCHAR)Ssid, SsidLen, (CHAR)Elem->Rssi0, (CHAR)Elem->Rssi1, (CHAR)Elem->Rssi2); +#endif /* IDS_SUPPORT */ + + +#ifdef DOT11_N_SUPPORT + /* 40Mhz BSS Width Trigger events Intolerant devices */ + if ((RealRssi > OBSS_BEACON_RSSI_THRESHOLD) && (pHtCapability->HtCapInfo.Forty_Mhz_Intolerant)) /* || (HtCapabilityLen == 0))) */ + { + Handle_BSS_Width_Trigger_Events(pAd); + } +#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) + { +#ifdef P2P_SUPPORT + if(OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED) && P2P_CLI_ON(pAd)) + { + if (Channel != pAd->CommonCfg.Channel) + { + DBGPRINT(RT_DEBUG_INFO, ("Channel=%d is not equal as CommonCfg.Channel = %d.\n", Channel, pAd->CommonCfg.Channel)); +// goto __End_Of_APPeerBeaconAction; + } + } + else +#endif /* P2P_SUPPORT */ + if (((pAd->CommonCfg.CentralChannel+2) != Channel) && + ((pAd->CommonCfg.CentralChannel-2) != 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 (Channel != pAd->CommonCfg.Channel) + goto __End_Of_APPeerBeaconAction; + } + } +#endif /* DOT11_N_SUPPORT */ + + SupportRate(SupRate, SupRateLen, ExtRate, ExtRateLen, &pRates, &RatesLen, &MaxSupportedRate); + + if ((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) + && (HtCapabilityLen == 0) && (RealRssi > OBSS_BEACON_RSSI_THRESHOLD)) + { + + pAd->ApCfg.LastNoneHTOLBCDetectTime = pAd->Mlme.Now32; + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef APCLI_SUPPORT + if (Elem->Wcid < MaxWcidNum) + { + PMAC_TABLE_ENTRY pEntry = NULL; + + pEntry = &pAd->MacTab.Content[Elem->Wcid]; + + if (pEntry && IS_ENTRY_APCLI(pEntry) && (pEntry->MatchAPCLITabIdx < MAX_APCLI_NUM)) + { + pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].ApCliRcvBeaconTime = pAd->Mlme.Now32; + + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + /* Check if root-ap change BW to 20 */ + if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_NONE) && (pAddHtInfo->AddHtInfo.RecomWidth == 0)) + { +#ifdef MAC_REPEATER_SUPPORT + UINT ifIndex; + UCHAR CliIdx; + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; +#endif /* MAC_REPEATER_SUPPORT */ + + pEntry->HTPhyMode.field.BW = 0; +#ifdef MAC_REPEATER_SUPPORT + ifIndex = pEntry->MatchAPCLITabIdx; + + 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)) + { + pEntry = &pAd->MacTab.Content[pReptEntry->MacTabWCID]; + if (pEntry) + pEntry->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 ((pAddHtInfo->AddHtInfo.ExtChanOffset != EXTCHA_NONE) && (HtCapabilityLen > 0) + && (pHtCapability->HtCapInfo.ChannelWidth == 1)) + { +#ifdef MAC_REPEATER_SUPPORT + UINT ifIndex; + UCHAR CliIdx; + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; +#endif /* MAC_REPEATER_SUPPORT */ + + pEntry->HTPhyMode.field.BW = 1; + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = pEntry->MatchAPCLITabIdx; + + 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)) + { + pEntry = &pAd->MacTab.Content[pReptEntry->MacTabWCID]; + if (pEntry) + pEntry->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; + } + } + } +#endif /* APCLI_CERT_SUPPORT */ + } + } + +#ifdef P2P_SUPPORT + if (P2P_CLI_ON(pAd) && + (ApCliWaitProbRsp(pAd, 0) == TRUE) && + (NdisEqualMemory(pAd->ApCfg.ApCliTab[0].CfgApCliBssid, Bssid, MAC_ADDR_LEN))) + { + MlmeEnqueue(pAd, APCLI_SYNC_STATE_MACHINE, APCLI_MT2_PEER_BEACON, Elem->MsgLen, Elem->Msg, 0); + } + else + { + PeerP2pBeacon(pAd, Addr2, Elem, TimeStamp); + if(MessageToMe) + { + MiniportMMRequest(pAd, 0, (PUCHAR)&pAd->ApCfg.ApCliTab[0].PsPollFrame, sizeof(PSPOLL_FRAME)); + } + } +#endif /* P2P_SUPPORT */ +#endif /* APCLI_SUPPORT */ + +#ifdef WDS_SUPPORT + do + { + PMAC_TABLE_ENTRY pEntry; + BOOLEAN bWmmCapable; + + /* check BEACON does in WDS TABLE. */ + pEntry = WdsTableLookup(pAd, Addr2, FALSE); + bWmmCapable = EdcaParm.bValid ? TRUE : FALSE; + + if (pEntry) + { + WdsPeerBeaconProc(pAd, pEntry, CapabilityInfo, MaxSupportedRate, RatesLen, bWmmCapable, RalinkIe, pHtCapability, HtCapabilityLen); + } + } while(FALSE); +#endif /* WDS_SUPPORT */ + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (pAd->CommonCfg.bOverlapScanning == TRUE) + { + INT index,secChIdx; + BOOLEAN found = FALSE; + ADD_HTINFO *pAdd_HtInfo; + + for (index = 0; index < pAd->ChannelListNum; index++) + { + /* found the effected channel, mark that. */ + if(pAd->ChannelList[index].Channel == Channel) + { + secChIdx = -1; + if (HtCapabilityLen > 0 && 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 = &pAddHtInfo->AddHtInfo; + if (pAdd_HtInfo->ExtChanOffset == EXTCHA_BELOW) + { +#ifdef A_BAND_SUPPORT + if (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 (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 != 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++; + } + + found = TRUE; + } + } + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + } + /* sanity check fail, ignore this frame */ + +__End_Of_APPeerBeaconAction: +/*#ifdef AUTO_CH_SELECT_ENHANCE */ +#ifdef CONFIG_AP_SUPPORT +IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +{ + if (Channel == pAd->ApCfg.AutoChannel_Channel) + { + if (AutoChBssSearchWithSSID(pAd, Bssid, (PUCHAR)Ssid, SsidLen, Channel) == BSS_NOT_FOUND) + pAd->pChannelInfo->ApCnt[pAd->ApCfg.current_channel_index]++; + AutoChBssInsertEntry(pAd, Bssid, Ssid, SsidLen, Channel, NewExtChannelOffset, RealRssi); + } +} +#endif /* CONFIG_AP_SUPPORT */ +/*#endif // AUTO_CH_SELECT_ENHANCE */ + +LabelErr: + 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 (Ssid != NULL) + os_free_mem(NULL, Ssid); + + return; +} + +#ifdef AP_SCAN_SUPPORT +/* + ========================================================================== + Description: + ========================================================================== + */ +VOID APInvalidStateWhenScan( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ +#ifdef MESH_SUPPORT + MlmeEnqueue(pAd, MESH_CTRL_STATE_MACHINE, APMT2_MLME_SCAN_ABORT, 0, NULL, 0); +#endif /* MESH_SUPPORT */ + 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( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + pAd->MlmeAux.Channel = NextChannel(pAd, pAd->MlmeAux.Channel); +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* + iwpriv set auto channel selection + update the current index of the channel + */ + if (pAd->ApCfg.bAutoChannelAtBootup == TRUE) + { + /* update current channel info */ + UpdateChannelInfo(pAd, pAd->ApCfg.current_channel_index, pAd->ApCfg.AutoChannelAlg); + + /* move to next channel */ + pAd->ApCfg.current_channel_index++; + if (pAd->ApCfg.current_channel_index < pAd->ChannelListNum) + { + pAd->ApCfg.AutoChannel_Channel = pAd->ChannelList[pAd->ApCfg.current_channel_index].Channel; + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + ScanNextChannel(pAd, OPMODE_AP); +} + +#ifdef CON_WPS +VOID APMlmeScanCompleteAction( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + BOOLEAN Cancelled; + UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType, BBPValue = 0; + ULONG Now; + + /* Suspend MSDU transmission here */ + RTMPSuspendMsduTransmission(pAd); + + /* first check the parameter sanity */ + if (MlmeScanReqSanity(pAd, Elem->Msg, Elem->MsgLen, &BssType, (PCHAR)Ssid, &SsidLen, &ScanType)) + { +#ifdef DOT11_N_SUPPORT +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPEnable == TRUE) + RTMP_CHIP_DISABLE_AP_MIMOPS(pAd); +#endif /* GREENAP_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("AP SYNC - MlmeScanReqAction\n")); + NdisGetSystemUpTime(&Now); + pAd->ApCfg.LastScanTime = Now; + + 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 */ + pAd->MlmeAux.Channel = FirstChannel(pAd); + + if ((pAd->ApCfg.bImprovedScan) && (pAd->Mlme.ApSyncMachine.CurrState == AP_SCAN_PENDING)) + pAd->MlmeAux.Channel = pAd->ApCfg.LastScanChannel; + + /* Let BBP register at 20MHz to do scan */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + 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; + } + } +#endif /* CONFIG_AP_SUPPORT */ + ScanNextChannel(pAd, OPMODE_AP); + } + 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( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; + UCHAR /* Ssid[MAX_LEN_OF_SSID], */ BssType, Channel=0, NewChannel, + SsidLen=0, DtimCount, DtimPeriod, BcastFlag, MessageToMe; + UCHAR *Ssid = NULL; + CF_PARM CfParm; + USHORT BeaconPeriod, AtimWin, CapabilityInfo; + PFRAME_802_11 pFrame; + LARGE_INTEGER TimeStamp; + UCHAR Erp; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen, ExtRateLen; + UCHAR CkipFlag; + UCHAR AironetCellPowerLimit; + EDCA_PARM EdcaParm; + QBSS_LOAD_PARM QbssLoad; + QOS_CAPABILITY_PARM QosCapability; + ULONG RalinkIe; +/* UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 */ + UCHAR *VarIE = NULL; + USHORT LenVIE; + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; +/* + HT_CAPABILITY_IE HtCapability; + ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE +*/ + HT_CAPABILITY_IE *pHtCapability = NULL; + ADD_HT_INFO_IE *pAddHtInfo = NULL; /* AP might use this additional ht info IE */ + UCHAR HtCapabilityLen; + UCHAR AddHtInfoLen; + UCHAR NewExtChannelOffset = 0xff; + CHAR RealRssi = -127; +#ifdef CONFIG_STA_SUPPORT + UCHAR pPreNHtCapabilityLen = 0; +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef MESH_SUPPORT + UCHAR HostName[MAX_HOST_NAME_LEN] = {0}; + UCHAR HostNameLen = 0; + UCHAR MeshId[MAX_MESH_ID_LEN] = {0}; + UCHAR MeshIdLen = 0; + MESH_CONFIGURAION_IE MeshConfig = {0}; +#endif /* MESH_SUPPORT */ + EXT_CAP_INFO_ELEMENT ExtCapInfo; + + + /* 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; + } + os_alloc_mem(NULL, (UCHAR **)&pHtCapability, sizeof(HT_CAPABILITY_IE)); + if (pHtCapability == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + os_alloc_mem(NULL, (UCHAR **)&pAddHtInfo, sizeof(ADD_HT_INFO_IE)); + if (pAddHtInfo == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + os_alloc_mem(NULL, (UCHAR **)&Ssid, MAX_LEN_OF_SSID); + if (Ssid == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + + SsidLen = 0; + + RTMPZeroMemory(pHtCapability, sizeof(HT_CAPABILITY_IE)); + RTMPZeroMemory(pAddHtInfo, sizeof(ADD_HT_INFO_IE)); + + 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, + 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 + &pPreNHtCapabilityLen, +#endif /* CONFIG_STA_SUPPORT */ + pHtCapability, + &ExtCapInfo, + &AddHtInfoLen, + pAddHtInfo, + &NewExtChannelOffset, + &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)); + +#ifdef MESH_SUPPORT + MeshPeerBeaconAndProbeSanity(pAd, Elem->Msg, Elem->MsgLen, HostName, &HostNameLen, MeshId, &MeshIdLen, &MeshConfig); + if(MESH_ON(pAd) && (MeshIdLen != 0)) + { + /*PMAC_TABLE_ENTRY pEntry = MacTableLookup(pAd, Addr2); */ + ULONG LinkIdx; + /*UCHAR MeshEncrypType = ENCRYPT_OPEN_NONE; */ + + /*MeshEncrypType = MeshCheckPeerMpCipher(CapabilityInfo, (PUCHAR)pVIE, LenVIE); */ + + InsertNeighborMP(pAd, RealRssi, Bssid, Channel, (UINT8)pAddHtInfo->AddHtInfo.RecomWidth, + (UINT8)pAddHtInfo->AddHtInfo.ExtChanOffset, HostName, MeshId, MeshIdLen, CapabilityInfo, (PUCHAR)pVIE, LenVIE, &MeshConfig); + + LinkIdx = GetMeshLinkId(pAd, (PCHAR)Addr2); + if(VALID_MESH_LINK_ID(LinkIdx)) + { + ULONG Now; + NdisGetSystemUpTime(&Now); + pAd->MeshTab.MeshLink[LinkIdx].Entry.LastBeaconTime = Now; + } + } +#endif /* MESH_SUPPORT */ +#ifdef P2P_SUPPORT + MlmeEnqueue(pAd, P2P_DISC_STATE_MACHINE, P2P_DISC_PEER_PROB_RSP, Elem->MsgLen, Elem->Msg, Channel); +#endif /* P2P_SUPPORT */ + + + /* ignore BEACON not in this channel */ + if (Channel != pAd->MlmeAux.Channel +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + && (pAd->CommonCfg.bOverlapScanning == FALSE) +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + ) + { + goto __End_Of_APPeerBeaconAtScanAction; + } + +#ifdef DOT11_N_SUPPORT + if ((RealRssi > OBSS_BEACON_RSSI_THRESHOLD) && (pHtCapability->HtCapInfo.Forty_Mhz_Intolerant)) /* || (HtCapabilityLen == 0))) */ + { + Handle_BSS_Width_Trigger_Events(pAd); + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef IDS_SUPPORT + /* Conflict SSID detection */ + if (Channel == pAd->CommonCfg.Channel) + RTMPConflictSsidDetection(pAd, Ssid, 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, Bssid, 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, Bssid, (PCHAR)Ssid, SsidLen, BssType, BeaconPeriod, + &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, pHtCapability, + pAddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag, + &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE); +#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) + && ((Channel > 0) && (Channel <= 14))) + { + int chListIdx; + + /* + First we find the channel list idx by the channel number + */ + for (chListIdx = 0; chListIdx < pAd->ChannelListNum; chListIdx++) + { + if (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, Bssid, pHtCapability, HtCapabilityLen, RegClass, 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); + } + } + + /* sanity check fail, ignored */ +__End_Of_APPeerBeaconAtScanAction: + /*scan beacon in pastive */ +#ifdef CONFIG_AP_SUPPORT +IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +{ + if (Channel == pAd->ApCfg.AutoChannel_Channel) + { + if (AutoChBssSearchWithSSID(pAd, Bssid, (PUCHAR)Ssid, SsidLen, Channel) == BSS_NOT_FOUND) + pAd->pChannelInfo->ApCnt[pAd->ApCfg.current_channel_index]++; + + AutoChBssInsertEntry(pAd, Bssid, (CHAR *)Ssid, SsidLen, Channel, NewExtChannelOffset, RealRssi); + } +} +#endif /* CONFIG_AP_SUPPORT */ + +LabelErr: + 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 (Ssid != NULL) + os_free_mem(NULL, Ssid); +} + +/* + ========================================================================== + Description: + MLME Cancel the SCAN req state machine procedure + ========================================================================== + */ +VOID APScanCnclAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + BOOLEAN Cancelled; + + RTMPCancelTimer(&pAd->MlmeAux.APScanTimer, &Cancelled); + pAd->MlmeAux.Channel = 0; + ScanNextChannel(pAd, OPMODE_AP); + + 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; + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + /* + * Still scanning, ignore this scanning. + */ + DBGPRINT(RT_DEBUG_TRACE, ("ApSiteSurvey:: Scanning now\n")); + return; + } + + AsicDisableSync(pAd); + + BssTableInit(&pAd->ScanTab); + 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); +} + +BOOLEAN ApScanRunning( + IN PRTMP_ADAPTER pAd) +{ + return (pAd->Mlme.ApSyncMachine.CurrState == AP_SCAN_LISTEN) ? TRUE : 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( + IN PRTMP_ADAPTER pAd) +{ + int i=0; + UCHAR regclass = 0; + + do + { + if (reg_class[i].spacing == pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth) + { + 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; + pIE->ChannelSwitchCount = pAd->Dot11_H.CSCount; +} +#endif /* DOT11_N_SUPPORT */ + diff --git a/mt7620/src/ap/ap_wds.c b/mt7620/src/ap/ap_wds.c new file mode 100644 index 0000000..8f0bb2e --- /dev/null +++ b/mt7620/src/ap/ap_wds.c @@ -0,0 +1,1441 @@ + +/* + *************************************************************************** + * 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 +*/ + +#ifdef WDS_SUPPORT + +#include "rt_config.h" + + +#define VAILD_KEY_INDEX( _X ) ((((_X) >= 0) && ((_X) < 4)) ? (TRUE) : (FALSE)) + + +/*extern INT rt28xx_ioctl(PNET_DEV net_dev, struct ifreq *rq, int cmd); */ + + +BOOLEAN ApWdsAllowToSendPacket( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + OUT UCHAR *pWcid) +{ + UCHAR wdsIndex; + BOOLEAN allowed; + + /*DBGPRINT(RT_DEBUG_TRACE, ("ApCliAllowToSendPacket():Packet to ApCli interface!\n")); */ + wdsIndex = RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_WDS; + if (ValidWdsEntry(pAd, wdsIndex)) + { + /* 3. send out the packet. b7 as WDS bit, b0-6 as WDS index when b7==1 */ + + *pWcid = (UCHAR)pAd->WdsTab.WdsEntry[wdsIndex].MacTabMatchWCID; + /*RTMP_SET_PACKET_WCID(pPacket, pAd->WdsTab.WdsEntry[wdsIndex].MacTabMatchWCID); // to all WDS links. */ + + allowed = TRUE; + } + else + { + allowed = FALSE; + } + + return allowed; +} + + +LONG WdsEntryAlloc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR 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; + } + } + + if (i == MAX_WDS_ENTRY) + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unable to allocate WdsEntry.\n", __FUNCTION__)); + + NdisReleaseSpinLock(&pAd->WdsTabLock); + + return WdsTabIdx; +} + +VOID WdsEntryDel( + IN PRTMP_ADAPTER pAd, + IN PUCHAR 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; + + + MacTableDeleteEntry(pAd, wcid, pAddr); + + return TRUE; +} + +/* +================================================================ +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 PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + UINT WdsTabIdx) +{ + PMAC_TABLE_ENTRY pEntry = NULL; + HTTRANSMIT_SETTING HTPhyMode; + + /* if FULL, return */ + if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE) + return NULL; + + if((pEntry = WdsTableLookup(pAd, pAddr, TRUE)) != NULL) + return pEntry; + + /* allocate one WDS entry */ + do + { + /* allocate one MAC entry */ + pEntry = MacTableInsertEntry(pAd, pAddr, (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 (pAd->WdsTab.WdsEntry[WdsTabIdx].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 = pAd->WdsTab.WdsEntry[WdsTabIdx].HTPhyMode.field.ShortGI; + HTPhyMode.field.BW = pAd->WdsTab.WdsEntry[WdsTabIdx].HTPhyMode.field.BW; + HTPhyMode.field.STBC = pAd->WdsTab.WdsEntry[WdsTabIdx].HTPhyMode.field.STBC; + HTPhyMode.field.MODE = MODE_HTMIX; + pEntry->RateLen = 12; + break; + + case MODE_HTGREENFIELD: + HTPhyMode.field.MCS = 7; + HTPhyMode.field.ShortGI = pAd->WdsTab.WdsEntry[WdsTabIdx].HTPhyMode.field.ShortGI; + HTPhyMode.field.BW = pAd->WdsTab.WdsEntry[WdsTabIdx].HTPhyMode.field.BW; + HTPhyMode.field.STBC = pAd->WdsTab.WdsEntry[WdsTabIdx].HTPhyMode.field.STBC; + HTPhyMode.field.MODE = MODE_HTGREENFIELD; + pEntry->RateLen = 12; + break; +#endif /* DOT11_N_SUPPORT */ + + default: + break; + } + + pEntry->MaxHTPhyMode.word = HTPhyMode.word; + pEntry->MinHTPhyMode.word = pAd->WdsTab.WdsEntry[WdsTabIdx].MinHTPhyMode.word; + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + +#ifdef DOT11_N_SUPPORT + if (pAd->WdsTab.WdsEntry[WdsTabIdx].PhyMode >= MODE_HTMIX) + { + if (pAd->WdsTab.WdsEntry[WdsTabIdx].DesiredTransmitSetting.field.MCS != MCS_AUTO) + { + DBGPRINT(RT_DEBUG_TRACE, ("IF-wds%d : Desired MCS = %d\n", WdsTabIdx, + pAd->WdsTab.WdsEntry[WdsTabIdx].DesiredTransmitSetting.field.MCS)); + + if (pAd->WdsTab.WdsEntry[WdsTabIdx].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->WdsTab.WdsEntry[WdsTabIdx].HTPhyMode.field.MCS) + { + /* STA supports fixed MCS */ + pEntry->MaxHTPhyMode.field.MCS = pAd->WdsTab.WdsEntry[WdsTabIdx].HTPhyMode.field.MCS; + } + } + + pEntry->MmpsMode = MMPS_ENABLE; + 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); + } +#endif /* DOT11_N_SUPPORT */ + else + { + NdisZeroMemory(&pEntry->HTCapability, sizeof(HT_CAPABILITY_IE)); + } + + /*if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */ + if (pAd->WdsTab.WdsEntry[WdsTabIdx].bAutoTxRateSwitch == FALSE) + { + pEntry->HTPhyMode.field.MCS = pAd->WdsTab.WdsEntry[WdsTabIdx].DesiredTransmitSetting.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + /* If the legacy mode is set, overwrite the transmit setting of this entry. */ + RTMPUpdateLegacyTxSetting((UCHAR)pAd->WdsTab.WdsEntry[WdsTabIdx].DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + else + { + pEntry->bAutoTxRateSwitch = TRUE; + } + + pAd->WdsTab.WdsEntry[WdsTabIdx].MacTabMatchWCID = (UCHAR)pEntry->Aid; + pEntry->MatchWDSTabIdx = WdsTabIdx; + + AsicUpdateWdsEncryption(pAd, pEntry->Aid); + + DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertWDSEntry - allocate entry #%d, Total= %d\n",WdsTabIdx, pAd->MacTab.Size)); + break; + } + }while(FALSE); + + return pEntry; +} + +MAC_TABLE_ENTRY *WdsTableLookupByWcid( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount) +{ + /*USHORT HashIdx; */ + ULONG WdsIndex; + PMAC_TABLE_ENTRY pCurEntry = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + + if (wcid <=0 || wcid >= MAX_LEN_OF_MAC_TABLE ) + return NULL; + + NdisAcquireSpinLock(&pAd->WdsTabLock); + NdisAcquireSpinLock(&pAd->MacTabLock); + + do + { + /*HashIdx = MAC_ADDR_HASH_INDEX(pAddr); */ + /*pCurEntry = pAd->MacTab.Hash[wcid]; */ + pCurEntry = &pAd->MacTab.Content[wcid]; + + WdsIndex = 0xff; + if ((pCurEntry) && IS_ENTRY_WDS(pCurEntry)) + { + WdsIndex = pCurEntry->MatchWDSTabIdx; + } + + 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( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount) +{ + USHORT HashIdx; + PMAC_TABLE_ENTRY pEntry = NULL; + + NdisAcquireSpinLock(&pAd->WdsTabLock); + NdisAcquireSpinLock(&pAd->MacTabLock); + + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + pEntry = pAd->MacTab.Hash[HashIdx]; + + while (pEntry) + { + if (IS_ENTRY_WDS(pEntry) && MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) + { + if(bResetIdelCount) + pEntry->NoDataIdleCount = 0; + break; + } + else + pEntry = pEntry->pNext; + } + + NdisReleaseSpinLock(&pAd->MacTabLock); + NdisReleaseSpinLock(&pAd->WdsTabLock); + + return pEntry; +} + +MAC_TABLE_ENTRY *FindWdsEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN PUCHAR 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].PhyMode == 0xff) + pAd->WdsTab.WdsEntry[WdsIdx].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, + &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 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 WdsTableMaintenance( + IN PRTMP_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", + pEntry->Addr[0],pEntry->Addr[1],pEntry->Addr[2],pEntry->Addr[3], + pEntry->Addr[4],pEntry->Addr[5], idx, MAC_TABLE_AGEOUT_TIME)); + WdsEntryDel(pAd, pEntry->Addr); + MacTableDeleteWDSEntry(pAd, pEntry->Aid, pEntry->Addr); + } + } + +} + + +VOID RT28xx_WDS_Close( + IN PRTMP_ADAPTER pAd) +{ + UINT index; + + for(index = 0; index < MAX_WDS_ENTRY; index++) + { + if (pAd->WdsTab.WdsEntry[index].dev) + RtmpOSNetDevClose(pAd->WdsTab.WdsEntry[index].dev); + } + return; +} + + + +VOID WdsDown( + IN PRTMP_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( + IN PRTMP_ADAPTER pAd) +{ + UINT index; + MAC_TABLE_ENTRY *pEntry = NULL; + + for(index = 0; index < MAX_WDS_ENTRY; index++) + { + if (pAd->WdsTab.WdsEntry[index].Valid != TRUE) + continue; + + pEntry = MacTableInsertWDSEntry(pAd, pAd->WdsTab.WdsEntry[index].PeerWdsAddr, index); + + RTMPSetSupportMCS(pAd, + OPMODE_AP, + pEntry, + pAd->CommonCfg.SupRate, + pAd->CommonCfg.SupRateLen, + pAd->CommonCfg.ExtRate, + pAd->CommonCfg.ExtRateLen, + &pAd->CommonCfg.HtCapability, + sizeof(pAd->CommonCfg.HtCapability)); + + switch (pAd->WdsTab.WdsEntry[index].PhyMode) + { + case 0xff: /* user doesn't specific a Mode for WDS link. */ + 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 */ + + default: + break; + } + } + + return; +} + +VOID AsicUpdateWdsEncryption( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid) +{ + UINT WdsIdex; + PMAC_TABLE_ENTRY pEntry = NULL; + + do + { + if (wcid >= MAX_LEN_OF_MAC_TABLE) + break; + + pEntry = &pAd->MacTab.Content[wcid]; + if (pAd->WdsTab.WdsEntry[pEntry->MatchWDSTabIdx].Valid != TRUE) + break; + + if (!IS_ENTRY_WDS(pEntry)) + break; + + WdsIdex = pEntry->MatchWDSTabIdx; + + if (((pAd->WdsTab.WdsEntry[WdsIdex].WepStatus == Ndis802_11Encryption1Enabled) || + (pAd->WdsTab.WdsEntry[WdsIdex].WepStatus == Ndis802_11Encryption2Enabled) || + (pAd->WdsTab.WdsEntry[WdsIdex].WepStatus == Ndis802_11Encryption3Enabled)) + && (pAd->WdsTab.WdsEntry[WdsIdex].WdsKey.KeyLen > 0)) + { + + INT DefaultKeyId = 0; + + if (pAd->WdsTab.WdsEntry[WdsIdex].WepStatus == Ndis802_11Encryption1Enabled) + DefaultKeyId = pAd->WdsTab.WdsEntry[pEntry->MatchWDSTabIdx].KeyIdx; + + if (!VAILD_KEY_INDEX(DefaultKeyId)) + break; + + /* Update key into Asic Pairwise key table */ + RTMP_ASIC_PAIRWISE_KEY_TABLE( + pAd, + pEntry->Aid, + &pAd->WdsTab.WdsEntry[pEntry->MatchWDSTabIdx].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, + pAd->WdsTab.WdsEntry[pEntry->MatchWDSTabIdx].WdsKey.CipherAlg, + pEntry->Aid, + 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, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen) +{ + UCHAR MaxSupportedRate = RATE_11; + + 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; + } + + 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; + } + 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->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; +#endif /* DOT11_N_SUPPORT */ + 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); + + 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) + && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + UCHAR j, bitmask;/*k,bitmask; */ + CHAR i; + + if ((pHtCapability->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 ((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 (i=15; i>=0; i--) */ + for (i=23; i>=0; i--) + { + j = i/8; + bitmask = (1<<(i-(j*8))); + if ((pAd->WdsTab.WdsEntry[pEntry->MatchWDSTabIdx].DesiredHtPhyInfo.MCSSet[j] & bitmask) && (pHtCapability->MCSSet[j] & bitmask)) + { + pEntry->MaxHTPhyMode.field.MCS = i; + break; + } + if (i==0) + break; + } + + if ((pEntry->MaxHTPhyMode.field.MCS > pAd->WdsTab.WdsEntry[pEntry->MatchWDSTabIdx].HTPhyMode.field.MCS) && (pAd->WdsTab.WdsEntry[pEntry->MatchWDSTabIdx].HTPhyMode.field.MCS != MCS_AUTO)) + pEntry->MaxHTPhyMode.field.MCS = pAd->WdsTab.WdsEntry[pEntry->MatchWDSTabIdx].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); + if (pHtCapability->ExtHtCapInfo.MCSFeedback == 0x03) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); + + NdisMoveMemory(&pEntry->HTCapability, pHtCapability, sizeof(HT_CAPABILITY_IE)); + } + else + { + NdisZeroMemory(&pEntry->HTCapability, sizeof(HT_CAPABILITY_IE)); + pAd->MacTab.fAnyStationIsLegacy = TRUE; + } +#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 */ + + default: + break; + } + } +} + +VOID APWdsInitialize( + IN PRTMP_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].PhyMode = 0xff; + pAd->WdsTab.WdsEntry[i].Valid = FALSE; + pAd->WdsTab.WdsEntry[i].MacTabMatchWCID = 0; + pAd->WdsTab.WdsEntry[i].WepStatus = Ndis802_11EncryptionDisabled; + pAd->WdsTab.WdsEntry[i].KeyIdx = 0; + NdisZeroMemory(&pAd->WdsTab.WdsEntry[i].WdsKey, sizeof(CIPHER_KEY)); + + pAd->WdsTab.WdsEntry[i].bAutoTxRateSwitch = TRUE; + pAd->WdsTab.WdsEntry[i].DesiredTransmitSetting.field.MCS = MCS_AUTO; + } + return; +} + +INT Show_WdsTable_Proc( + IN PRTMP_ADAPTER pAd, + IN 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].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.RxSwReadIdx, + pAd->RxRing.RxCpuIdx, + pAd->RxRing.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->MatchWDSTabIdx)); + 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", GetPhyMode(pEntry->HTPhyMode.field.MODE))); + DBGPRINT(RT_DEBUG_OFF, ("%-6s", GetBW(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\n", pEntry->HTPhyMode.field.STBC)); + } + } + + return TRUE; +} + +VOID rtmp_read_wds_from_file( + IN PRTMP_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; + + /*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++) + { + if ((strncmp(macptr, "CCK", 3) == 0) || (strncmp(macptr, "cck", 3) == 0)) + pAd->WdsTab.WdsEntry[i].PhyMode = MODE_CCK; + else if ((strncmp(macptr, "OFDM", 4) == 0) || (strncmp(macptr, "ofdm", 4) == 0)) + pAd->WdsTab.WdsEntry[i].PhyMode = MODE_OFDM; +#ifdef DOT11_N_SUPPORT + else if ((strncmp(macptr, "HTMIX", 5) == 0) || (strncmp(macptr, "htmix", 5) == 0)) + pAd->WdsTab.WdsEntry[i].PhyMode = MODE_HTMIX; + else if ((strncmp(macptr, "GREENFIELD", 10) == 0) || (strncmp(macptr, "greenfield", 10) == 0)) + pAd->WdsTab.WdsEntry[i].PhyMode = MODE_HTGREENFIELD; +#endif /* DOT11_N_SUPPORT */ + else + pAd->WdsTab.WdsEntry[i].PhyMode = 0xff; + + DBGPRINT(RT_DEBUG_TRACE, ("If/wds%d - WdsPhyMode=%d\n", i, pAd->WdsTab.WdsEntry[i].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].WepStatus = Ndis802_11WEPDisabled; + else if ((strncmp(macptr, "WEP", 3) == 0) || (strncmp(macptr, "wep", 3) == 0)) + pAd->WdsTab.WdsEntry[i].WepStatus = Ndis802_11WEPEnabled; + else if ((strncmp(macptr, "TKIP", 4) == 0) || (strncmp(macptr, "tkip", 4) == 0)) + pAd->WdsTab.WdsEntry[i].WepStatus = Ndis802_11Encryption2Enabled; + else if ((strncmp(macptr, "AES", 3) == 0) || (strncmp(macptr, "aes", 3) == 0)) + pAd->WdsTab.WdsEntry[i].WepStatus = Ndis802_11Encryption3Enabled; + else + pAd->WdsTab.WdsEntry[i].WepStatus = Ndis802_11WEPDisabled; + + DBGPRINT(RT_DEBUG_TRACE, ("WdsEncrypType[%d]=%d(%s)\n", i, pAd->WdsTab.WdsEntry[i].WepStatus, GetEncryptType(pAd->WdsTab.WdsEntry[i].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++) + { + pAd->WdsTab.WdsEntry[j].WepStatus = pAd->WdsTab.WdsEntry[0].WepStatus; + DBGPRINT(RT_DEBUG_TRACE, ("@WdsEncrypType[%d]=%d(%s)\n", j, pAd->WdsTab.WdsEntry[i].WepStatus, GetEncryptType(pAd->WdsTab.WdsEntry[i].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; + + /* check if the wds-0 link key material is valid */ + if (((pAd->WdsTab.WdsEntry[0].WepStatus == Ndis802_11Encryption2Enabled) + || (pAd->WdsTab.WdsEntry[0].WepStatus == Ndis802_11Encryption3Enabled)) + && (strlen(tmpbuf) >= 8) && (strlen(tmpbuf) <= 64)) + { + RT_CfgSetWPAPSKKey(pAd, tmpbuf, strlen(tmpbuf), (PUCHAR)RALINK_PASSPHRASE, sizeof(RALINK_PASSPHRASE), keyMaterial); + if (pAd->WdsTab.WdsEntry[0].WepStatus == Ndis802_11Encryption3Enabled) + pAd->WdsTab.WdsEntry[0].WdsKey.CipherAlg = CIPHER_AES; + else + pAd->WdsTab.WdsEntry[0].WdsKey.CipherAlg = CIPHER_TKIP; + + NdisMoveMemory(&pAd->WdsTab.WdsEntry[0].WdsKey.Key, keyMaterial, 16); + pAd->WdsTab.WdsEntry[0].WdsKey.KeyLen = 16; + NdisMoveMemory(&pAd->WdsTab.WdsEntry[0].WdsKey.RxMic, keyMaterial+16, 8); + NdisMoveMemory(&pAd->WdsTab.WdsEntry[0].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); + + /* WdsXKey (X=0~MAX_WDS_ENTRY-1) */ + if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, FALSE)) + { + if (pAd->WdsTab.WdsEntry[i].WepStatus == Ndis802_11Encryption1Enabled) + { + /* Ascii type */ + if (strlen(tmpbuf) == 5 || strlen(tmpbuf) == 13) + { + KeyLen = strlen(tmpbuf); + pAd->WdsTab.WdsEntry[i].WdsKey.KeyLen = KeyLen; + NdisMoveMemory(pAd->WdsTab.WdsEntry[i].WdsKey.Key, tmpbuf, KeyLen); + if (KeyLen == 5) + CipherAlg = CIPHER_WEP64; + else + CipherAlg = CIPHER_WEP128; + + pAd->WdsTab.WdsEntry[i].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); + pAd->WdsTab.WdsEntry[i].WdsKey.KeyLen = KeyLen / 2; + AtoH(tmpbuf, pAd->WdsTab.WdsEntry[i].WdsKey.Key, KeyLen / 2); + if (KeyLen == 10) + CipherAlg = CIPHER_WEP64; + else + CipherAlg = CIPHER_WEP128; + + pAd->WdsTab.WdsEntry[i].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 + { + pAd->WdsTab.WdsEntry[i].WepStatus = Ndis802_11EncryptionDisabled; + NdisZeroMemory(&pAd->WdsTab.WdsEntry[i].WdsKey, sizeof(CIPHER_KEY)); + DBGPRINT(RT_DEBUG_TRACE, ("IF/wds%d has invalid key for WEP, reset encryption to OPEN\n", i)); + } + } + else if ((pAd->WdsTab.WdsEntry[i].WepStatus == Ndis802_11Encryption2Enabled) + || (pAd->WdsTab.WdsEntry[i].WepStatus == Ndis802_11Encryption3Enabled)) + { + if ((strlen(tmpbuf) >= 8) && (strlen(tmpbuf) <= 64)) + { + RT_CfgSetWPAPSKKey(pAd, tmpbuf, strlen(tmpbuf), (PUCHAR) RALINK_PASSPHRASE, sizeof(RALINK_PASSPHRASE), keyMaterial); + if (pAd->WdsTab.WdsEntry[i].WepStatus == Ndis802_11Encryption3Enabled) + pAd->WdsTab.WdsEntry[i].WdsKey.CipherAlg = CIPHER_AES; + else + pAd->WdsTab.WdsEntry[i].WdsKey.CipherAlg = CIPHER_TKIP; + + NdisMoveMemory(&pAd->WdsTab.WdsEntry[i].WdsKey.Key, keyMaterial, 16); + pAd->WdsTab.WdsEntry[i].WdsKey.KeyLen = 16; + NdisMoveMemory(&pAd->WdsTab.WdsEntry[i].WdsKey.RxMic, keyMaterial+16, 8); + NdisMoveMemory(&pAd->WdsTab.WdsEntry[i].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)); + pAd->WdsTab.WdsEntry[i].WepStatus = Ndis802_11EncryptionDisabled; + NdisZeroMemory(&pAd->WdsTab.WdsEntry[i].WdsKey, sizeof(CIPHER_KEY)); + } + + } + else + { + pAd->WdsTab.WdsEntry[i].WepStatus = Ndis802_11EncryptionDisabled; + NdisZeroMemory(&pAd->WdsTab.WdsEntry[i].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++) + { + KeyIdx = (UCHAR) simple_strtol(macptr, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + pAd->WdsTab.WdsEntry[i].KeyIdx = (UCHAR) (KeyIdx - 1); + else + pAd->WdsTab.WdsEntry[i].KeyIdx = 0; + + if ((pAd->WdsTab.WdsEntry[i].WepStatus == Ndis802_11Encryption2Enabled) + || (pAd->WdsTab.WdsEntry[i].WepStatus == Ndis802_11Encryption3Enabled)) + pAd->WdsTab.WdsEntry[i].KeyIdx = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("IF/wds%d - WdsDefaultKeyID(0~3)=%d\n", i, pAd->WdsTab.WdsEntry[i].KeyIdx)); + } + } + + /* WdsTxMode */ + if (RTMPGetKeyParameter("WdsTxMode", tmpbuf, 25, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_WDS_ENTRY); macptr = rstrtok(NULL,";"), i++) + { + pWdsEntry = &pAd->WdsTab.WdsEntry[i]; + + pWdsEntry->DesiredTransmitSetting.field.FixedTxMode = + RT_CfgSetFixedTxPhyMode(macptr); + DBGPRINT(RT_DEBUG_TRACE, ("I/F(wds%d) Tx Mode = %d\n", i, + pWdsEntry->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++) + { + pWdsEntry = &pAd->WdsTab.WdsEntry[i]; + + pWdsEntry->DesiredTransmitSetting.field.MCS = + RT_CfgSetTxMCSProc(macptr, &pWdsEntry->bAutoTxRateSwitch); + + if (pWdsEntry->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, + pWdsEntry->DesiredTransmitSetting.field.MCS)); + } + } + } + + /*WdsEnable */ + if(RTMPGetKeyParameter("WdsEnable", tmpbuf, 10, buffer, TRUE)) + { + RT_802_11_WDS_ENTRY *pWdsEntry; + switch(simple_strtol(tmpbuf, 0, 10)) + { + case 2: /* Bridge mode, DisAllow association(stop Beacon generation and Probe Req. */ + pAd->WdsTab.Mode = WDS_BRIDGE_MODE; + break; + case 1: + case 3: /* Repeater mode */ + pAd->WdsTab.Mode = WDS_REPEATER_MODE; + break; + case 4: /* 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) + { + pAd->WdsTab.WdsEntry[i].WepStatus = pAd->WdsTab.WdsEntry[0].WepStatus; + pAd->WdsTab.WdsEntry[i].KeyIdx = pAd->WdsTab.WdsEntry[0].KeyIdx; + NdisMoveMemory(&pAd->WdsTab.WdsEntry[i].WdsKey, &pAd->WdsTab.WdsEntry[0].WdsKey, sizeof(CIPHER_KEY)); + } + } + pAd->WdsTab.Mode = WDS_LAZY_MODE; + break; + case 0: /* 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].VLAN_VID = simple_strtol(macptr, 0, 10); + pAd->WdsTab.WdsEntry[i].VLAN_Priority = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("If/wds%d - WdsVlanId=%d\n", i, pAd->WdsTab.WdsEntry[i].VLAN_VID)); + } + } +#endif /* WDS_VLAN_SUPPORT */ +} + +VOID WdsPrepareWepKeyFromMainBss( + IN PRTMP_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].WepStatus == Ndis802_11Encryption1Enabled && + pAd->WdsTab.WdsEntry[i].WdsKey.KeyLen == 0) + { + UCHAR main_bss_keyid = pAd->ApCfg.MBSSID[MAIN_MBSSID].DefaultKeyId; + + if (pAd->ApCfg.MBSSID[MAIN_MBSSID].WepStatus == Ndis802_11Encryption1Enabled && + (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].WepStatus = Ndis802_11EncryptionDisabled; + NdisZeroMemory(&pAd->WdsTab.WdsEntry[i].WdsKey, sizeof(CIPHER_KEY)); + } + } + } + +} + + +VOID WDS_Init( + IN PRTMP_ADAPTER pAd, + IN 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; +#ifdef MULTIPLE_CARD_SUPPORT + MC_RowID = pAd->MC_RowID; +#endif /* MULTIPLE_CARD_SUPPORT */ +#ifdef HOSTAPD_SUPPORT + IoctlIF = pAd->IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + pWdsNetDev = RtmpOSNetDevCreate(MC_RowID, &IoctlIF, INT_WDS, index, sizeof(PRTMP_ADAPTER), INF_WDS_DEV_NAME); +#ifdef HOSTAPD_SUPPORT + pAd->IoctlIF = IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + if (pWdsNetDev == NULL) + { + /* allocation fail, exit */ + DBGPRINT(RT_DEBUG_ERROR, ("Allocate network device fail (WDS)...\n")); + break; + } + else + { + PMAC_TABLE_ENTRY pWdsEntry; + pWdsEntry = &pAd->MacTab.Content[pAd->WdsTab.WdsEntry[index].MacTabMatchWCID]; + DBGPRINT(RT_DEBUG_TRACE, ("The new WDS interface MAC = %02X:%02X:%02X:%02X:%02X:%02X\n", + PRINT_MAC(pWdsEntry->Addr))); + } + + NdisZeroMemory(&pAd->WdsTab.WdsEntry[index].WdsCounter, sizeof(WDS_COUNTER)); + RTMP_OS_NETDEV_SET_PRIV(pWdsNetDev, pAd); + pAd->WdsTab.WdsEntry[index].PhyMode = 0xff; + pAd->WdsTab.WdsEntry[index].dev = pWdsNetDev; + + + pNetDevOps->priv_flags = INT_WDS; /* we are virtual interface */ + pNetDevOps->needProtcted = TRUE; + + /* Register this device */ + RtmpOSNetDevAttach(pAd->OpMode, pWdsNetDev, pNetDevOps); + + pAd->WdsTab.WdsEntry[index].PhyMode = 0xff; + pAd->WdsTab.WdsEntry[index].dev = pWdsNetDev; + } + + pAd->flg_wds_init = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("Total Allocate %d WDS interfaces!\n", index)); + +} + + +int WDS_PacketSend( + IN PNDIS_PACKET pSkb, + IN PNET_DEV dev, + IN RTMP_NET_PACKET_TRANSMIT Func) +{ + UCHAR i; + RTMP_ADAPTER *pAd; + PNDIS_PACKET pPacket = (PNDIS_PACKET) pSkb; + + pAd = (PRTMP_ADAPTER) RTMP_OS_NETDEV_GET_PRIV(dev); + + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return 0; + } +#endif /* RALINK_ATE */ + + if ((RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return 0; + } + + if (!(RTMP_OS_NETDEV_STATE_RUNNING(dev))) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return 0; + } + + for (i = 0; i < MAX_WDS_ENTRY; i++) + { + if (ValidWdsEntry(pAd, i) && (pAd->WdsTab.WdsEntry[i].dev == dev)) + { + RTMP_SET_PACKET_NET_DEVICE_WDS(pSkb, i); + SET_OS_PKT_NETDEV(pSkb, pAd->net_dev); + + return Func(pSkb); + } + } + + + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + + return 0; +} + + +VOID WDS_Remove( + IN PRTMP_ADAPTER pAd) +{ + UINT index; + + for(index = 0; index < MAX_WDS_ENTRY; index++) + { + if (pAd->WdsTab.WdsEntry[index].dev) + { + RtmpOSNetDevDetach(pAd->WdsTab.WdsEntry[index].dev); + RtmpOSNetDevFree(pAd->WdsTab.WdsEntry[index].dev); + + /* Clear it as NULL to prevent latter access error. */ + pAd->WdsTab.WdsEntry[index].dev = NULL; + } + } +} + + +BOOLEAN WDS_StatsGet( + IN PRTMP_ADAPTER pAd, + IN RT_CMD_STATS *pStats) +{ + INT WDS_apidx = 0,index; + + + /*struct net_device_stats stats; */ + for(index = 0; index < MAX_WDS_ENTRY; index++) + { + if (pAd->WdsTab.WdsEntry[index].dev == pStats->pNetDev) + { + WDS_apidx = index; + + break; + } + } + + if(index >= MAX_WDS_ENTRY) + { + DBGPRINT(RT_DEBUG_ERROR, ("rt28xx_ioctl can not find wds I/F\n")); + return FALSE; + } + + pStats->pStats = pAd->stats; + + pStats->rx_packets = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.ReceivedFragmentCount.QuadPart; + pStats->tx_packets = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.TransmittedFragmentCount.QuadPart; + + pStats->rx_bytes = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.ReceivedByteCount; + pStats->tx_bytes = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.TransmittedByteCount; + + pStats->rx_errors = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.RxErrors; + pStats->tx_errors = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.TxErrors; + + pStats->multicast = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.MulticastReceivedFrameCount.QuadPart; /* multicast packets received */ + pStats->collisions = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.OneCollision + pAd->WdsTab.WdsEntry[index].WdsCounter.MoreCollisions; /* Collision packets */ + + pStats->rx_over_errors = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.RxNoBuffer; /* receiver ring buff overflow */ + pStats->rx_crc_errors = 0;/*pAd->WlanCounters.FCSErrorCount; // recved pkt with crc error */ + pStats->rx_frame_errors = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.RcvAlignmentErrors; /* recv'd frame alignment error */ + pStats->rx_fifo_errors = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.RxNoBuffer; /* recv'r fifo overrun */ + + return TRUE; +} + +#endif /* WDS_SUPPORT */ + diff --git a/mt7620/src/ap/ap_wds_inf.c b/mt7620/src/ap/ap_wds_inf.c new file mode 100644 index 0000000..a668525 --- /dev/null +++ b/mt7620/src/ap/ap_wds_inf.c @@ -0,0 +1,156 @@ + +/* + *************************************************************************** + * 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" + +NET_DEV_STATS *RT28xx_get_wds_ether_stats( + IN PNET_DEV net_dev); + + +/* Register WDS interface */ +VOID RT28xx_WDS_Init( + IN VOID *pAd, + IN 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 = WdsVirtualIFSendPackets; + netDevOpHook.ioctl = WdsVirtualIF_ioctl; + netDevOpHook.get_stats = RT28xx_get_wds_ether_stats; + 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 WdsVirtualIFSendPackets( + IN PNDIS_PACKET pPktSrc, + IN PNET_DEV pDev) +{ + + + MEM_DBG_PKT_ALLOC_INC(pPktSrc); + + if(!(RTMP_OS_NETDEV_STATE_RUNNING(pDev))) + { + /* the interface is down */ + RELEASE_NDIS_PACKET(NULL, pPktSrc, NDIS_STATUS_FAILURE); + return 0; + } /* End of if */ + + return WDS_PacketSend(pPktSrc, pDev, rt28xx_packet_xmit); +} + + +INT WdsVirtualIF_open( + IN PNET_DEV dev) +{ + VOID *pAd; +#ifdef RTL865X_SOC + INT index; + unsigned int linkid; +#endif + + 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( + IN 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; +} + + +INT WdsVirtualIF_ioctl( + IN PNET_DEV net_dev, + IN OUT VOID *rq, + IN INT cmd) +{ + VOID *pAd = RTMP_OS_NETDEV_GET_PRIV(net_dev); /*RTMP_OS_NETDEV_GET_PRIV(pVirtualAd->RtmpDev); */ + +/* 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, ("VirtualIF_ioctl(%s)::Network is down!\n", RTMP_OS_NETDEV_GET_DEVNAME(net_dev))); + return -ENETDOWN; + } + + return rt28xx_ioctl(net_dev, rq, cmd); +} + + +VOID RT28xx_WDS_Remove( + IN VOID *pAd) +{ + + RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_WDS_REMOVE, 0, NULL, 0); +} + +#endif /* WDS_SUPPORT */ diff --git a/mt7620/src/ap/ap_wpa.c b/mt7620/src/ap/ap_wpa.c new file mode 100644 index 0000000..2733b19 --- /dev/null +++ b/mt7620/src/ap/ap_wpa.c @@ -0,0 +1,1720 @@ +/* + *************************************************************************** + * 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( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid) +{ + + MAC_TABLE_ENTRY *pEntry = (MAC_TABLE_ENTRY*)NULL; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + +/* *Privacy = Ndis802_11PrivFilterAcceptAll; */ +/* *WpaState = AS_NOTUSE; */ + + if (Wcid < MaxWcidNum) + { + pEntry = &(pAd->MacTab.Content[Wcid]); + + /*if (IS_ENTRY_CLIENT(&pAd->MacTab.Content[Wcid])) */ + + /*ASSERT(IS_ENTRY_CLIENT(&pAd->MacTab.Content[Wcid])); */ + /*ASSERT(pEntry->Sst == SST_ASSOC); */ + +/* *Privacy = pEntry->PrivacyFilter; */ +/* *WpaState = pEntry->WpaState; */ + } + + 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; + + + ASSERT(pEntry); + ASSERT(pEntry->apidx < pAd->ApCfg.BssidNum); + + apidx = pEntry->apidx; + + pEntry->AuthMode = pAd->ApCfg.MBSSID[apidx].AuthMode; + + if (eid_ptr->Len >= 6) + { + /* WPA and WPA2 format not the same in RSN_IE */ + if (eid_ptr->Eid == IE_WPA) + { + if (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1WPA2) + pEntry->AuthMode = Ndis802_11AuthModeWPA; + else if (pAd->ApCfg.MBSSID[apidx].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 ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1WPA2) || + (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) + IE_Idx = 1; + + if (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1WPA2) + pEntry->AuthMode = Ndis802_11AuthModeWPA2; + else if (pAd->ApCfg.MBSSID[apidx].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; + + ASSERT(pEntry); + ASSERT(pEntry->apidx < pAd->ApCfg.BssidNum); + + apidx = pEntry->apidx; + + pEntry->WepStatus = pAd->ApCfg.MBSSID[apidx].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 (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11Encryption4Enabled) + {/* multiple cipher (TKIP/CCMP) */ + + while (Count > 0) + { + /* TKIP */ + if (MIX_CIPHER_WPA_TKIP_ON(pAd->ApCfg.MBSSID[apidx].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_11Encryption2Enabled; + 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(pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher)) + { + if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][16], 4)) + { + pEntry->WepStatus = Ndis802_11Encryption3Enabled; + return TRUE; + } + } + } + else + { + /* AES */ + if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][12], 4)) + { + pEntry->WepStatus = Ndis802_11Encryption3Enabled; + 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 ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1WPA2) || (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) + IE_Idx = 1; + + if (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11Encryption4Enabled) + {/* multiple cipher (TKIP/CCMP) */ + + while (Count > 0) + { + /* WPA2 TKIP */ + if (MIX_CIPHER_WPA2_TKIP_ON(pAd->ApCfg.MBSSID[apidx].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_11Encryption2Enabled; + 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(pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher)) + { + if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][12], 4)) + { + pEntry->WepStatus = Ndis802_11Encryption3Enabled; + return TRUE; + } + } + } + else + { + /* AES */ + if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][8], 4)) + { + pEntry->WepStatus = Ndis802_11Encryption3Enabled; + 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].AuthMode == Ndis802_11AuthModeWPA1WPA2) || + (pAd->ApCfg.MBSSID[apidx].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; + } + + 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_11Encryption1Enabled) + CipherAlg = CIPHER_WEP64; + else if (pEntry->WepStatus == Ndis802_11Encryption2Enabled) + CipherAlg = CIPHER_TKIP; + else if (pEntry->WepStatus == Ndis802_11Encryption3Enabled) + 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( + IN PRTMP_ADAPTER pAd, + IN 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].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 + 1)) + { + /* 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); + RTMPSetTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV); + } + } + /* 3. 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); + } + /* 4. 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); + } + /* 4. 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 = (PRTMP_ADAPTER)pEntry->pAd; + + if (pEntry->MatchAPCLITabIdx < MAX_APCLI_NUM) + { + UCHAR ifIndex = pEntry->MatchAPCLITabIdx; + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) ApCli interface[%d] startdown.\n", __FUNCTION__, ifIndex)); +#ifdef MAC_REPEATER_SUPPORT + if ( (pAd->ApCfg.bMACRepeaterEn == TRUE) && (pEntry->bReptCli)) + ifIndex = (64 + ifIndex*MAX_EXT_MAC_ADDR_SIZE + pEntry->MatchReptCliIdx); +#endif /* MAC_REPEATER_SUPPORT */ + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, ifIndex); +#ifdef MAC_REPEATER_SUPPORT + if ( (pAd->ApCfg.bMACRepeaterEn == TRUE) && (pEntry->bReptCli)) + { + RTMP_MLME_HANDLER(pAd); + RTMPRemoveRepeaterEntry(pAd, pEntry->MatchAPCLITabIdx, pEntry->MatchReptCliIdx); + } +#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; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext; + PRALINK_TIMER_STRUCT pTimer = (PRALINK_TIMER_STRUCT) SystemSpecific3; + PMULTISSID_STRUCT pMbss = NULL; + + + 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]; + + if (pMbss->AuthMode < Ndis802_11AuthModeWPA || + pMbss->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 */ + pMbss->DefaultKeyId = (pMbss->DefaultKeyId == 1) ? 2 : 1; + + /* Generate GNonce randomly */ + GenRandom(pAd, pMbss->Bssid, pMbss->GNonce); + + /* Update GTK */ + WpaDeriveGTK(pMbss->GMK, + (UCHAR*)pMbss->GNonce, + pMbss->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)) + { + pEntry->GTKState = REKEY_NEGOTIATING; + + WPAStart2WayGroupHS(pAd, pEntry); + DBGPRINT(RT_DEBUG_TRACE, ("Rekey interval excess, Update Group Key for %x %x %x %x %x %x , DefaultKeyId= %x \n",\ + pEntry->Addr[0],pEntry->Addr[1],\ + pEntry->Addr[2],pEntry->Addr[3],\ + pEntry->Addr[4],pEntry->Addr[5],\ + pMbss->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, + pMbss->GroupKeyWepStatus, + apidx, + pMbss->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( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR pPacket, + IN 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].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].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", + pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], 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", + pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], 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", + pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], 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", + pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], 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 */ + +VOID RTMPGetTxTscFromAsic( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx, + OUT PUCHAR 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; + /* Read IVEIV from Asic */ + offset = MAC_IVEIV_TABLE_BASE + (Wcid * HW_IVEIV_ENTRY_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].GroupKeyWepStatus == Ndis802_11Encryption3Enabled) + { /* 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))); + + +} + +/* + ========================================================================== + 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]; + + if ((pMbss->WepStatus == Ndis802_11Encryption2Enabled) || + (pMbss->WepStatus == Ndis802_11Encryption3Enabled) || + (pMbss->WepStatus == Ndis802_11Encryption4Enabled)) + { + /* 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", + pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5])); + } + + + 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].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_11Encryption2Enabled) + { + 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].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", + DA[0], DA[1], DA[2], DA[3], DA[4], DA[5])); + + 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_11Encryption3Enabled) + { + 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_11Encryption3Enabled) + { + 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].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_11Encryption3Enabled) + { + 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",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); + return etherbuf; +} +#endif /* HOSTAPD_SUPPORT */ + + +#ifdef APCLI_SUPPORT +#ifdef APCLI_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->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, pMacEntry, + Header802_3, LENGTH_802_3, (PUCHAR)&Packet, 4, TRUE); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WpaSendEapolStart\n")); +} + +#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 ApcliWpaCheckEapCode( + IN PRTMP_ADAPTER pAd, + IN PUCHAR 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 /* APCLI_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->ApCliMlmeAux.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; + //PULONG pCurrState = &pAd->ApCfg.ApCliTab[0].CtrlCurrState; + + 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->ApCliMlmeAux.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/mt7620/src/ap/apcli_assoc.c b/mt7620/src/ap/apcli_assoc.c new file mode 100644 index 0000000..70e71cb --- /dev/null +++ b/mt7620/src/ap/apcli_assoc.c @@ -0,0 +1,1172 @@ +/* + *************************************************************************** + * 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; + PREPEATER_CLIENT_ENTRY pReptCliEntry = NULL; +#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].ApCliMlmeAux.ApCliAssocTimer, + GET_TIMER_FUNCTION(ApCliAssocTimeout), pAd, FALSE); + + RTMPInitTimer(pAd, &pAd->ApCfg.ApCliTab[i].ApCliMlmeAux.WpaDisassocAndBlockAssocTimer, + GET_TIMER_FUNCTION(ApCliWpaDisassocApAndBlockAssoc), pAd, FALSE); + +#ifdef MAC_REPEATER_SUPPORT + for (j = 0; j < MAX_EXT_MAC_ADDR_SIZE; j++) + { + pReptCliEntry = &pAd->ApCfg.ApCliTab[i].RepeaterCli[j]; + + pReptCliEntry->pAd = pAd; + pReptCliEntry->MatchApCliIdx = i; + pReptCliEntry->MatchLinkIdx = j; + pReptCliEntry->AssocCurrState = APCLI_ASSOC_IDLE; + + /* timer init */ + RTMPInitTimer(pAd, &pReptCliEntry->ApCliAssocTimer, GET_TIMER_FUNCTION(ApCliAssocTimeoutExt), pReptCliEntry, 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; + PAPCLI_STRUCT pApCliEntry = NULL; +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + USHORT VarIesOffset = 0; +#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ + UCHAR RSNIe = IE_WPA; +#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; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + /* Block all authentication request durning WPA block period */ + if (pApCliEntry->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(&pAd->ApCliMlmeAux.ApCliAssocTimer, &Cancelled); +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].ApCliAssocTimer, &Cancelled); + else +#endif /* MAC_REPEATER_SUPPORT */ + RTMPCancelTimer(&pApCliEntry->ApCliMlmeAux.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_ERROR, ("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; + } + +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + pApCliEntry->AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); + pApCliEntry->AssocInfo.AvailableRequestFixedIEs = + NDIS_802_11_AI_REQFI_CAPABILITIES | NDIS_802_11_AI_REQFI_LISTENINTERVAL; + pApCliEntry->AssocInfo.RequestFixedIEs.Capabilities = CapabilityInfo; + pApCliEntry->AssocInfo.RequestFixedIEs.ListenInterval = ListenIntv; + pApCliEntry->AssocInfo.OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); + + NdisZeroMemory(pApCliEntry->ReqVarIEs, MAX_VIE_LEN); + /*First add SSID*/ + VarIesOffset = 0; + NdisMoveMemory(pApCliEntry->ReqVarIEs + VarIesOffset, &SsidIe, 1); + VarIesOffset += 1; + NdisMoveMemory(pApCliEntry->ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SsidLen, 1); + VarIesOffset += 1; + NdisMoveMemory(pApCliEntry->ReqVarIEs + VarIesOffset, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + VarIesOffset += pAd->MlmeAux.SsidLen; + + /*Second add Supported rates*/ + NdisMoveMemory(pApCliEntry->ReqVarIEs + VarIesOffset, &SupRateIe, 1); + VarIesOffset += 1; + NdisMoveMemory(pApCliEntry->ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SupRateLen, 1); + VarIesOffset += 1; + NdisMoveMemory(pApCliEntry->ReqVarIEs + VarIesOffset, pAd->MlmeAux.SupRate, pAd->MlmeAux.SupRateLen); + VarIesOffset += pAd->MlmeAux.SupRateLen; +#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ + + + 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, pAd->ApCfg.ApCliTab[ifIndex].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, &pApCliEntry->ApCliMlmeAux.SsidLen, + pApCliEntry->ApCliMlmeAux.SsidLen, pApCliEntry->ApCliMlmeAux.Ssid, + 1, &SupRateIe, + 1, &pApCliEntry->ApCliMlmeAux.SupRateLen, + pApCliEntry->ApCliMlmeAux.SupRateLen, pApCliEntry->ApCliMlmeAux.SupRate, + END_OF_ARGS); + + if(pApCliEntry->ApCliMlmeAux.ExtRateLen != 0) + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &pApCliEntry->ApCliMlmeAux.ExtRateLen, + pApCliEntry->ApCliMlmeAux.ExtRateLen, pApCliEntry->ApCliMlmeAux.ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + +#ifdef DOT11_N_SUPPORT + /* HT */ + if ((pApCliEntry->ApCliMlmeAux.HtCapabilityLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + ULONG TmpLen; + HT_CAPABILITY_IE HtCapabilityTmp; + + NdisZeroMemory(&HtCapabilityTmp, sizeof(HT_CAPABILITY_IE)); + NdisMoveMemory(&HtCapabilityTmp, &pApCliEntry->ApCliMlmeAux.HtCapability, pApCliEntry->ApCliMlmeAux.HtCapabilityLen); +#ifdef DOT11N_SS3_SUPPORT + HtCapabilityTmp.MCSSet[2] = (pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[2] & pApCliEntry->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, &pApCliEntry->ApCliMlmeAux.HtCapabilityLen, + pApCliEntry->ApCliMlmeAux.HtCapabilityLen, &HtCapabilityTmp, + END_OF_ARGS); + + FrameLen += TmpLen; + } + +#ifdef DOT11N_DRAFT3 +#ifdef APCLI_CERT_SUPPORT + if (pAd->bApCliCertTest == TRUE) + { + ULONG TmpLen; + EXT_CAP_INFO_ELEMENT extCapInfo; + UCHAR extInfoLen; + + extInfoLen = sizeof (EXT_CAP_INFO_ELEMENT); + NdisZeroMemory(&extCapInfo, extInfoLen); + + + if ((pAd->CommonCfg.bBssCoexEnable == TRUE) && + (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + && (pAd->CommonCfg.Channel <= 14) + ) + { + extCapInfo.BssCoexistMgmtSupport = 1; + DBGPRINT(RT_DEBUG_TRACE, ("%s: BssCoexistMgmtSupport = 1\n", __FUNCTION__)); + } + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &ExtCapIe, + 1, &extInfoLen, + extInfoLen, &extCapInfo, + END_OF_ARGS); + FrameLen += TmpLen; + } +#endif /* APCLI_CERT_SUPPORT */ +#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) && ((pApCliEntry->ApCliMlmeAux.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 (pApCliEntry->ApCliMlmeAux.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 (pApCliEntry->ApCliMlmeAux.APEdcaParm.bValid) + { + if (pApCliEntry->UapsdInfo.bAPSDCapable && + pApCliEntry->ApCliMlmeAux.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; + } + /* Append RSN_IE when WPAPSK OR WPA2PSK, */ + if (((pApCliEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || + (pApCliEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + || (pApCliEntry->AuthMode >= Ndis802_11AuthModeWPA) +#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ +#ifdef WSC_AP_SUPPORT + && ((pApCliEntry->WscControl.WscConfMode == WSC_DISABLE) || + ((pApCliEntry->WscControl.WscConfMode != WSC_DISABLE) && + !(pApCliEntry->WscControl.bWscTrigger + ))) +#endif /* WSC_AP_SUPPORT */ + ) + { + RSNIe = IE_WPA; + + if ((pApCliEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + ||(pApCliEntry->AuthMode == Ndis802_11AuthModeWPA2) +#endif/*APCLI_WPA_SUPPLICANT_SUPPORT*/ + ) + RSNIe = IE_WPA2; + + +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + if (pApCliEntry->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, &pApCliEntry->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 ((pApCliEntry->AuthMode == Ndis802_11AuthModeWPA2) && + (NdisEqualMemory(pAd->MlmeAux.Bssid, pAd->CommonCfg.LastBssid, MAC_ADDR_LEN))) + { + FoundPMK = FALSE; + } + + if (FoundPMK) + { + // Set PMK number + *(PUSHORT) &pApCliEntry->RSN_IE[pApCliEntry->RSNIE_Len] = 1; + NdisMoveMemory(&pApCliEntry->RSN_IE[pApCliEntry->RSNIE_Len + 2], &pApCliEntry->SavedPMK[idx].PMKID, 16); + pApCliEntry->RSNIE_Len += 18; + } + } + +#ifdef SIOCSIWGENIE + if ((pApCliEntry->WpaSupplicantUP & WPA_SUPPLICANT_ENABLE) && + (pApCliEntry->bRSN_IE_FromWpaSupplicant == TRUE)) + { + ; + } + else +#endif +#endif /*APCLI_WPA_SUPPLICANT_SUPPORT*/ + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &RSNIe, + 1, &pApCliEntry->RSNIE_Len, + pApCliEntry->RSNIE_Len, pApCliEntry->RSN_IE, + END_OF_ARGS); + + FrameLen += tmp; + } + + +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT +#ifdef SIOCSIWGENIE + if (((pApCliEntry->WpaSupplicantUP & 0x7F) != WPA_SUPPLICANT_ENABLE) || + (pApCliEntry->bRSN_IE_FromWpaSupplicant == FALSE)) +#endif + { + // Append Variable IE + NdisMoveMemory(pApCliEntry->ReqVarIEs + VarIesOffset, &RSNIe, 1); + VarIesOffset += 1; + NdisMoveMemory(pApCliEntry->ReqVarIEs + VarIesOffset, &pApCliEntry->RSNIE_Len, 1); + VarIesOffset += 1; + + NdisMoveMemory(pApCliEntry->ReqVarIEs + VarIesOffset, pApCliEntry->RSN_IE, pApCliEntry->RSNIE_Len); + VarIesOffset += pAd->ApCfg.ApCliTab[ifIndex].RSNIE_Len; + + // Set Variable IEs Length + pApCliEntry->ReqVarIELen = VarIesOffset; + } + +#ifdef SIOCSIWGENIE + if ((pApCliEntry->WpaSupplicantUP & WPA_SUPPLICANT_ENABLE) && + (pApCliEntry->bRSN_IE_FromWpaSupplicant == TRUE)) + { + ULONG TmpWpaAssocIeLen = 0; + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpWpaAssocIeLen, + pApCliEntry->WpaAssocIeLen, pApCliEntry->pWpaAssocIe, + END_OF_ARGS); + + FrameLen += TmpWpaAssocIeLen; + + NdisMoveMemory(pApCliEntry->ReqVarIEs + VarIesOffset, pApCliEntry->pWpaAssocIe, pApCliEntry->WpaAssocIeLen); + VarIesOffset += pApCliEntry->WpaAssocIeLen; + + // Set Variable IEs Length + pApCliEntry->ReqVarIELen = VarIesOffset; + } +#endif +#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ + +#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; + + os_alloc_mem(pAd, (UCHAR **) & pWscBuf, 512); +/* if( (pWscBuf = kmalloc(512, GFP_ATOMIC)) != NULL) */ + 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; +/* kfree(pWscBuf); */ + os_free_mem(NULL, pWscBuf); + } else + DBGPRINT(RT_DEBUG_WARN, + ("%s:: WscBuf Allocate failed!\n", + __FUNCTION__)); + } +#endif /* WSC_AP_SUPPORT */ + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + RTMPSetTimer(&pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].ApCliAssocTimer, Timeout); + else +#endif /* MAC_REPEATER_SUPPORT */ + RTMPSetTimer(&pApCliEntry->ApCliMlmeAux.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); + COPY_MAC_ADDR(DisassocHdr.Addr2, pDisassocReq->Addr2); + } +#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 APCLI_WPA_SUPPLICANT_SUPPORT + if (pAd->ApCfg.ApCliTab[ifIndex].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 /*APCLI_WPA_SUPPLICANT_SUPPORT*/ + 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); + 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; + + if (ApCliPeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen, + &HtCapability, &AddHtInfo, &HtCapabilityLen,&AddHtInfoLen,&NewExtChannelOffset, &EdcaParm, &CkipFlag)) + { + /* The frame is for me ? */ + if(MAC_ADDR_EQUAL(Addr2, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid)) + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - receive ASSOC_RSP to me (status=%d)\n", Status)); +#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].ApCliMlmeAux.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); + } + + 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")); + } + + 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); + 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; + + if(PeerDisassocSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason)) + { + if (MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, Addr2)) + { + *pCurrState = APCLI_ASSOC_IDLE; + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_PEER_DISCONNECT_REQ, 0, NULL, ifIndex); +#ifdef MAC_REPEATER_SUPPORT + if ((pAd->ApCfg.bMACRepeaterEn == TRUE) && (ifIndex >= 64)) + { + RTMP_MLME_HANDLER(pAd); + ifIndex = ((ifIndex - 64) / 16); + RTMPRemoveRepeaterEntry(pAd, ifIndex, CliIdx); + } +#endif /* MAC_REPEATER_SUPPORT */ + } + } + 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); + 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 - 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) +{ + PAPCLI_STRUCT pApCliEntry = NULL; + + if (IfIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[IfIndex]; + + pApCliEntry->ApCliMlmeAux.BssType = BSS_INFRA; + pApCliEntry->ApCliMlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; + NdisMoveMemory(&pApCliEntry->ApCliMlmeAux.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM)); + + /* filter out un-supported rates */ + pApCliEntry->ApCliMlmeAux.SupRateLen = SupRateLen; + NdisMoveMemory(pApCliEntry->ApCliMlmeAux.SupRate, SupRate, SupRateLen); + RTMPCheckRates(pAd, pApCliEntry->ApCliMlmeAux.SupRate, &(pApCliEntry->ApCliMlmeAux.SupRateLen)); + + /* filter out un-supported rates */ + pApCliEntry->ApCliMlmeAux.ExtRateLen = ExtRateLen; + NdisMoveMemory(pApCliEntry->ApCliMlmeAux.ExtRate, ExtRate, ExtRateLen); + RTMPCheckRates(pAd, pApCliEntry->ApCliMlmeAux.ExtRate, &(pApCliEntry->ApCliMlmeAux.ExtRateLen)); + + DBGPRINT(RT_DEBUG_TRACE, (HtCapabilityLen ? "%s===> 11n HT STA\n" : "%s===> legacy STA\n", __FUNCTION__)); + +#ifdef DOT11_N_SUPPORT + if (HtCapabilityLen > 0 && (pAd->CommonCfg.PhyMode > PHY_11ABGN_MIXED)) + { + ApCliCheckHt(pAd, IfIndex, pHtCapability, pAddHtInfo); + } +#endif /* DOT11_N_SUPPORT */ + +} + +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT +VOID ApcliSendAssocIEsToWpaSupplicant( + IN PRTMP_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 /*APCLI_WPA_SUPPLICANT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + diff --git a/mt7620/src/ap/apcli_auth.c b/mt7620/src/ap/apcli_auth.c new file mode 100644 index 0000000..24e2753 --- /dev/null +++ b/mt7620/src/ap/apcli_auth.c @@ -0,0 +1,876 @@ +/* + *************************************************************************** + * 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 + -------- ---------- ---------------------------------------------- + Fonchi 2006-6-23 modified for rt61-APClinent +*/ + +#ifdef APCLI_SUPPORT + +#include "rt_config.h" + +static VOID ApCliAuthTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +#ifdef MAC_REPEATER_SUPPORT +static VOID ApCliAuthTimeoutExt( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif /* MAC_REPEATER_SUPPORT */ + +static VOID ApCliMlmeAuthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliPeerAuthRspAtSeq2Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliPeerAuthRspAtSeq4Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliPeerDeauthAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliAuthTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliInvalidStateWhenAuth( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliMlmeDeauthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +DECLARE_TIMER_FUNCTION(ApCliAuthTimeout); +BUILD_TIMER_FUNCTION(ApCliAuthTimeout); +#ifdef MAC_REPEATER_SUPPORT +DECLARE_TIMER_FUNCTION(ApCliAuthTimeoutExt); +BUILD_TIMER_FUNCTION(ApCliAuthTimeoutExt); +#endif /* MAC_REPEATER_SUPPORT */ + +/* + ========================================================================== + 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 PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + UCHAR i; +#ifdef MAC_REPEATER_SUPPORT + UCHAR j; + PREPEATER_CLIENT_ENTRY pReptCliEntry = NULL; +#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].ApCliMlmeAux.ApCliAuthTimer, GET_TIMER_FUNCTION(ApCliAuthTimeout), pAd, FALSE); + +#ifdef MAC_REPEATER_SUPPORT + for (j = 0; j < MAX_EXT_MAC_ADDR_SIZE; j++) + { + pReptCliEntry = &pAd->ApCfg.ApCliTab[i].RepeaterCli[j]; + + pReptCliEntry->pAd = pAd; + pReptCliEntry->MatchApCliIdx = i; + pReptCliEntry->MatchLinkIdx = j; + pReptCliEntry->AuthCurrState = APCLI_AUTH_REQ_IDLE; + + /* timer init */ + RTMPInitTimer(pAd, &pReptCliEntry->ApCliAuthTimer, GET_TIMER_FUNCTION(ApCliAuthTimeoutExt), pReptCliEntry, FALSE); + } +#endif /* MAC_REPEATER_SUPPORT */ + } + + return; +} + +/* + ========================================================================== + 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, ("APCLI AUTH - AuthTimeout\n")); + + 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].ApCliMlmeAux.ApCliAuthTimer, &Cancelled); + + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Alg = Alg; + + Seq = 1; + Status = MLME_SUCCESS; + + /* allocate and send out AuthReq frame */ + NState = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + 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].ApCliMlmeAux.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); + + 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].ApCliMlmeAux.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( + IN PRTMP_ADAPTER pAd, + IN 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; +#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; + + /* 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(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.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(&pAd->ApCfg.ApCliTab[ifIndex].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(&pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.ApCliAuthTimer, &Cancelled); + } + + if(Status == MLME_SUCCESS) + { + if(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.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 = pAd->ApCfg.ApCliTab[ifIndex].DefaultKeyId; + + pKey = &pAd->ApCfg.ApCliTab[ifIndex].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, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, ifIndex); + AuthHdr.FC.Wep = 1; +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + COPY_MAC_ADDR(AuthHdr.Addr2, pAd->ApCfg.ApCliTab[ifIndex].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(&pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].ApCliAuthTimer, AUTH_TIMEOUT); + else +#endif /* MAC_REPEATER_SUPPORT */ + RTMPSetTimer(&pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.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( + IN PRTMP_ADAPTER pAd, + IN 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].ApCliMlmeAux.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].ApCliMlmeAux.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( + IN PRTMP_ADAPTER pAd, + IN 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 APCLI_WPA_SUPPLICANT_SUPPORT + PMAC_TABLE_ENTRY pMacEntry = NULL; +#endif /*APCLI_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 APCLI_WPA_SUPPLICANT_SUPPORT + pMacEntry = &pAd->MacTab.Content[pAd->ApCfg.ApCliTab[ifIndex].MacTabWCID]; + if (!pMacEntry || !IS_ENTRY_APCLI(pMacEntry)) + { + return; + } +#endif /*APCLI_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 APCLI_WPA_SUPPLICANT_SUPPORT + if ((pAd->ApCfg.ApCliTab[ifIndex].WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) && + (pAd->ApCfg.ApCliTab[ifIndex].AuthMode == Ndis802_11AuthModeWPA2) + &&(pMacEntry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + pAd->ApCfg.ApCliTab[ifIndex].bLostAp = TRUE; + } +#endif /*APCLI_WPA_SUPPLICANT_SUPPORT*/ + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_PEER_DISCONNECT_REQ, 0, NULL, ifIndex); +#ifdef MAC_REPEATER_SUPPORT + if ((pAd->ApCfg.bMACRepeaterEn == TRUE) && (ifIndex >= 64)) + { + RTMP_MLME_HANDLER(pAd); + ifIndex = ((ifIndex - 64) / 16); + RTMPRemoveRepeaterEntry(pAd, ifIndex, CliIdx); + } +#endif /* MAC_REPEATER_SUPPORT */ + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH_RSP - ApCliPeerDeauthAction() sanity check fail\n")); + } + + return; +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +static VOID ApCliAuthTimeoutAction( + 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 */ + + 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( + 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].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 - ApCliMlmeDeAuthReqAction (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); + COPY_MAC_ADDR(DeauthHdr.Addr2, pDeauthReq->Addr2); + } +#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; +} + +#endif /* APCLI_SUPPORT */ + diff --git a/mt7620/src/ap/apcli_ctrl.c b/mt7620/src/ap/apcli_ctrl.c new file mode 100644 index 0000000..f20194b --- /dev/null +++ b/mt7620/src/ap/apcli_ctrl.c @@ -0,0 +1,1751 @@ +/* + *************************************************************************** + * 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" + +#ifdef MAC_REPEATER_SUPPORT +static VOID ReptCliConnectTimeoutReset( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif /* MAC_REPEATER_SUPPORT */ + +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 MAC_REPEATER_SUPPORT +DECLARE_TIMER_FUNCTION(ReptCliConnectTimeoutReset); +BUILD_TIMER_FUNCTION(ReptCliConnectTimeoutReset); +#endif /* MAC_REPEATER_SUPPORT */ + +/* + ========================================================================== + 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; + PREPEATER_CLIENT_ENTRY pReptCliEntry = NULL; +#endif /* MAC_REPEATER_SUPPORT */ + + 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 */ + 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++) + { + pReptCliEntry = &pAd->ApCfg.ApCliTab[i].RepeaterCli[j]; + + pReptCliEntry->pAd = pAd; + pReptCliEntry->MatchApCliIdx = i; + pReptCliEntry->MatchLinkIdx = j; + pReptCliEntry->CtrlCurrState = APCLI_CTRL_DISCONNECTED; + pReptCliEntry->CliConnectState = 0; + + /* timer init */ + RTMPInitTimer(pAd, &pAd->ApCfg.ApCliTab[i].RepeaterCli[j].ReptCliResetTimer, + GET_TIMER_FUNCTION(ReptCliConnectTimeoutReset), &pAd->ApCfg.ApCliTab[i].RepeaterCli[j], FALSE); + } +#endif /* MAC_REPEATER_SUPPORT */ + } + + 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 ReptCliConnectTimeoutReset( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PREPEATER_CLIENT_ENTRY pEntry = (PREPEATER_CLIENT_ENTRY)FunctionContext; + PRTMP_ADAPTER pAd; + USHORT HashIdx; + REPEATER_CLIENT_ENTRY *pPrevEntry, *pProbeEntry; + REPEATER_CLIENT_ENTRY_MAP *pMapEntry, *pPrevMapEntry, *pProbeMapEntry; + + DBGPRINT(RT_DEBUG_TRACE, ("Repeater Cli Auth Timeout Reset Entry \n")); + + pAd = pEntry->pAd; + + DBGPRINT(RT_DEBUG_ERROR, (" (%s) ifIndex = %d, CliIdx = %d !!!\n", + __FUNCTION__, pEntry->MatchApCliIdx, pEntry->MatchLinkIdx)); + + RTMPRemoveRepeaterAsicEntry(pAd, pEntry->MatchLinkIdx); + + NdisAcquireSpinLock(&pAd->ApCfg.ReptCliEntryLock); + + HashIdx = MAC_ADDR_HASH_INDEX(pEntry->CurrentAddress); + + pPrevEntry = NULL; + pProbeEntry = pAd->ApCfg.ReptCliHash[HashIdx]; + ASSERT(pProbeEntry); + 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); + + pMapEntry = &pAd->ApCfg.ApCliTab[pEntry->MatchApCliIdx].RepeaterCliMap[pEntry->MatchLinkIdx]; + + 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); + + NdisZeroMemory(pEntry->OriginalAddress, MAC_ADDR_LEN); + NdisZeroMemory(pEntry->CurrentAddress, MAC_ADDR_LEN); + pEntry->CliConnectState = 0; + pEntry->CtrlCurrState = APCLI_CTRL_DISCONNECTED; + pEntry->AuthCurrState = APCLI_AUTH_REQ_IDLE; + pEntry->AssocCurrState = APCLI_ASSOC_IDLE; + pEntry->CliConnectState = 0; + pEntry->CliValid = FALSE; + pEntry->CliEnable = FALSE; + pEntry->bEthCli = FALSE; + pEntry->MacTabWCID = 0xFF; + pEntry->AuthReqCnt = 0; + pEntry->AssocReqCnt = 0; + pEntry->CliTriggerTime = 0; + + pAd->ApCfg.RepeaterCliSize--; + NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); +} +#endif /* MAC_REPEATER_SUPPORT */ + +/* + ========================================================================== + 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.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; + } + } + } + } + else +#endif /* WSC_AP_SUPPORT */ + if (pApCliEntry->CfgSsidLen != 0) + { + JoinReq.SsidLen = pApCliEntry->CfgSsidLen; + NdisMoveMemory(&(JoinReq.Ssid), pApCliEntry->CfgSsid, JoinReq.SsidLen); + } + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Probe Ssid=%s, Bssid=%02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, JoinReq.Ssid, JoinReq.Bssid[0], JoinReq.Bssid[1], JoinReq.Bssid[2], + JoinReq.Bssid[3], JoinReq.Bssid[4], JoinReq.Bssid[5])); + + *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 > 7) + { + /* + if exceed the APCLI_MAX_PROBE_RETRY_NUM (7), + switch to try next candidate AP. + */ + *pCurrState = APCLI_CTRL_DISCONNECTED; + NdisZeroMemory(pAd->MlmeAux.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); + pApCliEntry->ProbeReqCnt = 0; + + if (pAd->ApCfg.ApCliAutoConnectRunning == TRUE) + ApCliSwitchCandidateAP(pAd); + 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 ((pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode != WSC_DISABLE) && + (pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger == TRUE)) + { + 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); + } + else +#endif /* WSC_AP_SUPPORT */ + if (pApCliEntry->CfgSsidLen != 0) + { + JoinReq.SsidLen = pApCliEntry->CfgSsidLen; + NdisMoveMemory(&(JoinReq.Ssid), pApCliEntry->CfgSsid, JoinReq.SsidLen); + } + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Probe Ssid=%s, Bssid=%02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, JoinReq.Ssid, JoinReq.Bssid[0], JoinReq.Bssid[1], JoinReq.Bssid[2], + JoinReq.Bssid[3], JoinReq.Bssid[4], JoinReq.Bssid[5])); + 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; +#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 */ + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + 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) Probe respond success.\n", __FUNCTION__)); + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Apcli-Interface Ssid=%s.\n", __FUNCTION__, pApCliEntry->Ssid)); + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Apcli-Interface Bssid=%02x:%02x:%02x:%02x:%02x:%02x.\n", __FUNCTION__, + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid[0], + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid[1], + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid[2], + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid[3], + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid[4], + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid[5])); + + *pCurrState = APCLI_CTRL_AUTH; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AuthReqCnt = 0; + else +#endif /* MAC_REPEATER_SUPPORT */ + pApCliEntry->AuthReqCnt = 0; + + COPY_MAC_ADDR(AuthReq.Addr, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid); + + /* start Authentication Req. */ + /* If AuthMode is Auto, try shared key first */ + if ((pAd->ApCfg.ApCliTab[ifIndex].AuthMode == Ndis802_11AuthModeShared) || + (pAd->ApCfg.ApCliTab[ifIndex].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); +#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 = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CtrlCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].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) + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AssocReqCnt = 0; + else +#endif /* MAC_REPEATER_SUPPORT */ + pApCliEntry->AssocReqCnt = 0; + + AssocParmFill(pAd, &AssocReq, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.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 + { + if (pApCliEntry->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, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.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) + { + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AuthReqCnt = 0; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.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); +#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 */ + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + 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) Auth2 Rsp Success.\n", __FUNCTION__)); + *pCurrState = APCLI_CTRL_ASSOC; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AssocReqCnt = 0; + else +#endif /* MAC_REPEATER_SUPPORT */ + pApCliEntry->AssocReqCnt = 0; + + AssocParmFill(pAd, &AssocReq, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.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 + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Apcli Auth Rsp Failure.\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); +#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; + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Auth Req Timeout.\n", __FUNCTION__)); + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AuthReqCnt++; + + if (pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AuthReqCnt > 5) + { + *pCurrState = APCLI_CTRL_DISCONNECTED; + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AuthReqCnt = 0; + //RTMPSetTimer(&pApCliEntry->RepeaterCli[CliIdx].ReptCliResetTimer, AUTH_TIMEOUT * 50); + return; + } + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pApCliEntry->AuthReqCnt++; + + if (pApCliEntry->AuthReqCnt > 5) + { + *pCurrState = APCLI_CTRL_DISCONNECTED; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.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); +#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, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid); + AuthReq.Alg = pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.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 APCLI_WPA_SUPPLICANT_SUPPORT + if (pAd->ApCfg.ApCliTab[ifIndex].WpaSupplicantUP) + { + ApcliSendAssocIEsToWpaSupplicant(pAd,ifIndex); + RtmpOSWrielessEventSend(pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + RT_ASSOC_EVENT_FLAG, + NULL, NULL, 0); + } +#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + if (ApCliLinkUp(pAd, ifIndex)) + { + *pCurrState = APCLI_CTRL_CONNECTED; + } + 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); +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + } + } + 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); +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + } + + 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 */ + + //DBGPRINT(RT_DEBUG_ERROR, ("(%s) 1. Before do ApCliLinkDown.\n", __FUNCTION__)); + 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) + { + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AssocReqCnt++; + if (pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AssocReqCnt > 5) + { + *pCurrState = APCLI_CTRL_DISCONNECTED; + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AssocReqCnt = 0; + //RTMPSetTimer(&pApCliEntry->RepeaterCli[CliIdx].ReptCliResetTimer, ASSOC_TIMEOUT * 50); + return; + } + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pApCliEntry->AssocReqCnt++; + if (pApCliEntry->AssocReqCnt > 5) + { + *pCurrState = APCLI_CTRL_DISCONNECTED; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.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); +#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].ApCliMlmeAux.Bssid, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.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); + 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 ApCliMlmeAux.Ssid and Bssid. */ + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, MAC_ADDR_LEN); + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.SsidLen = 0; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Ssid, MAX_LEN_OF_SSID); + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.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 */ + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Peer DeAssoc Req.\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) + { + UCHAR index; + BOOLEAN Cancelled; + + for(index = 0; index < MAX_EXT_MAC_ADDR_SIZE; index++) + { + if (pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[index].CliEnable) + { + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[index].ApCliAuthTimer, &Cancelled); + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[index].ApCliAssocTimer, &Cancelled); + if (pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[index].CliValid) + ApCliLinkDown(pAd, (64 + MAX_EXT_MAC_ADDR_SIZE*ifIndex + index)); + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[index].CliValid = FALSE; + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[index].CliEnable = FALSE; + 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); + } +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + + /* 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 ApCliMlmeAux.Ssid and Bssid. */ + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, MAC_ADDR_LEN); + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.SsidLen = 0; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Ssid, MAX_LEN_OF_SSID); + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.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].ApCliMlmeAux.Bssid, REASON_DISASSOC_STA_LEAVING); + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + COPY_MAC_ADDR(DisassocReq.Addr2, pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CurrentAddress); + 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); + + //DBGPRINT(RT_DEBUG_ERROR, ("(%s) 5. 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); + 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 ApCliMlmeAux.Ssid and Bssid. */ + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, MAC_ADDR_LEN); + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.SsidLen = 0; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Ssid, MAX_LEN_OF_SSID); + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.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].ApCliMlmeAux.Bssid); + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + COPY_MAC_ADDR(DeAuthFrame.Addr2, pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CurrentAddress); + 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 ApCliMlmeAux.Ssid and Bssid. */ + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, MAC_ADDR_LEN); + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.SsidLen = 0; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Ssid, MAX_LEN_OF_SSID); + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.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); + DBGPRINT(RT_DEBUG_TRACE, ("\nApCliWpaMicFailureReportFrame ----->\n")); + + 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[pAd->ApCfg.ApCliTab[ifIndex].MacTabWCID]; + if (!IS_ENTRY_APCLI(pMacEntry)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s, !IS_ENTRY_APCLI(pMacEntry)\n", __FUNCTION__)); + return; + } + + Wcid = pAd->ApCfg.ApCliTab[ifIndex].MacTabWCID; + MAKE_802_3_HEADER(Header802_3, pAd->MacTab.Content[Wcid].Addr, pAd->ApCfg.ApCliTab[ifIndex].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->ApCfg.ApCliTab[ifIndex].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, pAd->ApCfg.ApCliTab[ifIndex].ReplayCounter, LEN_KEY_DESC_REPLAY); + inc_byte_array(pAd->ApCfg.ApCliTab[ifIndex].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->ApCfg.ApCliTab[ifIndex].WepStatus == Ndis802_11Encryption3Enabled) + { /* AES */ + UCHAR digest[20] = {0}; + RT_HMAC_SHA1(pAd->ApCfg.ApCliTab[ifIndex].PTK, LEN_PTK_KCK, pOutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else + { /* TKIP */ + RT_HMAC_MD5(pAd->ApCfg.ApCliTab[ifIndex].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 */ +#endif /* APCLI_SUPPORT */ + diff --git a/mt7620/src/ap/apcli_sync.c b/mt7620/src/ap/apcli_sync.c new file mode 100644 index 0000000..2b591e0 --- /dev/null +++ b/mt7620/src/ap/apcli_sync.c @@ -0,0 +1,762 @@ +/* + *************************************************************************** + * 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, + OUT PCHAR Ssid, + IN USHORT ifIndex); + +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; + + 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); + + /*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); + + + for (i = 0; i < MAX_APCLI_NUM; i++) + { + /* timer init */ + RTMPInitTimer(pAd, &pAd->ApCfg.ApCliTab[i].ApCliMlmeAux.ProbeTimer, GET_TIMER_FUNCTION(ApCliProbeTimeout), pAd, FALSE); + + 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) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + DBGPRINT(RT_DEBUG_TRACE, ("ApCli_SYNC - ProbeReqTimeout\n")); + + MlmeEnqueue(pAd, APCLI_SYNC_STATE_MACHINE, APCLI_MT2_PROBE_TIMEOUT, 0, NULL, 0); + 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; + PAPCLI_STRUCT pApCliEntry = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("ApCli SYNC - ApCliMlmeProbeReqAction(Ssid %s)\n", Info->Ssid)); + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + /* reset all the timers */ + RTMPCancelTimer(&(pApCliEntry->ApCliMlmeAux.ProbeTimer), &Cancelled); + + pApCliEntry->ApCliMlmeAux.Rssi = -9999; + pApCliEntry->ApCliMlmeAux.Channel = pAd->CommonCfg.Channel; + pApCliEntry->ApCliMlmeAux.SupRateLen = pAd->CommonCfg.SupRateLen; + NdisMoveMemory(pApCliEntry->ApCliMlmeAux.SupRate, pAd->CommonCfg.SupRate, pAd->CommonCfg.SupRateLen); + + /* Prepare the default value for extended rate */ + pApCliEntry->ApCliMlmeAux.ExtRateLen = pAd->CommonCfg.ExtRateLen; + NdisMoveMemory(pApCliEntry->ApCliMlmeAux.ExtRate, pAd->CommonCfg.ExtRate, pAd->CommonCfg.ExtRateLen); + + RTMPSetTimer(&(pApCliEntry->ApCliMlmeAux.ProbeTimer), PROBE_TIMEOUT); + + ApCliEnqueueProbeRequest(pAd, Info->SsidLen, (PCHAR) Info->Ssid, ifIndex); + + DBGPRINT(RT_DEBUG_TRACE, ("ApCli SYNC - Start Probe the SSID %s on channel =%d\n", pApCliEntry->ApCliMlmeAux.Ssid, pApCliEntry->ApCliMlmeAux.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) +{ + UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; + UCHAR /* Ssid[MAX_LEN_OF_SSID], */ SsidLen=0, BssType, Channel=0, MessageToMe, + DtimCount, DtimPeriod, BcastFlag; + UCHAR *Ssid = NULL; + LARGE_INTEGER TimeStamp; + USHORT BeaconPeriod, AtimWin, CapabilityInfo; +/* UINT FrameLen = 0; */ + CF_PARM Cf; + UCHAR Erp; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen, ExtRateLen; + UCHAR CkipFlag; + USHORT LenVIE; + UCHAR AironetCellPowerLimit; + EDCA_PARM EdcaParm; + QBSS_LOAD_PARM QbssLoad; + QOS_CAPABILITY_PARM QosCapability; +/* UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 */ + UCHAR *VarIE = NULL; + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + ULONG RalinkIe; + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; +/* HT_CAPABILITY_IE HtCapability; */ +/* ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE */ + HT_CAPABILITY_IE *pHtCapability = NULL; + ADD_HT_INFO_IE *pAddHtInfo = NULL; /* AP might use this additional ht info IE */ + UCHAR HtCapabilityLen; + UCHAR AddHtInfoLen; + UCHAR NewChannel; + UCHAR NewExtChannelOffset = 0xff; + PAPCLI_STRUCT pApCliEntry = NULL; +#ifdef DOT11_N_SUPPORT + UCHAR CentralChannel; +#endif /* DOT11_N_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + UCHAR pPreNHtCapabilityLen = 0; +#endif /* CONFIG_STA_SUPPORT */ + EXT_CAP_INFO_ELEMENT ExtCapInfo; + + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].SyncCurrState; + + if (ifIndex >= MAX_APCLI_NUM) + return; + + /* 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; + } + os_alloc_mem(NULL, (UCHAR **)&pHtCapability, sizeof(HT_CAPABILITY_IE)); + if (pHtCapability == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + os_alloc_mem(NULL, (UCHAR **)&pAddHtInfo, sizeof(ADD_HT_INFO_IE)); + if (pAddHtInfo == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + os_alloc_mem(NULL, (UCHAR **)&Ssid, MAX_LEN_OF_SSID); + if (Ssid == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + + /* Init Variable IE structure */ + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + RTMPZeroMemory(pHtCapability, sizeof(HT_CAPABILITY_IE)); + RTMPZeroMemory(pAddHtInfo, sizeof(ADD_HT_INFO_IE)); + RTMPZeroMemory(&QosCapability, sizeof(QosCapability)); + RTMPZeroMemory(&EdcaParm, sizeof(EdcaParm)); + + if (PeerBeaconAndProbeRspSanity(pAd, + Elem->Msg, + Elem->MsgLen, + Elem->Channel, + Addr2, + Bssid, + (PCHAR) Ssid, + &SsidLen, + &BssType, + &BeaconPeriod, + &Channel, + &NewChannel, + &TimeStamp, + &Cf, + &AtimWin, + &CapabilityInfo, + &Erp, + &DtimCount, + &DtimPeriod, + &BcastFlag, + &MessageToMe, + SupRate, + &SupRateLen, + ExtRate, + &ExtRateLen, + &CkipFlag, + &AironetCellPowerLimit, + &EdcaParm, + &QbssLoad, + &QosCapability, + &RalinkIe, + &HtCapabilityLen, +#ifdef CONFIG_STA_SUPPORT + &pPreNHtCapabilityLen, +#endif /* CONFIG_STA_SUPPORT */ + pHtCapability, + &ExtCapInfo, + &AddHtInfoLen, + pAddHtInfo, + &NewExtChannelOffset, + &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; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + /* Check the Probe-Rsp's Bssid. */ + if(!MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, ZERO_MAC_ADDR)) + bssidEqualFlag = MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, Bssid); + else + bssidEmptyFlag = TRUE; + + /* Check the Probe-Rsp's Ssid. */ + if(pApCliEntry->CfgSsidLen != 0) + ssidEqualFlag = SSID_EQUAL(pApCliEntry->CfgSsid, pApCliEntry->CfgSsidLen, Ssid, 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; + + + 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 + && ((pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode == WSC_DISABLE) || + (pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger == FALSE)) +#endif /* WSC_AP_SUPPORT */ + ) + { + if (ApCliValidateRSNIE(pAd, (PEID_STRUCT)pVIE, LenVIE, ifIndex)) + { + pApCliEntry->ApCliMlmeAux.VarIELen = LenVIE; + NdisMoveMemory(pApCliEntry->ApCliMlmeAux.VarIEs, pVIE, pApCliEntry->ApCliMlmeAux.VarIELen); + } + else + { + /* ignore this response */ + pApCliEntry->ApCliMlmeAux.VarIELen = 0; + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The RSN IE of this received Probe-resp is dis-match !!!!!!!!!! \n")); + goto LabelErr; + } + } + else + { + if (pApCliEntry->AuthMode >= Ndis802_11AuthModeWPA +#ifdef WSC_AP_SUPPORT + && ((pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode == WSC_DISABLE) || + (pAd->ApCfg.ApCliTab[ifIndex].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->ApCliMlmeAux.VarIELen = 0; + } + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - receive desired PROBE_RSP at JoinWaitProbeRsp... Channel = %d\n", 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 RealRssi = (LONG)(RTMPMaxRssi(pAd, Rssi0, Rssi1, Rssi2)); + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - previous Rssi = %ld current Rssi=%ld\n", pApCliEntry->ApCliMlmeAux.Rssi, (LONG)RealRssi)); + if (pApCliEntry->ApCliMlmeAux.Rssi > (LONG)RealRssi) + goto LabelErr; + else + pApCliEntry->ApCliMlmeAux.Rssi = RealRssi; + } else + { + BOOLEAN Cancelled; + RTMPCancelTimer(&pApCliEntry->ApCliMlmeAux.ProbeTimer, &Cancelled); + } + + NdisMoveMemory(pApCliEntry->ApCliMlmeAux.Ssid, Ssid, SsidLen); + pApCliEntry->ApCliMlmeAux.SsidLen = SsidLen; + + NdisMoveMemory(pApCliEntry->ApCliMlmeAux.Bssid, Bssid, MAC_ADDR_LEN); + pApCliEntry->ApCliMlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; + pApCliEntry->ApCliMlmeAux.BssType = BssType; + pApCliEntry->ApCliMlmeAux.BeaconPeriod = BeaconPeriod; + pApCliEntry->ApCliMlmeAux.Channel = Channel; + pApCliEntry->ApCliMlmeAux.AtimWin = AtimWin; + pApCliEntry->ApCliMlmeAux.CfpPeriod = Cf.CfpPeriod; + pApCliEntry->ApCliMlmeAux.CfpMaxDuration = Cf.CfpMaxDuration; + pApCliEntry->ApCliMlmeAux.APRalinkIe = RalinkIe; + + /* Copy AP's supported rate to ApCliMlmeAux for creating assoication request */ + /* Also filter out not supported rate */ + pApCliEntry->ApCliMlmeAux.SupRateLen = SupRateLen; + NdisMoveMemory(pApCliEntry->ApCliMlmeAux.SupRate, SupRate, SupRateLen); + RTMPCheckRates(pAd, pApCliEntry->ApCliMlmeAux.SupRate, &(pApCliEntry->ApCliMlmeAux.SupRateLen)); + pApCliEntry->ApCliMlmeAux.ExtRateLen = ExtRateLen; + NdisMoveMemory(pApCliEntry->ApCliMlmeAux.ExtRate, ExtRate, ExtRateLen); + RTMPCheckRates(pAd, pApCliEntry->ApCliMlmeAux.ExtRate, &pApCliEntry->ApCliMlmeAux.ExtRateLen); + +#ifdef APCLI_CERT_SUPPORT + /* Get the ext capability info element */ + if (pAd->bApCliCertTest == TRUE) + { + NdisMoveMemory(&pApCliEntry->ApCliMlmeAux.ExtCapInfo, &ExtCapInfo,sizeof(ExtCapInfo)); +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + DBGPRINT(RT_DEBUG_TRACE, ("\x1b[31m ApCliMlmeAux.ExtCapInfo=%d \x1b[m\n", pApCliEntry->ApCliMlmeAux.ExtCapInfo.BssCoexistMgmtSupport)); //zero debug 210121122 + if (pAd->CommonCfg.bBssCoexEnable == TRUE) + pAd->CommonCfg.ExtCapIE.BssCoexistMgmtSupport = 1; +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + } +#endif /* APCLI_CERT_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].RxMcsSet,sizeof(pAd->ApCfg.ApCliTab[ifIndex].RxMcsSet)); + /* filter out un-supported ht rates */ + if ((HtCapabilityLen > 0) && + (pApCliEntry->DesiredHtPhyInfo.bHtEnable) && + (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + RTMPZeroMemory(&(pApCliEntry->ApCliMlmeAux.HtCapability), SIZE_HT_CAP_IE); + pApCliEntry->ApCliMlmeAux.NewExtChannelOffset = NewExtChannelOffset; + pApCliEntry->ApCliMlmeAux.HtCapabilityLen = HtCapabilityLen; + ApCliCheckHt(pAd, ifIndex, pHtCapability, pAddHtInfo); + + if (AddHtInfoLen > 0) + { + CentralChannel = pAddHtInfo->ControlChan; + /* Check again the Bandwidth capability of this AP. */ + if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40)) + { + CentralChannel = pAddHtInfo->ControlChan - 2; + } + else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40)) + { + CentralChannel = pAddHtInfo->ControlChan + 2; + } + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction HT===>Central Channel = %d, Control Channel = %d, .\n", CentralChannel, pAddHtInfo->ControlChan)); + + } + + } + else +#endif /* DOT11_N_SUPPORT */ + { + RTMPZeroMemory(&(pApCliEntry->ApCliMlmeAux.HtCapability), SIZE_HT_CAP_IE); + RTMPZeroMemory(&(pApCliEntry->ApCliMlmeAux.AddHtInfo), SIZE_ADD_HT_INFO_IE); + pApCliEntry->ApCliMlmeAux.HtCapabilityLen = 0; + } + ApCliUpdateMlmeRate(pAd, ifIndex); + +#ifdef DOT11_N_SUPPORT + /* copy QOS related information */ + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + { + NdisMoveMemory(&(pApCliEntry->ApCliMlmeAux.APEdcaParm), &EdcaParm, sizeof(EDCA_PARM)); + NdisMoveMemory(&(pApCliEntry->ApCliMlmeAux.APQbssLoad), &QbssLoad, sizeof(QBSS_LOAD_PARM)); + NdisMoveMemory(&(pApCliEntry->ApCliMlmeAux.APQosCapability), &QosCapability, sizeof(QOS_CAPABILITY_PARM)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + NdisZeroMemory(&(pApCliEntry->ApCliMlmeAux.APEdcaParm), sizeof(EDCA_PARM)); + NdisZeroMemory(&(pApCliEntry->ApCliMlmeAux.APQbssLoad), sizeof(QBSS_LOAD_PARM)); + NdisZeroMemory(&(pApCliEntry->ApCliMlmeAux.APQosCapability), sizeof(QOS_CAPABILITY_PARM)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI SYNC - after JOIN, SupRateLen=%d, ExtRateLen=%d\n", + pApCliEntry->ApCliMlmeAux.SupRateLen, pApCliEntry->ApCliMlmeAux.ExtRateLen)); + + if (AironetCellPowerLimit != 0xFF) + { + /*We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power */ + ChangeToCellPowerLimit(pAd, AironetCellPowerLimit); + } + else /*Used the default TX Power Percentage. */ + pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; + +#ifdef WSC_AP_SUPPORT +#ifdef DOT11_N_SUPPORT + if ((pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode != WSC_DISABLE) && + (pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger == TRUE)) + { + ADD_HTINFO RootApHtInfo, ApHtInfo; + ApHtInfo = pAd->CommonCfg.AddHTInfo.AddHtInfo; + RootApHtInfo = pAddHtInfo->AddHtInfo; + if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && + (RootApHtInfo.RecomWidth) && + (RootApHtInfo.ExtChanOffset != ApHtInfo.ExtChanOffset)) + { + /*STRING ChStr[5] = {0}; */ + + if (RootApHtInfo.ExtChanOffset == EXTCHA_ABOVE) + Set_HtExtcha_Proc(pAd, "1"); + else + Set_HtExtcha_Proc(pAd, "0"); + + goto LabelErr; + } + } +#endif /* DOT11_N_SUPPORT */ +#endif /* WSC_AP_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); + } + } + /* not to me BEACON, ignored */ + } + /* sanity check fail, ignore this frame */ + +LabelErr: + 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 (Ssid != NULL) + os_free_mem(NULL, Ssid); + 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; + PAPCLI_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; + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_SYNC - ApCliMlmeAux.Bssid=%02x:%02x:%02x:%02x:%02x:%02x\n", + pApCliEntry->ApCliMlmeAux.Bssid[0], + pApCliEntry->ApCliMlmeAux.Bssid[1], + pApCliEntry->ApCliMlmeAux.Bssid[2], + pApCliEntry->ApCliMlmeAux.Bssid[3], + pApCliEntry->ApCliMlmeAux.Bssid[4], + pApCliEntry->ApCliMlmeAux.Bssid[5])); + + if(!MAC_ADDR_EQUAL(pApCliEntry->ApCliMlmeAux.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, + OUT PCHAR Ssid, + 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]; + PAPCLI_STRUCT pApCliEntry = NULL; + BOOLEAN bHasWscIe = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("force out a ProbeRequest ...\n")); + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + 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(pAd->ApCfg.ApCliTab[ifIndex].CfgApCliBssid, ZERO_MAC_ADDR)) + ApCliMgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, + BROADCAST_ADDR, BROADCAST_ADDR, ifIndex); + else + ApCliMgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, + pAd->ApCfg.ApCliTab[ifIndex].CfgApCliBssid, pAd->ApCfg.ApCliTab[ifIndex].CfgApCliBssid, 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->ApCliMlmeAux.SupRateLen), + pApCliEntry->ApCliMlmeAux.SupRateLen, pApCliEntry->ApCliMlmeAux.SupRate, + END_OF_ARGS); + + /* Add the extended rate IE */ + if (pApCliEntry->ApCliMlmeAux.ExtRateLen != 0) + { + ULONG tmp; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &(pApCliEntry->ApCliMlmeAux.ExtRateLen), + pApCliEntry->ApCliMlmeAux.ExtRateLen, pApCliEntry->ApCliMlmeAux.ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + +/* 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 CON_WPS + if ((pAd->conWscStatus != CON_WPS_STATUS_DISABLED) && bHasWscIe) + { + bHasWscIe = FALSE; + printk("YF DEBUG: Don't Put THE WSC IE IN ProbeReq due to CON_WPS\n"); + } +#endif /* CON_WPS */ + 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->ApCfg.ApCliTab[0].WscControl, 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__)); + } + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + + return; +} + +#endif /* APCLI_SUPPORT */ + diff --git a/mt7620/src/ate/chips/rt2883_ate.c b/mt7620/src/ate/chips/rt2883_ate.c new file mode 100644 index 0000000..c5090e7 --- /dev/null +++ b/mt7620/src/ate/chips/rt2883_ate.c @@ -0,0 +1,909 @@ +/* + *************************************************************************** + * 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: + rt2883_ate.c + + Abstract: + Specific ATE funcitons and variables for RT2883 + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifdef RT2883 + +#include "rt_config.h" + +extern RTMP_RF_REGS RF2850RegTable[]; +extern UCHAR NUM_OF_2850_CHNL; + + +/* +========================================================================== + Description: + + AsicSwitchChannel() dedicated for RT2883 ATE. + +========================================================================== +*/ +VOID RT2883ATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 Value = 0; + CHAR TxPwer = 0, TxPwer2 = 0; + UCHAR index = 0, BbpValue = 0, Channel = 0; + UINT32 R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0; + RTMP_RF_REGS *RFRegTable = NULL; +#ifdef DOT11N_SS3_SUPPORT + CHAR TxPwer3 = 0; +#endif /* DOT11N_SS3_SUPPORT */ + + SYNC_CHANNEL_WITH_QA(pATEInfo, &Channel); + + /* fill Tx power value */ + TxPwer = pATEInfo->TxPower0; + TxPwer2 = pATEInfo->TxPower1; +#ifdef DOT11N_SS3_SUPPORT + TxPwer3 = pATEInfo->TxPower2; +#endif /* DOT11N_SS3_SUPPORT */ + + RFRegTable = RF2850RegTable; + + switch (pAd->RfIcType) + { + case RFIC_2853: + for (index = 0; index < NUM_OF_2850_CHNL; index++) + { + if (Channel == RFRegTable[index].Channel) + { + R2 = RFRegTable[index].R2; + + /* If TX path is 1, bit 14 = 1. */ + if (pAd->Antenna.field.TxPath == 1) + { + R2 |= 0x4000; + } + + if (pAd->Antenna.field.TxPath < 3) + { + R2 |= 0x2000;/* write 1 to bit 13 */ + } + + if (pAd->Antenna.field.TxPath == 3) + { + RTMP_IO_READ32(pAd, 0x1048, &Value); + + if (pATEInfo->TxAntennaSel == 1) + { + /* BBP, MAC control */ + RTMP_IO_READ32(pAd, 0x1048, &Value); + + Value &= ~0x000F0000; + Value |= 0x00000000; /* 0b00 for bit 16,17 */ + RTMP_IO_WRITE32(pAd, 0x1048, Value); + + RTMP_IO_READ32(pAd, 0x1048, &Value); + + /* RF Reg2 bit[15:14:13]=0:1:1 */ + R2 &= ~(0x0000E000); + R2 |= 0x00006000; + } + else if (pATEInfo->TxAntennaSel == 2) + { + /* BBP, MAC control */ + RTMP_IO_READ32(pAd, 0x1048, &Value); + Value &= ~0x000F0000; + Value |= 0x00010000; + RTMP_IO_WRITE32(pAd, 0x1048, Value); + + RTMP_IO_READ32(pAd, 0x1048, &Value); + + /* RF Reg2 bit[15:14:13]=1:0:1 */ + R2 &= ~(0x0000E000); + R2 |= 0x0000A000; + } + else if (pATEInfo->TxAntennaSel == 3) + { + /* BBP, MAC control */ + RTMP_IO_READ32(pAd, 0x1048, &Value); + Value &= ~0x000F0000; + Value |= 0x00020000; + RTMP_IO_WRITE32(pAd, 0x1048, Value); + + RTMP_IO_READ32(pAd, 0x1048, &Value); + + /* RF Reg2 bit[15:14:13]=1:1:0 */ + R2 &= ~(0x0000E000); + R2 |= 0x0000C000; + } + else + { + /* BBP, MAC control */ + RTMP_IO_READ32(pAd, 0x1048, &Value); + Value |= 0x00030000; + RTMP_IO_WRITE32(pAd, 0x1048, Value); + RTMP_IO_READ32(pAd, 0x1048, &Value); + + /* RF Reg2 bit[15:14:13]=0:0:0 */ + R2 &= ~(0x0000E000); + R2 |= 0x00000000; + } + } + + if (pAd->Antenna.field.TxPath == 2) + { + if (pATEInfo->TxAntennaSel == 1) + { + /* If TX Antenna select is 1 , bit 14 = 1; Disable Ant 2 */ + R2 |= 0x4000; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; /* 11100111B */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + } + else if (pATEInfo->TxAntennaSel == 2) + { + /* If TX Antenna select is 2 , bit 15 = 1; Disable Ant 1 */ + R2 |= 0x8000; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + } + else + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + } + } + + if (pAd->Antenna.field.RxPath == 2) + { + switch (pATEInfo->RxAntennaSel) + { + case 1: + R2 |= 0x20040; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x00; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + case 2: + R2 |= 0x10040; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x01; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + default: + R2 |= 0x40; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + /* Only enable two Antenna to receive. */ + BbpValue |= 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + } + } + else if (pAd->Antenna.field.RxPath == 1) + { + /* write 1 to off RxPath */ + R2 |= 0x20040; + } + + if (pAd->Antenna.field.RxPath == 3) + { + switch (pATEInfo->RxAntennaSel) + { + case 1: + R2 |= 0x20040; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x00; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + case 2: + R2 |= 0x10040; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x01; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + case 3: + R2 |= 0x30000; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x02; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + default: + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + } + } + + if (Channel > 14) + { + /* initialize R3, R4 */ + R3 = (RFRegTable[index].R3 & 0xffffc1ff); + R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pATEInfo->RFFreqOffset << 15); + + /* + According the Rory's suggestion to solve the middle range issue. + + 5.5G band power range : 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" + means the TX power reduce 7dB. + */ + /* R3 */ + if ((TxPwer >= -7) && (TxPwer < 0)) + { + TxPwer = (7+TxPwer); + R3 |= (TxPwer << 10); + DBGPRINT(RT_DEBUG_TRACE, ("ATEAsicSwitchChannel: TxPwer=%d \n", TxPwer)); + } + else + { + TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); + R3 |= (TxPwer << 10) | (1 << 9); + } + + /* R4 */ + if ((TxPwer2 >= -7) && (TxPwer2 < 0)) + { + TxPwer2 = (7+TxPwer2); + R4 |= (TxPwer2 << 7); + DBGPRINT(RT_DEBUG_TRACE, ("ATEAsicSwitchChannel: TxPwer2=%d \n", TxPwer2)); + } + else + { + TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); + R4 |= (TxPwer2 << 7) | (1 << 6); + } + + RFRegTable[index].R1 &= 0xff8fffcf; /* clear bit 4,5,20,21,22 */ + /* R1 */ + if ((TxPwer3 >= -7) && (TxPwer3 < 0)) + { + TxPwer3 = (7+TxPwer3); + RFRegTable[index].R1 |= (((TxPwer3 & 0xe) << 19) | ((TxPwer3 & 0x1) << 5)); + } + else + { + TxPwer3 = (TxPwer3 > 0xF) ? (0xF) : (TxPwer3); + RFRegTable[index].R1 |= (((TxPwer3 & 0xe) << 19) | ((TxPwer3 & 0x1) << 5)) | (1 << 4); + } + RFRegTable[index].R1 &= 0xfffffdff; + } + else + { + /* Set TX power0. */ + R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); + /* Set frequency offset and TX power1. */ + R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pATEInfo->RFFreqOffset << 15) | (TxPwer2 <<6); + + RFRegTable[index].R1 &= 0xff8fffcf; /* clear bit 4,5,20,21,22 */ + /* R1 */ + RFRegTable[index].R1 |= (((TxPwer3 & 0x1c) << 18) | ((TxPwer3 & 0x3) << 4)); + RFRegTable[index].R1 &= 0xfffffdff; + } + + /* based on BBP current mode before changing RF channel */ + if (pATEInfo->TxWI.BW == BW_40) + { + R4 |=0x200000; + } + + /* Update variables. */ + pAd->LatchRfRegs.Channel = Channel; + pAd->LatchRfRegs.R1 = RFRegTable[index].R1; + pAd->LatchRfRegs.R2 = R2; + pAd->LatchRfRegs.R3 = R3; + pAd->LatchRfRegs.R4 = R4; + + RtmpRfIoWrite(pAd); + + break; + } + } + break; + + default: + break; + } + + + /* Change BBP setting during switch from a->g, g->a */ + if (Channel <= 14) + { + UINT32 TxPinCfg = 0x00050F0A;/* 2007.10.09 by Brian : 0x0005050A ==> 0x00050F0A */ + + TxPinCfg = 0x32050F0A;/* Gary 2007/08/09 0x050A0A */ + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + + /* According the Rory's suggestion to solve the middle range issue. */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0); + + /* Rx High power VGA offset for LNA select */ + if (pAd->NicConfig2.field.ExternalLNAForG) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + /* 2.4 G band selection PIN */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x04); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + /* 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; + } + + /* calibration power unbalance issues */ + if (pAd->Antenna.field.TxPath == 2) + { + if (pATEInfo->TxAntennaSel == 1) + { + TxPinCfg &= 0xFFFFFFF7; + } + else if (pATEInfo->TxAntennaSel == 2) + { + TxPinCfg &= 0xFFFFFFFD; + } + } + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + } + /* channel > 14 */ + else + { + UINT32 TxPinCfg = 0x00050F05;/* 2007.10.09 by Brian : 0x00050505 ==> 0x00050F05 */ + + TxPinCfg = 0x31050F05;/* Gary 2007/08/09 0x050A0A */ + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + + /* According the Rory's suggestion to solve the middle range issue. */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0); + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + } + + ATE_CHIP_RX_VGA_GAIN_INIT(pAd); + + RtmpOsMsDelay(1); + + if (Channel > 14) + { + /* When 5.5GHz band the LSB of TxPwr will be used to reduced 7dB or not. */ + DBGPRINT(RT_DEBUG_TRACE, ("RT2883:SwitchChannel#%d(RF=%d, %dT) to , R1=0x%08x, R2=0x%08x, R3=0x%08x, R4=0x%08x\n", + Channel, + pAd->RfIcType, + pAd->Antenna.field.TxPath, + pAd->LatchRfRegs.R1, + pAd->LatchRfRegs.R2, + pAd->LatchRfRegs.R3, + pAd->LatchRfRegs.R4)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("RT2883:SwitchChannel#%d(RF=%d, Pwr0=%u, Pwr1=%u, %dT) to , R1=0x%08x, R2=0x%08x, R3=0x%08x, R4=0x%08x\n", + Channel, + pAd->RfIcType, + (R3 & 0x00003e00) >> 9, + (R4 & 0x000007c0) >> 6, + pAd->Antenna.field.TxPath, + pAd->LatchRfRegs.R1, + pAd->LatchRfRegs.R2, + pAd->LatchRfRegs.R3, + pAd->LatchRfRegs.R4)); + } +} + + +INT RT2883ATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index) +{ + PATE_INFO pATEInfo = &(pAd->ate); + ULONG R; + CHAR TxPower = 0; + UCHAR Bbp94 = 0; + BOOLEAN bPowerReduce = FALSE; + +#ifdef RALINK_QA + if ((pATEInfo->bQATxStart == TRUE) || (pATEInfo->bQARxStart == TRUE)) + { + return 0; + } + else +#endif /* RALINK_QA */ + if (index == 0) + { + TxPower = pATEInfo->TxPower0; + } + else if (index == 1) + { + TxPower = pATEInfo->TxPower1; + } +#ifdef DOT11N_SS3_SUPPORT + else if (index == 2) + { + TxPower = pATEInfo->TxPower2; + } +#endif /* DOT11N_SS3_SUPPORT */ + else + { +#ifdef DOT11N_SS3_SUPPORT + DBGPRINT_ERR(("%s : Only TxPower0, TxPower1, and TxPower2 are adjustable !\n", __FUNCTION__)); +#else + DBGPRINT_ERR(("%s : Only TxPower0 and TxPower1 are adjustable !\n", __FUNCTION__)); +#endif /* DOT11N_SS3_SUPPORT */ + DBGPRINT_ERR(("%s : TxPower%d is out of range !\n", __FUNCTION__, index)); + return -1; + } + + if (pATEInfo->Channel <= 14) + { + if (TxPower > 31) + { + /* R3, R4 can't large than 31 (0x24), 31 ~ 36 used by BBP 94 */ + R = 31; + if (TxPower <= 36) + Bbp94 = BBPR94_DEFAULT + (UCHAR)(TxPower - 31); + } + else if (TxPower < 0) + { + /* R3, R4 can't less than 0, -1 ~ -6 used by BBP 94 */ + R = 0; + if (TxPower >= -6) + Bbp94 = BBPR94_DEFAULT + TxPower; + } + else + { + /* 0 ~ 31 */ + R = (ULONG) TxPower; + Bbp94 = BBPR94_DEFAULT; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s : (TxPower=%d, R=%ld, BBP_R94=%d)\n", __FUNCTION__, TxPower, R, Bbp94)); + } + else /* 5.5 GHz */ + { + if (TxPower > 15) + { + /* R3, R4 can't large than 15 (0x0F) */ + R = 15; + } + else if (TxPower < 0) + { + /* R3, R4 can't less than 0 */ + /* -1 ~ -7 */ + ASSERT((TxPower >= -7)); + R = (ULONG)(TxPower + 7); + bPowerReduce = TRUE; + } + else + { + /* 0 ~ 15 */ + R = (ULONG) TxPower; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s : (TxPower=%d, R=%lu)\n", __FUNCTION__, TxPower, R)); + } + + if (pATEInfo->Channel <= 14) + { + if (index == 0) + { + /* shift TX power control to correct RF(R3) register bit position */ + R = R << 9; + R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); + pAd->LatchRfRegs.R3 = R; + } + else + { + /* shift TX power control to correct RF(R4) register bit position */ + R = R << 6; + R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); + pAd->LatchRfRegs.R4 = R; + } + } + else /* 5.5GHz */ + { + if (bPowerReduce == FALSE) + { + if (index == 0) + { + /* shift TX power control to correct RF(R3) register bit position */ + R = (R << 10) | (1 << 9); + R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); + pAd->LatchRfRegs.R3 = R; + } + else + { + /* shift TX power control to correct RF(R4) register bit position */ + R = (R << 7) | (1 << 6); + R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); + pAd->LatchRfRegs.R4 = R; + } + } + else + { + if (index == 0) + { + /* shift TX power control to correct RF(R3) register bit position */ + R = (R << 10); + R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); + + /* Clear bit 9 of R3 to reduce 7dB. */ + pAd->LatchRfRegs.R3 = (R & (~(1 << 9))); + } + else + { + /* shift TX power control to correct RF(R4) register bit position */ + R = (R << 7); + R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); + + /* Clear bit 6 of R4 to reduce 7dB. */ + pAd->LatchRfRegs.R4 = (R & (~(1 << 6))); + } + } + } + RtmpRfIoWrite(pAd); + + return 0; +} + + +VOID RT2883ATERxVGAInit( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR R66; + CHAR LNAGain = GET_LNA_GAIN(pAd); + + if (pATEInfo->Channel <= 14) + { + /* BG band */ + R66 = (UCHAR)(0x2E + LNAGain); + } + else + { + /* A band */ + if (pATEInfo->TxWI.BW == BW_20) + { + /* A band, BW == 20 */ + R66 = (UCHAR)(0x32 + (LNAGain*5)/3); + } + else + { + /* A band, BW == 40 */ + R66 = (UCHAR)(0x3A + (LNAGain*5)/3); + } + } + + ATEBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + + + return; +} + + +/* +========================================================================== + Description: + Set RT2883 ATE RF BW + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT RT2883_Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + INT powerIndex; + UCHAR value = 0; + UCHAR BBPCurrentBW; + + BBPCurrentBW = simple_strtol(arg, 0, 10); + + if (BBPCurrentBW == 0) + { + pATEInfo->TxWI.BW = BW_20; + } + else + { + pATEInfo->TxWI.BW = BW_40; + } + + if ((pATEInfo->TxWI.PHYMODE == MODE_CCK) && (pATEInfo->TxWI.BW == BW_40)) + { + DBGPRINT_ERR(("Set_ATE_TX_BW_Proc!! Warning!! CCK only supports 20MHZ!!\n")); + DBGPRINT_ERR(("Bandwidth switch to 20!!\n")); + pATEInfo->TxWI.BW = BW_20; + } + + if (pATEInfo->TxWI.BW == BW_20) + { + if (pATEInfo->Channel <= 14) + { + /* BW=20;G band */ + for (powerIndex=0; powerIndexTx20MPwrCfgGBand[powerIndex] == 0xffffffff) + continue; + + /* TX_PWR_CFG_0 ~ TX_PWR_CFG_6 */ + /* TX_PWR_CFG_0_EXT ~ TX_PWR_CFG_4_EXT */ + if (powerIndex == 5) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_5, pAd->Tx20MPwrCfgGBand[powerIndex]); + } + else if (powerIndex == 6) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_6, pAd->Tx20MPwrCfgGBand[powerIndex]); + } + else + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx20MPwrCfgGBand[powerIndex]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0_EXT + powerIndex*4, (pAd->Tx20MPwrCfgGBand[powerIndex] & 0xf0f0f0f0) >> 4); + } + RtmpOsMsDelay(5); + } + } + else + { + /* BW=20;A band */ + for (powerIndex=0; powerIndexTx20MPwrCfgABand[powerIndex] == 0xffffffff) + continue; + + /* TX_PWR_CFG_0 ~ TX_PWR_CFG_6 */ + /* TX_PWR_CFG_0_EXT ~ TX_PWR_CFG_4_EXT */ + if (powerIndex == 5) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_5, pAd->Tx20MPwrCfgABand[powerIndex]); + } + else if (powerIndex == 6) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_6, pAd->Tx20MPwrCfgABand[powerIndex]); + } + else + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx20MPwrCfgABand[powerIndex]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0_EXT + powerIndex*4, (pAd->Tx20MPwrCfgABand[powerIndex] & 0xf0f0f0f0) >> 4); + } + RtmpOsMsDelay(5); + } + } + + /* set BW = 20 MHz */ + /* Set BBP R4 bit[4:3]=0:0 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value &= (~0x18); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + /* Set BBP R66=0x3C */ + value = 0x3C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value); + + pAd->LatchRfRegs.R4 &= ~0x00200000; + RtmpRfIoWrite(pAd); + + /* BW = 20 MHz */ + /* Set BBP R68=0x0B to improve Rx sensitivity. */ + value = 0x0B; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + /* Set BBP R69=0x16 */ + value = 0x16; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + /* Set BBP R70=0x08 */ + value = 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + /* Set BBP R73=0x11 */ + value = 0x11; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + + if (pATEInfo->Channel == 14) + { + INT TxMode = pATEInfo->TxWI.PHYMODE; + + if (TxMode == MODE_CCK) + { + /* when Channel==14 && Mode==CCK && BandWidth==20M, BBP R4 bit5=1 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value |= 0x20; /* set bit5=1 */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + } + } + } + /* If bandwidth = 40M, set RF Reg4 bit 21 = 0. */ + else if (pATEInfo->TxWI.BW == BW_40) + { + if (pATEInfo->Channel <= 14) + { + /* BW=40;G band */ + for (powerIndex=0; powerIndexTx40MPwrCfgGBand[powerIndex] == 0xffffffff) + continue; + + /* TX_PWR_CFG_0 ~ TX_PWR_CFG_6 */ + /* TX_PWR_CFG_0_EXT ~ TX_PWR_CFG_4_EXT */ + if (powerIndex == 5) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_5, pAd->Tx40MPwrCfgGBand[powerIndex]); + } + else if (powerIndex == 6) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_6, pAd->Tx40MPwrCfgGBand[powerIndex]); + } + else + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx40MPwrCfgGBand[powerIndex]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0_EXT + powerIndex*4, (pAd->Tx40MPwrCfgGBand[powerIndex] & 0xf0f0f0f0) >> 4); + } + RtmpOsMsDelay(5); + } + } + else + { + /* BW=40;A band */ + for (powerIndex=0; powerIndexTx40MPwrCfgABand[powerIndex] == 0xffffffff) + continue; + + /* TX_PWR_CFG_0 ~ TX_PWR_CFG_6 */ + if (powerIndex == 5) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_5, pAd->Tx40MPwrCfgABand[powerIndex]); + } + else if (powerIndex == 6) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_6, pAd->Tx40MPwrCfgABand[powerIndex]); + } + else + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx40MPwrCfgABand[powerIndex]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0_EXT + powerIndex*4, (pAd->Tx40MPwrCfgABand[powerIndex] & 0xf0f0f0f0) >> 4); + } + RtmpOsMsDelay(5); + } + + if ((pATEInfo->TxWI.PHYMODE >= 2) && (pATEInfo->TxWI.MCS == 7)) + { + value = 0x28; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R67, value); + } + } + + /* Set BBP R4 bit[4:3]=1:0 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value &= (~0x18); + value |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + /* Set BBP R66=0x3C */ + value = 0x3C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value); + + /* set BW = 40 MHz */ + pAd->LatchRfRegs.R4 |= 0x00200000; + RtmpRfIoWrite(pAd); + + /* BW = 40 MHz */ + /* Set BBP R68=0x0C to improve Rx sensitivity. */ + value = 0x0C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + /* Set BBP R69=0x1A */ + value = 0x1A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + /* Set BBP R70=0x0A */ + value = 0x0A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + /* Set BBP R73=0x16 */ + value = 0x16; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + } + + return TRUE; +} + + +INT RT2883_Set_ATE_TX_FREQ_OFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + ULONG R4 = 0; + UCHAR RFFreqOffset = 0; + + RFFreqOffset = simple_strtol(arg, 0, 10); + + if (RFFreqOffset >= 64) + { + DBGPRINT_ERR(("Set_ATE_TX_FREQ_OFFSET_Proc::Out of range(0 ~ 63).\n")); + return FALSE; + } + + pATEInfo->RFFreqOffset = RFFreqOffset; + + /* shift TX power control to correct RF register bit position */ + R4 = pATEInfo->RFFreqOffset << 15; + R4 |= (pAd->LatchRfRegs.R4 & ((~0x001f8000))); + pAd->LatchRfRegs.R4 = R4; + + RtmpRfIoWrite(pAd); + + return TRUE; +} + +struct _ATE_CHIP_STRUCT RALINK2883 = +{ + /* functions */ + .ChannelSwitch = RT2883ATEAsicSwitchChannel, + .TxPwrHandler = RT2883ATETxPwrHandler, + .TssiCalibration = NULL, + .ExtendedTssiCalibration = NULL, + .RxVGAInit = RT2883ATERxVGAInit, + .AsicSetTxRxPath = NULL, + .AdjustTxPower = DefaultATEAsicAdjustTxPower, + .AsicExtraPowerOverMAC = NULL, + + /* command handlers */ + .Set_BW_Proc = RT2883_Set_ATE_TX_BW_Proc, + .Set_FREQ_OFFSET_Proc = RT2883_Set_ATE_TX_FREQ_OFFSET_Proc, + + /* variables */ + .maxTxPwrCnt = 7, + .bBBPStoreTXCARR = TRUE, + .bBBPStoreTXCARRSUPP = TRUE, + .bBBPStoreTXCONT = TRUE, + .bBBPLoadATESTOP = TRUE, +}; + +#endif /* RT2883 */ + diff --git a/mt7620/src/ate/chips/rt28xx_ate.c b/mt7620/src/ate/chips/rt28xx_ate.c new file mode 100644 index 0000000..9306d77 --- /dev/null +++ b/mt7620/src/ate/chips/rt28xx_ate.c @@ -0,0 +1,823 @@ +/* + *************************************************************************** + * 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: + rt28xx_ate.c + + Abstract: + Specific ATE funcitons and variables for + RT2860 + RT2870 + RT2880 + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifdef RT28xx + +#include "rt_config.h" + +extern RTMP_RF_REGS RF2850RegTable[]; +extern UCHAR NUM_OF_2850_CHNL; + + +/* +========================================================================== + Description: + + AsicSwitchChannel() dedicated for RT28xx ATE. + +========================================================================== +*/ +VOID RT28xxATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 Value = 0; + CHAR TxPwer = 0, TxPwer2 = 0; + UCHAR index = 0, BbpValue = 0, Channel = 0; + UINT32 R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0; + RTMP_RF_REGS *RFRegTable = NULL; + + SYNC_CHANNEL_WITH_QA(pATEInfo, &Channel); + + /* fill Tx power value */ + TxPwer = pATEInfo->TxPower0; + TxPwer2 = pATEInfo->TxPower1; + + RFRegTable = RF2850RegTable; + + switch (pAd->RfIcType) + { + /* But only 2850 and 2750 support 5.5GHz band... */ + case RFIC_2820: + case RFIC_2850: + case RFIC_2720: + case RFIC_2750: + for (index = 0; index < NUM_OF_2850_CHNL; index++) + { + if (Channel == RFRegTable[index].Channel) + { + R2 = RFRegTable[index].R2; + + /* If TX path is 1, bit 14 = 1. */ + if (pAd->Antenna.field.TxPath == 1) + { + R2 |= 0x4000; + } + + if (pAd->Antenna.field.TxPath == 2) + { + if (pATEInfo->TxAntennaSel == 1) + { + /* If TX Antenna select is 1 , bit 14 = 1; Disable Ant 2 */ + R2 |= 0x4000; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; /* 11100111B */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + } + else if (pATEInfo->TxAntennaSel == 2) + { + /* If TX Antenna select is 2 , bit 15 = 1; Disable Ant 1 */ + R2 |= 0x8000; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + } + else + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + } + } + + if (pAd->Antenna.field.RxPath == 2) + { + switch (pATEInfo->RxAntennaSel) + { + case 1: + R2 |= 0x20040; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x00; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + case 2: + R2 |= 0x10040; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x01; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + default: + R2 |= 0x40; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + /* Only enable two Antenna to receive. */ + BbpValue |= 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + } + } + else if (pAd->Antenna.field.RxPath == 1) + { + /* write 1 to off RxPath */ + R2 |= 0x20040; + } + + if (pAd->Antenna.field.RxPath == 3) + { + switch (pATEInfo->RxAntennaSel) + { + case 1: + R2 |= 0x20040; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x00; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + case 2: + R2 |= 0x10040; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x01; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + case 3: + R2 |= 0x30000; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x02; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + default: + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + } + } + + if (Channel > 14) + { + /* initialize R3, R4 */ + R3 = (RFRegTable[index].R3 & 0xffffc1ff); + R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pATEInfo->RFFreqOffset << 15); + + /* + According the Rory's suggestion to solve the middle range issue. + + 5.5G band power range : 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" + means the TX power reduce 7dB. + */ + /* R3 */ + if ((TxPwer >= -7) && (TxPwer < 0)) + { + TxPwer = (7+TxPwer); + R3 |= (TxPwer << 10); + DBGPRINT(RT_DEBUG_TRACE, ("ATEAsicSwitchChannel: TxPwer=%d \n", TxPwer)); + } + else + { + TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); + R3 |= (TxPwer << 10) | (1 << 9); + } + + /* R4 */ + if ((TxPwer2 >= -7) && (TxPwer2 < 0)) + { + TxPwer2 = (7+TxPwer2); + R4 |= (TxPwer2 << 7); + DBGPRINT(RT_DEBUG_TRACE, ("ATEAsicSwitchChannel: TxPwer2=%d \n", TxPwer2)); + } + else + { + TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); + R4 |= (TxPwer2 << 7) | (1 << 6); + } + } + else + { + /* Set TX power0. */ + R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); + /* Set frequency offset and TX power1. */ + R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pATEInfo->RFFreqOffset << 15) | (TxPwer2 <<6); + } + + /* based on BBP current mode before changing RF channel */ + if (pATEInfo->TxWI.BW == BW_40) + { + R4 |=0x200000; + } + + /* Update variables. */ + pAd->LatchRfRegs.Channel = Channel; + pAd->LatchRfRegs.R1 = RFRegTable[index].R1; + pAd->LatchRfRegs.R2 = R2; + pAd->LatchRfRegs.R3 = R3; + pAd->LatchRfRegs.R4 = R4; + + RtmpRfIoWrite(pAd); + + break; + } + } + break; + + default: + break; + } + + /* Change BBP setting during switch from a->g, g->a */ + if (Channel <= 14) + { + UINT32 TxPinCfg = 0x00050F0A;/* 2007.10.09 by Brian : 0x0005050A ==> 0x00050F0A */ + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + + /* According the Rory's suggestion to solve the middle range issue. */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0); + + /* Rx High power VGA offset for LNA select */ + if (pAd->NicConfig2.field.ExternalLNAForG) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + /* 2.4 G band selection PIN */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x04); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + /* 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; + } + + /* calibration power unbalance issues */ + if (pAd->Antenna.field.TxPath == 2) + { + if (pATEInfo->TxAntennaSel == 1) + { + TxPinCfg &= 0xFFFFFFF7; + } + else if (pATEInfo->TxAntennaSel == 2) + { + TxPinCfg &= 0xFFFFFFFD; + } + } + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + } + /* channel > 14 */ + else + { + UINT32 TxPinCfg = 0x00050F05;/* 2007.10.09 by Brian : 0x00050505 ==> 0x00050F05 */ + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + + /* According the Rory's suggestion to solve the middle range issue. */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0); + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2); + + /* Rx High power VGA offset for LNA select */ + if (pAd->NicConfig2.field.ExternalLNAForA) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R91, &BbpValue); + ASSERT((BbpValue == 0x04)); + + /* 5 G band selection PIN, bit1 and bit2 are complement */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x02); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + /* 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); + } + + ATE_CHIP_RX_VGA_GAIN_INIT(pAd); + + RtmpOsMsDelay(1); + +#ifndef RTMP_RF_RW_SUPPORT + if (Channel > 14) + { + /* When 5.5GHz band the LSB of TxPwr will be used to reduced 7dB or not. */ + DBGPRINT(RT_DEBUG_TRACE, ("RT28xx:SwitchChannel#%d(RF=%d, %dT) to , R1=0x%08x, R2=0x%08x, R3=0x%08x, R4=0x%08x\n", + Channel, + pAd->RfIcType, + pAd->Antenna.field.TxPath, + pAd->LatchRfRegs.R1, + pAd->LatchRfRegs.R2, + pAd->LatchRfRegs.R3, + pAd->LatchRfRegs.R4)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("RT28xx:SwitchChannel#%d(RF=%d, Pwr0=%u, Pwr1=%u, %dT) to , R1=0x%08x, R2=0x%08x, R3=0x%08x, R4=0x%08x\n", + Channel, + pAd->RfIcType, + (R3 & 0x00003e00) >> 9, + (R4 & 0x000007c0) >> 6, + pAd->Antenna.field.TxPath, + pAd->LatchRfRegs.R1, + pAd->LatchRfRegs.R2, + pAd->LatchRfRegs.R3, + pAd->LatchRfRegs.R4)); + } +#endif /* !RTMP_RF_RW_SUPPORT */ +} + + +INT RT28xxATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index) +{ + PATE_INFO pATEInfo = &(pAd->ate); + ULONG R; + CHAR TxPower = 0; + UCHAR Bbp94 = 0; + BOOLEAN bPowerReduce = FALSE; + +#ifdef RALINK_QA + if ((pATEInfo->bQATxStart == TRUE) || (pATEInfo->bQARxStart == TRUE)) + { + return 0; + } + else +#endif /* RALINK_QA */ + if (index == 0) + { + TxPower = pATEInfo->TxPower0; + } + else if (index == 1) + { + TxPower = pATEInfo->TxPower1; + } + else + { + DBGPRINT_ERR(("%s : Only TxPower0 and TxPower1 are adjustable !\n", __FUNCTION__)); + DBGPRINT_ERR(("%s : TxPower%d is out of range !\n", __FUNCTION__, index)); + return -1; + } + + if (pATEInfo->Channel <= 14) + { + if (TxPower > 31) + { + /* R3, R4 can't large than 31 (0x24), 31 ~ 36 used by BBP 94 */ + R = 31; + if (TxPower <= 36) + Bbp94 = BBPR94_DEFAULT + (UCHAR)(TxPower - 31); + } + else if (TxPower < 0) + { + /* R3, R4 can't less than 0, -1 ~ -6 used by BBP 94 */ + R = 0; + if (TxPower >= -6) + Bbp94 = BBPR94_DEFAULT + TxPower; + } + else + { + /* 0 ~ 31 */ + R = (ULONG) TxPower; + Bbp94 = BBPR94_DEFAULT; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s : (TxPower=%d, R=%ld, BBP_R94=%d)\n", __FUNCTION__, TxPower, R, Bbp94)); + } + else /* 5.5 GHz */ + { + if (TxPower > 15) + { + /* R3, R4 can't large than 15 (0x0F) */ + R = 15; + } + else if (TxPower < 0) + { + /* R3, R4 can't less than 0 */ + /* -1 ~ -7 */ + ASSERT((TxPower >= -7)); + R = (ULONG)(TxPower + 7); + bPowerReduce = TRUE; + } + else + { + /* 0 ~ 15 */ + R = (ULONG) TxPower; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s : (TxPower=%d, R=%lu)\n", __FUNCTION__, TxPower, R)); + } + + if (pATEInfo->Channel <= 14) + { + if (index == 0) + { + /* shift TX power control to correct RF(R3) register bit position */ + R = R << 9; + R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); + pAd->LatchRfRegs.R3 = R; + } + else + { + /* shift TX power control to correct RF(R4) register bit position */ + R = R << 6; + R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); + pAd->LatchRfRegs.R4 = R; + } + } + else /* 5.5GHz */ + { + if (bPowerReduce == FALSE) + { + if (index == 0) + { + /* shift TX power control to correct RF(R3) register bit position */ + R = (R << 10) | (1 << 9); + R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); + pAd->LatchRfRegs.R3 = R; + } + else + { + /* shift TX power control to correct RF(R4) register bit position */ + R = (R << 7) | (1 << 6); + R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); + pAd->LatchRfRegs.R4 = R; + } + } + else + { + if (index == 0) + { + /* shift TX power control to correct RF(R3) register bit position */ + R = (R << 10); + R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); + + /* Clear bit 9 of R3 to reduce 7dB. */ + pAd->LatchRfRegs.R3 = (R & (~(1 << 9))); + } + else + { + /* shift TX power control to correct RF(R4) register bit position */ + R = (R << 7); + R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); + + /* Clear bit 6 of R4 to reduce 7dB. */ + pAd->LatchRfRegs.R4 = (R & (~(1 << 6))); + } + } + } + RtmpRfIoWrite(pAd); + + return 0; +} + + +VOID RT28xxATERxVGAInit( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR R66; + CHAR LNAGain = GET_LNA_GAIN(pAd); + + if (pATEInfo->Channel <= 14) + { + /* BG band */ + R66 = (UCHAR)(0x2E + LNAGain); + } + else + { + /* A band */ + if (pATEInfo->TxWI.BW == BW_20) + { + /* A band, BW == 20 */ + R66 = (UCHAR)(0x32 + (LNAGain*5)/3); + } + else + { + /* A band, BW == 40 */ + R66 = (UCHAR)(0x3A + (LNAGain*5)/3); + } + } + + ATEBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + + + return; +} + + +/* +========================================================================== + Description: + Set RT28xx/RT2880 ATE RF BW + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT RT28xx_Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + INT powerIndex; + UCHAR value = 0; + UCHAR BBPCurrentBW; + + BBPCurrentBW = simple_strtol(arg, 0, 10); + + if (BBPCurrentBW == 0) + { + pATEInfo->TxWI.BW = BW_20; + } + else + { + pATEInfo->TxWI.BW = BW_40; + } + + if ((pATEInfo->TxWI.PHYMODE == MODE_CCK) && (pATEInfo->TxWI.BW == BW_40)) + { + DBGPRINT_ERR(("Set_ATE_TX_BW_Proc!! Warning!! CCK only supports 20MHZ!!\n")); + DBGPRINT_ERR(("Bandwidth switch to 20!!\n")); + pATEInfo->TxWI.BW = BW_20; + } + + if (pATEInfo->TxWI.BW == BW_20) + { + if (pATEInfo->Channel <= 14) + { + /* BW=20;G band */ + for (powerIndex=0; powerIndexTx20MPwrCfgGBand[powerIndex] == 0xffffffff) + continue; + + /* TX_PWR_CFG_0 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx20MPwrCfgGBand[powerIndex]); + RtmpOsMsDelay(5); + } + } + else + { + /* BW=20;A band */ + for (powerIndex=0; powerIndexTx20MPwrCfgABand[powerIndex] == 0xffffffff) + continue; + + /* TX_PWR_CFG_0 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx20MPwrCfgABand[powerIndex]); + RtmpOsMsDelay(5); + } + } + + /* set BW = 20 MHz */ + /* Set BBP R4 bit[4:3]=0:0 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value &= (~0x18); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + /* Set BBP R66=0x3C */ + value = 0x3C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value); + + /* set BW = 20 MHz */ + pAd->LatchRfRegs.R4 &= ~0x00200000; + RtmpRfIoWrite(pAd); + + /* BW = 20 MHz */ + /* Set BBP R68=0x0B to improve Rx sensitivity. */ + value = 0x0B; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + /* Set BBP R69=0x16 */ + value = 0x16; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + /* Set BBP R70=0x08 */ + value = 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + /* Set BBP R73=0x11 */ + value = 0x11; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + + if (pATEInfo->Channel == 14) + { + INT TxMode = pATEInfo->TxWI.PHYMODE; + + if (TxMode == MODE_CCK) + { + /* when Channel==14 && Mode==CCK && BandWidth==20M, BBP R4 bit5=1 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value |= 0x20; /* set bit5=1 */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + } + } + } + /* If bandwidth = 40M, set RF Reg4 bit 21 = 0. */ + else if (pATEInfo->TxWI.BW == BW_40) + { + if (pATEInfo->Channel <= 14) + { + /* BW=40;G band */ + for (powerIndex=0; powerIndexTx40MPwrCfgGBand[powerIndex] == 0xffffffff) + continue; + + /* TX_PWR_CFG_0 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx40MPwrCfgGBand[powerIndex]); + RtmpOsMsDelay(5); + } + } + else + { + /* BW=40;A band */ + for (powerIndex=0; powerIndexTx40MPwrCfgABand[powerIndex] == 0xffffffff) + continue; + + /* TX_PWR_CFG_0 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx40MPwrCfgABand[powerIndex]); + RtmpOsMsDelay(5); + } + + if ((pATEInfo->TxWI.PHYMODE >= 2) && (pATEInfo->TxWI.MCS == 7)) + { + value = 0x28; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R67, value); + } + } + + /* Set BBP R4 bit[4:3]=1:0 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value &= (~0x18); + value |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + /* Set BBP R66=0x3C */ + value = 0x3C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value); + + /* set BW = 40 MHz */ + pAd->LatchRfRegs.R4 |= 0x00200000; + RtmpRfIoWrite(pAd); + + /* BW = 40 MHz */ + /* Set BBP R68=0x0C to improve Rx sensitivity. */ + value = 0x0C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + /* Set BBP R69=0x1A */ + value = 0x1A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + /* Set BBP R70=0x0A */ + value = 0x0A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + /* Set BBP R73=0x16 */ + value = 0x16; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + } + + return TRUE; +} + + +INT RT28xx_Set_ATE_TX_FREQ_OFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + ULONG R4 = 0; + UCHAR RFFreqOffset = 0; + + RFFreqOffset = simple_strtol(arg, 0, 10); + + if (RFFreqOffset >= 64) + { + DBGPRINT_ERR(("Set_ATE_TX_FREQ_OFFSET_Proc::Out of range(0 ~ 63).\n")); + return FALSE; + } + + pATEInfo->RFFreqOffset = RFFreqOffset; + + /* shift TX power control to correct RF register bit position */ + R4 = pATEInfo->RFFreqOffset << 15; + R4 |= (pAd->LatchRfRegs.R4 & ((~0x001f8000))); + pAd->LatchRfRegs.R4 = R4; + + RtmpRfIoWrite(pAd); + + return TRUE; +} + +#ifdef RT2860 +struct _ATE_CHIP_STRUCT RALINK2860 = +{ + /* functions */ + .ChannelSwitch = RT28xxATEAsicSwitchChannel, + .TxPwrHandler = RT28xxATETxPwrHandler, + .TssiCalibration = NULL, + .ExtendedTssiCalibration = NULL, + .RxVGAInit = RT28xxATERxVGAInit, + .AsicSetTxRxPath = NULL, + .AdjustTxPower = DefaultATEAsicAdjustTxPower, + .AsicExtraPowerOverMAC = NULL, + + /* command handlers */ + .Set_BW_Proc = RT28xx_Set_ATE_TX_BW_Proc, + .Set_FREQ_OFFSET_Proc = RT28xx_Set_ATE_TX_FREQ_OFFSET_Proc, + + /* variables */ + .maxTxPwrCnt = 5, + .bBBPStoreTXCARR = FALSE, + .bBBPStoreTXCARRSUPP = FALSE, + .bBBPStoreTXCONT = FALSE, + .bBBPLoadATESTOP = FALSE, +}; +#endif /* RT2860 */ + + +#ifdef RT2880 +struct _ATE_CHIP_STRUCT RALINK2880 = +{ + /* functions */ + .ChannelSwitch = RT28xxATEAsicSwitchChannel, + .TxPwrHandler = RT28xxATETxPwrHandler, + .TssiCalibration = NULL, + .ExtendedTssiCalibration = NULL, + .RxVGAInit = RT28xxATERxVGAInit, + .AsicSetTxRxPath = NULL, + .AdjustTxPower = DefaultATEAsicAdjustTxPower, + .AsicExtraPowerOverMAC = NULL, + + /* command handlers */ + .Set_BW_Proc = RT28xx_Set_ATE_TX_BW_Proc, + .Set_FREQ_OFFSET_Proc = RT28xx_Set_ATE_TX_FREQ_OFFSET_Proc, + + /* variables */ + .maxTxPwrCnt = 5, + .bBBPStoreTXCARR = FALSE, + .bBBPStoreTXCARRSUPP = FALSE, + .bBBPStoreTXCONT = FALSE, + .bBBPLoadATESTOP = FALSE, +}; +#endif /* RT2880 */ + +#endif /*RT28xx */ + diff --git a/mt7620/src/ate/chips/rt305x_ate.c b/mt7620/src/ate/chips/rt305x_ate.c new file mode 100644 index 0000000..491acbc --- /dev/null +++ b/mt7620/src/ate/chips/rt305x_ate.c @@ -0,0 +1,1983 @@ +/* + *************************************************************************** + * 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: + rt305x_ate.c + + Abstract: + Specific ATE funcitons and variables for RT305x(i.e., RT3050/RT3051/RT3052) + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifdef RT305x + +#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 */ + +extern FREQUENCY_ITEM RtmpFreqItems3020[]; +extern UCHAR NUM_OF_3020_CHNL; + + +#ifdef RT3050 +/* +========================================================================== + Description: + + AsicSwitchChannel() dedicated for RT3050 ATE. + +========================================================================== +*/ +VOID RT3050ATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 Value = 0; + CHAR TxPwer = 0, TxPwer2 = 0; + UCHAR index = 0, BbpValue = 0, Channel = 0; + /* added to prevent RF register reading error */ + UCHAR RFValue = 0, RFValue2 = 0; + + SYNC_CHANNEL_WITH_QA(pATEInfo, &Channel); + + /* fill Tx power value */ + TxPwer = pATEInfo->TxPower0; + TxPwer2 = pATEInfo->TxPower1; + + if ((pAd->RfIcType == RFIC_3022) || (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3020) || \ + (pAd->RfIcType == RFIC_3320) || (pAd->RfIcType == RFIC_3322)) + { + UINT32 step=0; + + for (index = 0; index < NUM_OF_3020_CHNL; index++) + { + /* Please don't change "RtmpFreqItems3020" to "FreqItems3020" ! */ + if (Channel == RtmpFreqItems3020[index].Channel) + { + /* programming channel parameters */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R02, RtmpFreqItems3020[index].N); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R03, RtmpFreqItems3020[index].K); + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R06, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xFC) | RtmpFreqItems3020[index].R; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R06, (UCHAR)RFValue); + + /* set tx power0 */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R12, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xE0) | TxPwer; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R12, (UCHAR)RFValue); + + /* set tx power1 */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R13, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xE0) | TxPwer2; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R13, (UCHAR)RFValue); + + /* set RF offset */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R23, (PUCHAR)&RFValue); + RFValue2 = (RFValue & 0x80) | pATEInfo->RFFreqOffset; + + if (RFValue2 > RFValue) + { + for (step = 1; step <= (RFValue2 - RFValue); step++) + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R23, (UCHAR)(RFValue + step)); + RtmpOsMsDelay(10); + } + } + else + { + for (step = 1; step <= (RFValue - RFValue2); step++) + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R23, (UCHAR)(RFValue - step)); + RtmpOsMsDelay(10); + } + } + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R24, (PUCHAR)&RFValue); + RFValue &= 0xDF; + if (pATEInfo->TxWI.BW == BW_40) + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R31, 0x2F); + RFValue |= 0x20; + } + else + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R31, 0x0F); + } + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R24, (UCHAR)RFValue); + + /* RF Rx antenna selection */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R01, (PUCHAR)&RFValue); + RFValue = (RFValue & 0x03) | 0xC1; + + if (pATEInfo->RxAntennaSel == 1) + { + RFValue = RFValue | 0x10; + } + else if (pATEInfo->RxAntennaSel == 2) + { + RFValue = RFValue | 0x04; + } + + /* RF Tx antenna selection */ + if (pATEInfo->TxAntennaSel == 1) + { + RFValue = RFValue | 0x20; + } + else if (pATEInfo->TxAntennaSel == 2) + { + RFValue = RFValue | 0x08; + } + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R01, (UCHAR)RFValue); + + /* BBP Rx antenna selection */ + if (pATEInfo->RxAntennaSel == 1) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, 0x0); + } + else if (pATEInfo->RxAntennaSel == 2) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, 0x1); + } + else + { + /* RXANT_NUM >= 2, must turn on Bit 0 and 1 for all ADCs */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, 0xB); + } + + /* enable RF tuning */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R07, (PUCHAR)&RFValue); + RFValue = RFValue | 0x1; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R07, (UCHAR)RFValue); + + /* latch channel for future usage */ + pAd->LatchRfRegs.Channel = Channel; + break; + } + } + } + + /* Change BBP setting during switch from a->g, g->a */ + if (Channel <= 14) + { + UINT32 TxPinCfg = 0x00050F0A;/* 2007.10.09 by Brian : 0x0005050A ==> 0x00050F0A */ + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + + /* According the Rory's suggestion to solve the middle range issue. */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0); + + /* Rx High power VGA offset for LNA select */ + if (pAd->NicConfig2.field.ExternalLNAForG) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + /* 2.4 G band selection PIN */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x04); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + /* 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; + } + + /* calibration power unbalance issues */ + if (pAd->Antenna.field.TxPath == 2) + { + if (pATEInfo->TxAntennaSel == 1) + { + TxPinCfg &= 0xFFFFFFF7; + } + else if (pATEInfo->TxAntennaSel == 2) + { + TxPinCfg &= 0xFFFFFFFD; + } + } + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + } + /* channel > 14 */ + else + { + UINT32 TxPinCfg = 0x00050F05;/* 2007.10.09 by Brian : 0x00050505 ==> 0x00050F05 */ + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + + /* According the Rory's suggestion to solve the middle range issue. */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0); + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2); + + /* Rx High power VGA offset for LNA select */ + if (pAd->NicConfig2.field.ExternalLNAForA) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R91, &BbpValue); + ASSERT((BbpValue == 0x04)); + + /* 5 G band selection PIN, bit1 and bit2 are complement */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x02); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + /* 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); + } + + ATE_CHIP_RX_VGA_GAIN_INIT(pAd); + + RtmpOsMsDelay(1); + + DBGPRINT(RT_DEBUG_TRACE, ("RT3050:SwitchChannel#%d(RFIC=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", + Channel, + pAd->RfIcType, + TxPwer, + TxPwer2, + pAd->Antenna.field.TxPath, + RtmpFreqItems3020[index].N, + RtmpFreqItems3020[index].K, + RtmpFreqItems3020[index].R)); +} +#endif /* RT3050 */ + + +#ifdef RT3052 +/* +========================================================================== + Description: + + AsicSwitchChannel() dedicated for RT3052 ATE. + +========================================================================== +*/ +VOID RT3052ATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 Value = 0; + CHAR TxPwer = 0, TxPwer2 = 0; + UCHAR index = 0, BbpValue = 0, Channel = 0; + /* added to prevent RF register reading error */ + UCHAR RFValue = 0, RFValue2 = 0; + + SYNC_CHANNEL_WITH_QA(pATEInfo, &Channel); + + /* fill Tx power value */ + TxPwer = pATEInfo->TxPower0; + TxPwer2 = pATEInfo->TxPower1; + + if ((pAd->RfIcType == RFIC_3022) || (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3020) || \ + (pAd->RfIcType == RFIC_3320) || (pAd->RfIcType == RFIC_3322)) + { + UINT32 step=0; + + for (index = 0; index < NUM_OF_3020_CHNL; index++) + { + /* Please don't change "RtmpFreqItems3020" to "FreqItems3020" ! */ + if (Channel == RtmpFreqItems3020[index].Channel) + { + /* programming channel parameters */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R02, RtmpFreqItems3020[index].N); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R03, RtmpFreqItems3020[index].K); + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R06, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xFC) | RtmpFreqItems3020[index].R; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R06, (UCHAR)RFValue); + + /* set tx power0 */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R12, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xE0) | TxPwer; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R12, (UCHAR)RFValue); + + /* set tx power1 */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R13, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xE0) | TxPwer2; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R13, (UCHAR)RFValue); + + /* set RF offset */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R23, (PUCHAR)&RFValue); + RFValue2 = (RFValue & 0x80) | pATEInfo->RFFreqOffset; + + if (RFValue2 > RFValue) + { + for (step = 1; step <= (RFValue2 - RFValue); step++) + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R23, (UCHAR)(RFValue + step)); + RtmpOsMsDelay(10); + } + } + else + { + for (step = 1; step <= (RFValue - RFValue2); step++) + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R23, (UCHAR)(RFValue - step)); + RtmpOsMsDelay(10); + } + } + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R24, (PUCHAR)&RFValue); + RFValue &= 0xDF; + if (pATEInfo->TxWI.BW == BW_40) + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R31, 0x2F); + RFValue |= 0x20; + } + else + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R31, 0x0F); + } + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R24, (UCHAR)RFValue); + + /* RF Rx antenna selection */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R01, (PUCHAR)&RFValue); + RFValue = (RFValue & 0x03) | 0xC1; + + if (pATEInfo->RxAntennaSel == 1) + { + RFValue = RFValue | 0x10; + } + else if (pATEInfo->RxAntennaSel == 2) + { + RFValue = RFValue | 0x04; + } + + /* RF Tx antenna selection */ + if (pATEInfo->TxAntennaSel == 1) + { + RFValue = RFValue | 0x20; + } + else if (pATEInfo->TxAntennaSel == 2) + { + RFValue = RFValue | 0x08; + } + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R01, (UCHAR)RFValue); + + /* BBP Rx antenna selection */ + if (pATEInfo->RxAntennaSel == 1) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, 0x0); + } + else if (pATEInfo->RxAntennaSel == 2) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, 0x1); + } + else + { + /* RXANT_NUM >= 2, must turn on Bit 0 and 1 for all ADCs */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, 0xB); + } + + /* enable RF tuning */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R07, (PUCHAR)&RFValue); + RFValue = RFValue | 0x1; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R07, (UCHAR)RFValue); + + /* calibrate power unbalance issues */ + if (pAd->Antenna.field.TxPath == 2) + { + if (pATEInfo->TxAntennaSel == 1) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; /* DAC0 (11100111B) */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + } + else if (pATEInfo->TxAntennaSel == 2) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x08; /* DAC1 */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + } + else + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + } + } + + /* latch channel for future usage */ + pAd->LatchRfRegs.Channel = Channel; + break; + } + } + } + + /* Change BBP setting during switch from a->g, g->a */ + if (Channel <= 14) + { + UINT32 TxPinCfg = 0x00050F0A;/* 2007.10.09 by Brian : 0x0005050A ==> 0x00050F0A */ + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + + /* According the Rory's suggestion to solve the middle range issue. */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0); + + /* Rx High power VGA offset for LNA select */ + if (pAd->NicConfig2.field.ExternalLNAForG) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + /* 2.4 G band selection PIN */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x04); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + /* 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; + } + + /* calibration power unbalance issues */ + if (pAd->Antenna.field.TxPath == 2) + { + if (pATEInfo->TxAntennaSel == 1) + { + TxPinCfg &= 0xFFFFFFF7; + } + else if (pATEInfo->TxAntennaSel == 2) + { + TxPinCfg &= 0xFFFFFFFD; + } + } + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + } + /* channel > 14 */ + else + { + UINT32 TxPinCfg = 0x00050F05;/* 2007.10.09 by Brian : 0x00050505 ==> 0x00050F05 */ + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + + /* According the Rory's suggestion to solve the middle range issue. */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0); + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2); + + /* Rx High power VGA offset for LNA select */ + if (pAd->NicConfig2.field.ExternalLNAForA) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R91, &BbpValue); + ASSERT((BbpValue == 0x04)); + + /* 5 G band selection PIN, bit1 and bit2 are complement */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x02); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + /* 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); + } + + ATE_CHIP_RX_VGA_GAIN_INIT(pAd); + + RtmpOsMsDelay(1); + + DBGPRINT(RT_DEBUG_TRACE, ("RT3052:SwitchChannel#%d(RFIC=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", + Channel, + pAd->RfIcType, + TxPwer, + TxPwer2, + pAd->Antenna.field.TxPath, + RtmpFreqItems3020[index].N, + RtmpFreqItems3020[index].K, + RtmpFreqItems3020[index].R)); +} +#endif /* RT3052 */ + + +#ifdef RT3350 +/* +========================================================================== + Description: + + AsicSwitchChannel() dedicated for RT3350 ATE. + +========================================================================== +*/ +VOID RT3350ATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 Value = 0; + CHAR TxPwer = 0, TxPwer2 = 0; + UCHAR index = 0, BbpValue = 0, Channel = 0; + /* added to prevent RF register reading error */ + UCHAR RFValue = 0, RFValue2 = 0; + + SYNC_CHANNEL_WITH_QA(pATEInfo, &Channel); + + /* fill Tx power value */ + TxPwer = pATEInfo->TxPower0; + TxPwer2 = pATEInfo->TxPower1; + + if ((pAd->RfIcType == RFIC_3022) || (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3020) || \ + (pAd->RfIcType == RFIC_3320) || (pAd->RfIcType == RFIC_3322)) + { + UINT32 step=0; + + for (index = 0; index < NUM_OF_3020_CHNL; index++) + { + /* Please don't change "RtmpFreqItems3020" to "FreqItems3020" ! */ + if (Channel == RtmpFreqItems3020[index].Channel) + { + /* programming channel parameters */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R02, RtmpFreqItems3020[index].N); + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R03, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xF0) | (RtmpFreqItems3020[index].K & 0x0F); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R03, (UCHAR)RFValue); + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R06, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xFC) | RtmpFreqItems3020[index].R; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R06, (UCHAR)RFValue); + + /* set tx power0 */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R12, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xE0) | TxPwer; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R12, (UCHAR)RFValue); + + /* set tx power1 */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R13, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xE0) | TxPwer2; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R13, (UCHAR)RFValue); + + /* set RF offset */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R23, (PUCHAR)&RFValue); + RFValue2 = (RFValue & 0x80) | pATEInfo->RFFreqOffset; + + if (RFValue2 > RFValue) + { + for (step = 1; step <= (RFValue2 - RFValue); step++) + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R23, (UCHAR)(RFValue + step)); + RtmpOsMsDelay(10); + } + } + else + { + for (step = 1; step <= (RFValue - RFValue2); step++) + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R23, (UCHAR)(RFValue - step)); + RtmpOsMsDelay(10); + } + } + + /* set RF_R24 and RF_R31 */ + if (pATEInfo->TxWI.BW == BW_40) + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R31, 0x68); + + if(pATEInfo->TxWI.PHYMODE == MODE_CCK) + RFValue = 0x3F; + else + RFValue = 0x28; + } + else + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R31, 0x48); + + if (pATEInfo->TxWI.PHYMODE == MODE_CCK) + RFValue = 0x1F; + else if (pATEInfo->TxWI.PHYMODE == MODE_OFDM) + RFValue = 0x18; + else + RFValue = 0x10;/* Simba:2010.02.04 */ + } + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R24, (UCHAR)RFValue); + + /* RF Rx antenna selection */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R01, (PUCHAR)&RFValue); + RFValue = (RFValue & 0x03) | 0xC1; + + if (pATEInfo->RxAntennaSel == 1) + { + RFValue = RFValue | 0x10; + } + else if (pATEInfo->RxAntennaSel == 2) + { + RFValue = RFValue | 0x04; + } + + /* RF Tx antenna selection */ + if (pATEInfo->TxAntennaSel == 1) + { + RFValue = RFValue | 0x20; + } + else if (pATEInfo->TxAntennaSel == 2) + { + RFValue = RFValue | 0x08; + } + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R01, (UCHAR)RFValue); + + /* BBP Rx antenna selection */ + if (pATEInfo->RxAntennaSel == 1) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, 0x0); + } + else if (pATEInfo->RxAntennaSel == 2) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, 0x1); + } + else + { + /* RXANT_NUM >= 2, must turn on Bit 0 and 1 for all ADCs */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, 0xB); + } + + /* enable RF tuning */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R07, (PUCHAR)&RFValue); + RFValue = RFValue | 0x1; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R07, (UCHAR)RFValue); + + /* latch channel for future usage */ + pAd->LatchRfRegs.Channel = Channel; + break; + } + } + } + + /* Change BBP setting during switch from a->g, g->a */ + if (Channel <= 14) + { + UINT32 TxPinCfg = 0x00050F0A;/* 2007.10.09 by Brian : 0x0005050A ==> 0x00050F0A */ + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + + /* According the Rory's suggestion to solve the middle range issue. */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0); + + /* Rx High power VGA offset for LNA select */ + if (pAd->NicConfig2.field.ExternalLNAForG) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + /* 2.4 G band selection PIN */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x04); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + /* 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; + } + + /* calibration power unbalance issues */ + if (pAd->Antenna.field.TxPath == 2) + { + if (pATEInfo->TxAntennaSel == 1) + { + TxPinCfg &= 0xFFFFFFF7; + } + else if (pATEInfo->TxAntennaSel == 2) + { + TxPinCfg &= 0xFFFFFFFD; + } + } + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + } + /* channel > 14 */ + else + { + UINT32 TxPinCfg = 0x00050F05;/* 2007.10.09 by Brian : 0x00050505 ==> 0x00050F05 */ + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + + /* According the Rory's suggestion to solve the middle range issue. */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0); + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2); + + /* Rx High power VGA offset for LNA select */ + if (pAd->NicConfig2.field.ExternalLNAForA) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R91, &BbpValue); + ASSERT((BbpValue == 0x04)); + + /* 5 G band selection PIN, bit1 and bit2 are complement */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x02); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + /* 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); + } + + ATE_CHIP_RX_VGA_GAIN_INIT(pAd); + + RtmpOsMsDelay(1); + + DBGPRINT(RT_DEBUG_TRACE, ("RT3350:SwitchChannel#%d(RFIC=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", + Channel, + pAd->RfIcType, + TxPwer, + TxPwer2, + pAd->Antenna.field.TxPath, + RtmpFreqItems3020[index].N, + RtmpFreqItems3020[index].K, + RtmpFreqItems3020[index].R)); +} +#endif /* RT3350 */ + + +#if defined(RT3050) || defined(RT3052) || defined(RT3350) +/* This routine is also for RT3050/RT3052/RT3350 */ +INT RT305xATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index) +{ + PATE_INFO pATEInfo = &(pAd->ate); + CHAR TxPower = 0; + UCHAR RFValue = 0; + +#ifdef RALINK_QA + if ((pATEInfo->bQATxStart == TRUE) || (pATEInfo->bQARxStart == TRUE)) + { + return 0; + } + else +#endif /* RALINK_QA */ + if (index == 0) + { + TxPower = pATEInfo->TxPower0; + } + else if (index == 1) + { + TxPower = pATEInfo->TxPower1; + } + else + { + DBGPRINT_ERR(("%s : Only TxPower0 and TxPower1 are adjustable !\n", __FUNCTION__)); + DBGPRINT_ERR(("%s : TxPower%d is out of range !\n", __FUNCTION__, index)); + return -1; + } + + if (index == 0) + { + /* Set Tx0 Power */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R12, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xE0) | TxPower; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R12, (UCHAR)RFValue); + } + + if (index == 1) + { + /* Set Tx1 Power */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R13, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xE0) | TxPower; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R13, (UCHAR)RFValue); + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s : (TxPower%d=%d, RFValue=%x)\n", __FUNCTION__, index, TxPower, RFValue)); + + return 0; +} + + +VOID RT305xATERxVGAInit( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR R66; + CHAR LNAGain = GET_LNA_GAIN(pAd); + + if (pATEInfo->Channel <= 14) + { + /* BG band */ + R66 = (UCHAR)(0x2E + LNAGain); + } + else + { + /* A band. Not supported. */ + DBGPRINT_ERR(("%s :Ch=%d\n", __FUNCTION__, pATEInfo->Channel)); + DBGPRINT_ERR(("%s :5 GHz band not supported !\n", __FUNCTION__)); + + return; + } + + ATEBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + + + return; +} +#endif /* defined(RT3050) || defined(RT3052) || defined(RT3350) */ + + +#if defined(RT3050) || defined(RT3052) +/* +========================================================================== + Description: + Set RT3050/RT3052 ATE RF BW + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT RT305x_Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + INT powerIndex; + UCHAR value = 0; + UCHAR BBPCurrentBW; + + BBPCurrentBW = simple_strtol(arg, 0, 10); + + if (BBPCurrentBW == 0) + { + pATEInfo->TxWI.BW = BW_20; + } + else + { + pATEInfo->TxWI.BW = BW_40; + } + + if ((pATEInfo->TxWI.PHYMODE == MODE_CCK) && (pATEInfo->TxWI.BW == BW_40)) + { + DBGPRINT_ERR(("Set_ATE_TX_BW_Proc!! Warning!! CCK only supports 20MHZ!!\n")); + DBGPRINT_ERR(("Bandwidth switch to 20!!\n")); + pATEInfo->TxWI.BW = BW_20; + } + + if (pATEInfo->TxWI.BW == BW_20) + { + if (pATEInfo->Channel <= 14) + { + /* BW=20;G band */ + for (powerIndex=0; powerIndexTx20MPwrCfgGBand[powerIndex] == 0xffffffff) + continue; + + /* TX_PWR_CFG_0 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx20MPwrCfgGBand[powerIndex]); + RtmpOsMsDelay(5); + } + } + else + { + /* BW=20;A band */ + for (powerIndex=0; powerIndexTx20MPwrCfgABand[powerIndex] == 0xffffffff) + continue; + + /* TX_PWR_CFG_0 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx20MPwrCfgABand[powerIndex]); + RtmpOsMsDelay(5); + } + } + + /* BW = 20 MHz */ + /* Set BBP R4 bit[4:3]=0:0 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value &= (~0x18); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + /* Set BBP R66=0x3C */ + value = 0x3C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value); + + /* set BW */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R24, (PUCHAR)&value); + value &= 0xDF; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R24, (UCHAR)value); + + /* Rx filter */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R31, 0x0F); + + /* BW = 20 MHz */ + /* Set BBP R68=0x0B to improve Rx sensitivity. */ + value = 0x0B; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + /* Set BBP R69=0x16 */ + value = 0x16; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + /* Set BBP R70=0x08 */ + value = 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + /* Set BBP R73=0x11 */ + value = 0x11; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + + if (pATEInfo->Channel == 14) + { + INT TxMode = pATEInfo->TxWI.PHYMODE; + + if (TxMode == MODE_CCK) + { + /* when Channel==14 && Mode==CCK && BandWidth==20M, BBP R4 bit5=1 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value |= 0x20; /* set bit5=1 */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + } + } + } + /* If bandwidth = 40M, set RF Reg4 bit 21 = 0. */ + else if (pATEInfo->TxWI.BW == BW_40) + { + if (pATEInfo->Channel <= 14) + { + /* BW=40;G band */ + for (powerIndex=0; powerIndexTx40MPwrCfgGBand[powerIndex] == 0xffffffff) + continue; + + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx40MPwrCfgGBand[powerIndex]); + RtmpOsMsDelay(5); + } + } + else + { + /* BW=40;A band */ + for (powerIndex=0; powerIndexTx40MPwrCfgABand[powerIndex] == 0xffffffff) + continue; + + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx40MPwrCfgABand[powerIndex]); + RtmpOsMsDelay(5); + } + + if ((pATEInfo->TxWI.PHYMODE >= 2) && (pATEInfo->TxWI.MCS == 7)) + { + value = 0x28; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R67, value); + } + } + + /* Set BBP R4 bit[4:3]=1:0 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value &= (~0x18); + value |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + /* Set BBP R66=0x3C */ + value = 0x3C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value); + + /* set BW */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R24, (PUCHAR)&value); + value &= 0xDF; + value |= 0x20; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R24, (UCHAR)value); + + /* Rx filter */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R31, 0x2F); + + /* Set BBP R68=0x0C to improve Rx sensitivity. */ + value = 0x0C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + /* Set BBP R69=0x1A */ + value = 0x1A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + /* Set BBP R70=0x0A */ + value = 0x0A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + /* Set BBP R73=0x16 */ + value = 0x16; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + } + + return TRUE; +} +#endif /* defined(RT3050) || defined(RT3052) */ + + +#ifdef RT3350 +/* +========================================================================== + Description: + Set RT3350 ATE RF BW + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT RT3350_Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + INT powerIndex; + UCHAR value = 0; + UCHAR BBPCurrentBW; + + BBPCurrentBW = simple_strtol(arg, 0, 10); + + if (BBPCurrentBW == 0) + { + pATEInfo->TxWI.BW = BW_20; + } + else + { + pATEInfo->TxWI.BW = BW_40; + } + + if ((pATEInfo->TxWI.PHYMODE == MODE_CCK) && (pATEInfo->TxWI.BW == BW_40)) + { + DBGPRINT_ERR(("Set_ATE_TX_BW_Proc!! Warning!! CCK only supports 20MHZ!!\n")); + DBGPRINT_ERR(("Bandwidth switch to 20!!\n")); + pATEInfo->TxWI.BW = BW_20; + } + + if (pATEInfo->TxWI.BW == BW_20) + { + if (pATEInfo->Channel <= 14) + { + /* BW=20;G band */ + for (powerIndex=0; powerIndexTx20MPwrCfgGBand[powerIndex] == 0xffffffff) + continue; + + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx20MPwrCfgGBand[powerIndex]); + RtmpOsMsDelay(5); + } + } + else + { + /* BW=20;A band */ + for (powerIndex=0; powerIndexTx20MPwrCfgABand[powerIndex] == 0xffffffff) + continue; + + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx20MPwrCfgABand[powerIndex]); + RtmpOsMsDelay(5); + } + } + + /* set BW = 20 MHz */ + /* Set BBP R4 bit[4:3]=0:0 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value &= (~0x18); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + /* Set BBP R66=0x3C */ + value = 0x3C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value); + + /* set RF_R24 */ + if(pATEInfo->TxWI.PHYMODE == MODE_CCK) + value = 0x1F; + else + value = 0x18; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R24, (UCHAR)value); + + /* Rx filter */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R31, 0x48); + + /* BW = 20 MHz */ + /* Set BBP R68=0x0B to improve Rx sensitivity. */ + value = 0x0B; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + /* Set BBP R69=0x16 */ + value = 0x16; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + /* Set BBP R70=0x08 */ + value = 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + /* Set BBP R73=0x11 */ + value = 0x11; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + + if (pATEInfo->Channel == 14) + { + INT TxMode = pATEInfo->TxWI.PHYMODE; + + if (TxMode == MODE_CCK) + { + /* when Channel==14 && Mode==CCK && BandWidth==20M, BBP R4 bit5=1 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value |= 0x20; /* set bit5=1 */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + } + } + } + /* If bandwidth = 40M, set RF Reg4 bit 21 = 0. */ + else if (pATEInfo->TxWI.BW == BW_40) + { + if (pATEInfo->Channel <= 14) + { + /* BW=40;G band */ + for (powerIndex=0; powerIndexTx40MPwrCfgGBand[powerIndex] == 0xffffffff) + continue; + + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx40MPwrCfgGBand[powerIndex]); + RtmpOsMsDelay(5); + } + } + else + { + /* BW=40;A band */ + for (powerIndex=0; powerIndexTx40MPwrCfgABand[powerIndex] == 0xffffffff) + continue; + + /* TX_PWR_CFG_0 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx40MPwrCfgABand[powerIndex]); + RtmpOsMsDelay(5); + } + + if ((pATEInfo->TxWI.PHYMODE >= 2) && (pATEInfo->TxWI.MCS == 7)) + { + value = 0x28; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R67, value); + } + } + + /* Set BBP R4 bit[4:3]=1:0 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value &= (~0x18); + value |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + /* Set BBP R66=0x3C */ + value = 0x3C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value); + + /* set RF_R24 */ + if(pATEInfo->TxWI.PHYMODE == MODE_CCK) + value = 0x3F; + else + value = 0x28; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R24, (UCHAR)value); + + /* Rx filter */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R31, 0x68); + + /* BW = 40 MHz */ + /* Set BBP R68=0x0C to improve Rx sensitivity. */ + value = 0x0C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + /* Set BBP R69=0x1A */ + value = 0x1A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + /* Set BBP R70=0x0A */ + value = 0x0A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + /* Set BBP R73=0x16 */ + value = 0x16; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + + } + + return TRUE; +} +#endif /* RT3350 */ + + +#if defined(RT3050) || defined(RT3052) +INT RT305x_Set_ATE_TX_FREQ_OFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR RFFreqOffset = 0; + UCHAR RFValue = 0; + UCHAR step = 0; + UCHAR RFValue2 = 0; + + RFFreqOffset = simple_strtol(arg, 0, 10); + + if (RFFreqOffset >= 96) + { + DBGPRINT_ERR(("Set_ATE_TX_FREQ_OFFSET_Proc::Out of range(0 ~ 95).\n")); + return FALSE; + } + + pATEInfo->RFFreqOffset = RFFreqOffset; + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R23, (PUCHAR)&RFValue); + RFValue2 = (RFValue & 0x80) | pATEInfo->RFFreqOffset; + + if (RFValue2 > RFValue) + { + for (step = 1; step <= (RFValue2 - RFValue); step++) + { + + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R23, (UCHAR)(RFValue + step)); + RtmpOsMsDelay(10); + } + } + else + { + for (step = 1; step <= (RFValue - RFValue2); step++) + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R23, (UCHAR)(RFValue - step)); + RtmpOsMsDelay(10); + } + } + + return TRUE; +} +#endif /* defined(RT3050) || defined(RT3052) */ + + +#ifdef RT3350 +INT RT3350_Set_ATE_TX_FREQ_OFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR RFFreqOffset = 0; + UCHAR RFValue = 0; + UCHAR step = 0; + UCHAR RFValue2 = 0; + + RFFreqOffset = simple_strtol(arg, 0, 10); + + if (RFFreqOffset >= 96) + { + DBGPRINT_ERR(("Set_ATE_TX_FREQ_OFFSET_Proc::Out of range(0 ~ 95).\n")); + return FALSE; + } + + pATEInfo->RFFreqOffset = RFFreqOffset; + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R23, (PUCHAR)&RFValue); + RFValue2 = (RFValue & 0x80) | pATEInfo->RFFreqOffset; + + if (RFValue2 > RFValue) + { + for (step = 1; step <= (RFValue2 - RFValue); step++) + { + + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R23, (UCHAR)(RFValue + step)); + RtmpOsMsDelay(10); + } + } + else + { + for (step = 1; step <= (RFValue - RFValue2); step++) + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R23, (UCHAR)(RFValue - step)); + RtmpOsMsDelay(10); + } + } + + return TRUE; +} +#endif /* RT3350 */ + + +#ifdef RT3350 +VOID RT3350ATEAsicAdjustTxPower( + IN PRTMP_ADAPTER pAd) +{ + INT i, j, maxTxPwrCnt; + CHAR DeltaPwr = 0; + BOOLEAN bAutoTxAgc = FALSE; + UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep; + UCHAR BbpR49 = 0, idx; + UCHAR BbpR1 = 0; + PCHAR pTxAgcCompensate; + ULONG TxPwr[9]; /* NOTE: the TxPwr array size should be the maxima value of all supported chipset!!!! */ + CHAR Value = 0; +#ifdef RTMP_INTERNAL_TX_ALC + UINT32 MacPwr = 0; + PTX_POWER_TUNING_ENTRY_STRUCT pTxPowerTuningEntry = NULL; + CHAR TotalDeltaPower = 0; /* (non-positive number) including the transmit power controlled by the MAC and the BBP R1 */ + CHAR desiredTSSI = 0, currentTSSI = 0, TuningTableIndex = 0; + UCHAR RFValue = 0, TmpValue = 0; +#endif /* RTMP_INTERNAL_TX_ALC */ + + maxTxPwrCnt = 5; + + if (pAd->ate.TxWI.BW == BW_40) + { + if (pAd->ate.Channel > 14) + { + for (i =0 ; i < maxTxPwrCnt; i ++) + { + TxPwr[i] = pAd->Tx40MPwrCfgABand[i]; + } + } + else + { + for (i =0 ; i < maxTxPwrCnt; i ++) + { + TxPwr[i] = pAd->Tx40MPwrCfgGBand[i]; + } + } + } + else + { + if (pAd->ate.Channel > 14) + { + for (i =0 ; i < maxTxPwrCnt; i ++) + { + TxPwr[i] = pAd->Tx20MPwrCfgABand[i]; + } + } + else + { + for (i =0 ; i < maxTxPwrCnt; i ++) + { + TxPwr[i] = pAd->Tx20MPwrCfgGBand[i]; + } + } + } + +#ifdef RTMP_INTERNAL_TX_ALC + /* Locate the internal Tx ALC tuning entry */ + if (pAd->TxPowerCtrl.bInternalTxALC == TRUE) + { + { + desiredTSSI = ATEGetDesiredTSSI(pAd); +/* + if (desiredTSSI == -1) + { + return; + } +*/ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); + + currentTSSI = BbpR49 & 0x1F; + + /* ATE always excutes extended TSSI. */ + if (1 /* pAd->TxPowerCtrl.bExtendedTssiMode == TRUE */) /* Per-channel TSSI */ + { + if ((pAd->ate.Channel >= 1) && (pAd->ate.Channel <= 14)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: bExtendedTssiMode = %d, original desiredTSSI = %d, CentralChannel = %d, PerChTxPwrOffset = %d\n", + __FUNCTION__, + pAd->TxPowerCtrl.bExtendedTssiMode, + desiredTSSI, + pAd->ate.Channel, + pAd->TxPowerCtrl.PerChTxPwrOffset[pAd->ate.Channel])); + + desiredTSSI += pAd->TxPowerCtrl.PerChTxPwrOffset[pAd->ate.Channel]; + } + } + + if (desiredTSSI < 0x00) + { + desiredTSSI = 0x00; + } + else if (desiredTSSI > 0x1F) + { + desiredTSSI = 0x1F; + } + + if (desiredTSSI > currentTSSI) + { + pAd->TxPowerCtrl.idxTxPowerTable++; + } + + if (desiredTSSI < currentTSSI) + { + pAd->TxPowerCtrl.idxTxPowerTable--; + } + + TuningTableIndex = pAd->TxPowerCtrl.idxTxPowerTable + + pAd->TxPower[pAd->ate.Channel-1].Power; + + if (TuningTableIndex < LOWERBOUND_TX_POWER_TUNING_ENTRY) + { + TuningTableIndex = LOWERBOUND_TX_POWER_TUNING_ENTRY; + } + + if (TuningTableIndex >= UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd)) + { + TuningTableIndex = UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd); + } + + /* Valid pAd->TxPowerCtrl.idxTxPowerTable: -30 ~ 45 */ + /* zero-based array */ + pTxPowerTuningEntry = &RT3350_TxPowerTuningTable[TuningTableIndex + TX_POWER_TUNING_ENTRY_OFFSET]; + pAd->TxPowerCtrl.RF_TX_ALC = pTxPowerTuningEntry->RF_TX_ALC; + pAd->TxPowerCtrl.MAC_PowerDelta = pTxPowerTuningEntry->MAC_PowerDelta; + + DBGPRINT(RT_DEBUG_TRACE, ("TuningTableIndex = %d, pAd->TxPowerCtrl.RF_TX_ALC = %d, pAd->TxPowerCtrl.MAC_PowerDelta = %d\n", + TuningTableIndex, pAd->TxPowerCtrl.RF_TX_ALC, pAd->TxPowerCtrl.MAC_PowerDelta )); + + /* Tx power adjustment over RF */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R12, (PUCHAR)(&RFValue)); + TmpValue = (RFValue & 0xE0); + RFValue = (TmpValue | (pAd->TxPowerCtrl.RF_TX_ALC & 0x1F)); + DBGPRINT(RT_DEBUG_TRACE, ("Write RF_R12 = 0x%02x\n", RFValue)); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R12, (UCHAR)(RFValue)); + + /* Tx power adjustment over MAC */ + TotalDeltaPower += pAd->TxPowerCtrl.MAC_PowerDelta; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSI = %d, currentTSSI = %d, TuningTableIndex = %d, {RF_TX_ALC = %d, MAC_PowerDelta = %d}\n", + __FUNCTION__, + desiredTSSI, + currentTSSI, + TuningTableIndex, + pTxPowerTuningEntry->RF_TX_ALC, + pTxPowerTuningEntry->MAC_PowerDelta)); + + /* The BBP R1 controls the transmit power for all rates */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1); + + BbpR1 &= ~ATE_MDSM_BBP_R1_STATIC_TX_POWER_CONTROL_MASK; + + if (TotalDeltaPower <= -12) + { + TotalDeltaPower += 12; + BbpR1 |= ATE_MDSM_DROP_TX_POWER_BY_12dBm; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); + + DBGPRINT(RT_DEBUG_TRACE, ("TPC: %s: Drop the transmit power by 12 dBm (BBP R1)\n", __FUNCTION__)); + } + else if ((TotalDeltaPower <= -6) && (TotalDeltaPower > -12)) + { + TotalDeltaPower += 6; + BbpR1 |= ATE_MDSM_DROP_TX_POWER_BY_6dBm; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); + + DBGPRINT(RT_DEBUG_TRACE, ("TPC: %s: Drop the transmit power by 6 dBm (BBP R1)\n", __FUNCTION__)); + } + else + { + /* Control the transmit power by using the MAC only */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); + } + } + } +#endif /* RTMP_INTERNAL_TX_ALC */ + + /* TX power compensation for temperature variation based on TSSI. */ + /* Do it per 4 seconds. */ + if (pAd->ate.OneSecPeriodicRound % 4 == 0) + { + if (pAd->ate.Channel <= 14) + { + /* bg channel */ + bAutoTxAgc = pAd->bAutoTxAgcG; + TssiRef = pAd->TssiRefG; + pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0]; + TxAgcStep = pAd->TxAgcStepG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + /* a channel */ + bAutoTxAgc = pAd->bAutoTxAgcA; + TssiRef = pAd->TssiRefA; + pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0]; + TxAgcStep = pAd->TxAgcStepA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + { + /* BbpR49 is unsigned char. */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); + + /* (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 0x10 ~ 0x40, minus is 0x60 ~ 0x90 */ + /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */ + /* if value is 0x65, tx power will be -= TxAgcStep*(2-1) */ + + if (BbpR49 > 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++) + { + /* Found the range. */ + if (BbpR49 <= pTssiMinusBoundary[idx]) + 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 R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n", + BbpR49, TssiRef, TxAgcStep, idx-1)); + } + else if (BbpR49 < 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++) + { + /* Found the range. */ + if (BbpR49 >= pTssiPlusBoundary[idx]) + 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 R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, idx-1)); + } + else + { + *pTxAgcCompensate = 0; + DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, 0)); + } + } + } + else + { + if (pAd->ate.Channel <= 14) + { + bAutoTxAgc = pAd->bAutoTxAgcG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + bAutoTxAgc = pAd->bAutoTxAgcA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + DeltaPwr += (*pTxAgcCompensate); + } + + /* Reset different new tx power for different TX rate. */ + for (i=0; i> j*4) & 0x0F); /* 0 ~ 15 */ + +#ifdef RTMP_INTERNAL_TX_ALC + /* + The upper bounds of the MAC 0x1314~0x1324 + are variable when the STA uses the internal Tx ALC. + */ + if (pAd->TxPowerCtrl.bInternalTxALC == TRUE) + { + switch (TX_PWR_CFG_0 + (i * 4)) + { + case TX_PWR_CFG_0: + { + /* TX0 ALC */ + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE) + { + Value = 0xE; + } + else + { + Value += TotalDeltaPower; + } + } + break; + + case TX_PWR_CFG_1: + { + /* TX0 ALC */ + if ((j >= 0) && (j <= 3)) + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xC) + { + Value = 0xC; + } + else + { + Value += TotalDeltaPower; + } + } + else + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE) + { + Value = 0xE; + } + else + { + Value += TotalDeltaPower; + } + } + } + break; + + case TX_PWR_CFG_2: + { + /* TX0 ALC */ + if ((j == 0) || (j == 2) || (j == 3)) + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xC) + { + Value = 0xC; + } + else + { + Value += TotalDeltaPower; + } + } + else + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE) + { + Value = 0xE; + } + else + { + Value += TotalDeltaPower; + } + } + } + break; + + case TX_PWR_CFG_3: + { + /* TX0 ALC */ + if ((j == 0) || (j == 2) || (j == 3) || + ((j >= 4) && (j <= 7))) + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xC) + { + Value = 0xC; + } + else + { + Value += TotalDeltaPower; + } + } + else + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE) + { + Value = 0xE; + } + else + { + Value += TotalDeltaPower; + } + } + } + break; + + case TX_PWR_CFG_4: + { + /* TX0 ALC */ + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xC) + { + Value = 0xC; + } + else + { + Value += TotalDeltaPower; + } + } + break; + + default: + { + /* do nothing */ + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknown register = 0x%X\n", + __FUNCTION__, + (TX_PWR_CFG_0 + (i * 4)))); + } + break; + } + } + else +#endif /* RTMP_INTERNAL_TX_ALC */ + { + if ((Value + DeltaPwr) < 0) + { + Value = 0; /* min */ + } + else if ((Value + DeltaPwr) > 0xF) + { + Value = 0xF; /* max */ + } + else + { + Value += DeltaPwr; /* temperature compensation */ + } + } + + /* fill new value to CSR offset */ + /* Tx power adjustment over MAC */ + /* TX0 ALC only */ + TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4); + } + + /* write tx power value to CSR */ + /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M + TX power for OFDM 6M/9M + TX power for CCK5.5M/11M + TX power for CCK1M/2M */ + /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + (i << 2), TxPwr[i]); + +#ifdef RTMP_INTERNAL_TX_ALC + /* Tx power adjustment over MAC */ + RTMP_IO_READ32(pAd, TX_PWR_CFG_0 + (i << 2), &MacPwr); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: MAC register = 0x%X, MacPwr = 0x%X\n", + __FUNCTION__, + (TX_PWR_CFG_0 + (i << 2)), MacPwr)); +#endif /* RTMP_INTERNAL_TX_ALC */ + } + } +} +#endif /* RT3350 */ + + +#ifdef RT3050 +struct _ATE_CHIP_STRUCT RALINK3050 = +{ + /* functions */ + .ChannelSwitch = RT3050ATEAsicSwitchChannel, + .TxPwrHandler = RT305xATETxPwrHandler, + .TssiCalibration = NULL, + .ExtendedTssiCalibration = NULL, + .RxVGAInit = RT305xATERxVGAInit, + .AsicSetTxRxPath = NULL, + .AdjustTxPower = DefaultATEAsicAdjustTxPower, + .AsicExtraPowerOverMAC = NULL, + + /* command handlers */ + .Set_BW_Proc = RT305x_Set_ATE_TX_BW_Proc, + .Set_FREQ_OFFSET_Proc = RT305x_Set_ATE_TX_FREQ_OFFSET_Proc, + + /* variables */ + .maxTxPwrCnt = 5, + .bBBPStoreTXCARR = TRUE, + .bBBPStoreTXCARRSUPP = TRUE, + .bBBPStoreTXCONT = FALSE, + .bBBPLoadATESTOP = TRUE, +}; +#endif /* RT3050 */ + +#ifdef RT3052 +struct _ATE_CHIP_STRUCT RALINK3052 = +{ + /* functions */ + .ChannelSwitch = RT3052ATEAsicSwitchChannel, + .TxPwrHandler = RT305xATETxPwrHandler, + .TssiCalibration = NULL, + .ExtendedTssiCalibration = NULL, + .RxVGAInit = RT305xATERxVGAInit, + .AsicSetTxRxPath = NULL, + .AdjustTxPower = DefaultATEAsicAdjustTxPower, + .AsicExtraPowerOverMAC = NULL, + + /* command handlers */ + .Set_BW_Proc = RT305x_Set_ATE_TX_BW_Proc, + .Set_FREQ_OFFSET_Proc = RT305x_Set_ATE_TX_FREQ_OFFSET_Proc, + + /* variables */ + .maxTxPwrCnt = 5, + .bBBPStoreTXCARR = TRUE, + .bBBPStoreTXCARRSUPP = TRUE, + .bBBPStoreTXCONT = FALSE, + .bBBPLoadATESTOP = TRUE, +}; +#endif /* RT3052 */ + +#ifdef RT3350 +struct _ATE_CHIP_STRUCT RALINK3350 = +{ + /* functions */ + .ChannelSwitch = RT3350ATEAsicSwitchChannel, + .TxPwrHandler = RT305xATETxPwrHandler, + .TssiCalibration = NULL, + .ExtendedTssiCalibration = RT335xATETssiCalibrationExtend, + .RxVGAInit = RT305xATERxVGAInit, + .AsicSetTxRxPath = NULL, + .AdjustTxPower = RT3350ATEAsicAdjustTxPower, + .AsicExtraPowerOverMAC = NULL, + + /* command handlers */ + .Set_BW_Proc = RT3350_Set_ATE_TX_BW_Proc, + .Set_FREQ_OFFSET_Proc = RT3350_Set_ATE_TX_FREQ_OFFSET_Proc, + + /* variables */ + .maxTxPwrCnt = 5, + .bBBPStoreTXCARR = TRUE, + .bBBPStoreTXCARRSUPP = TRUE, + .bBBPStoreTXCONT = FALSE, + .bBBPLoadATESTOP = TRUE, +}; +#endif /* RT3350 */ + + +#endif /* RT305x */ + diff --git a/mt7620/src/ate/chips/rt3352_ate.c b/mt7620/src/ate/chips/rt3352_ate.c new file mode 100644 index 0000000..a6616a1 --- /dev/null +++ b/mt7620/src/ate/chips/rt3352_ate.c @@ -0,0 +1,1405 @@ +/* + *************************************************************************** + * 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: + rt3352_ate.c + + Abstract: + Specific ATE funcitons and variables for RT3352 + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifdef RT3352 + +#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 */ + +extern FREQUENCY_ITEM FreqItems3020_Xtal20M[]; +extern FREQUENCY_ITEM RtmpFreqItems3020[]; +extern UCHAR NUM_OF_3020_CHNL; + + +/* +========================================================================== + Description: + + AsicSwitchChannel() dedicated for RT3352 ATE. + +========================================================================== +*/ +VOID RT3352ATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 Value = 0; + CHAR TxPwer = 0, TxPwer2 = 0; + UCHAR index = 0, BbpValue = 0, Channel = 0; + /* added to prevent RF register reading error */ + UCHAR RFValue = 0, RFValue2 = 0; + + SYNC_CHANNEL_WITH_QA(pATEInfo, &Channel); + + /* fill Tx power value */ + TxPwer = pATEInfo->TxPower0; + TxPwer2 = pATEInfo->TxPower1; + + if ((pAd->RfIcType == RFIC_3022) || (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3020) || \ + (pAd->RfIcType == RFIC_3320) || (pAd->RfIcType == RFIC_3322)) + { + UINT32 step=0; + + for (index = 0; index < NUM_OF_3020_CHNL; index++) + { + /* Please don't change "RtmpFreqItems3020" to "FreqItems3020" ! */ + if (Channel == RtmpFreqItems3020[index].Channel) + { + /* programming channel parameters */ + step = (*((volatile u32 *)(RALINK_SYSCTL_BASE + 0x10))); + + if (step & (1<<20)) + { + /* Xtal=40M */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R08, RtmpFreqItems3020[index].N); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R09, RtmpFreqItems3020[index].K); + } + else + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R08, FreqItems3020_Xtal20M[index].N); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R09, FreqItems3020_Xtal20M[index].K); + } + + RFValue = 0x42; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R11, (UCHAR)RFValue); + RFValue = 0x1C; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R12, (UCHAR)RFValue); + + RFValue = 0x00; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R13, (UCHAR)RFValue); + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R30, (PUCHAR)&RFValue); + + if (pATEInfo->TxWI.BW == BW_20) + { + RFValue &= ~(0x03); /* 20MBW tx_h20M=0, rx_h20M=0 */ + } + else + { + RFValue |= 0x03; /* 40MBW tx_h20M=1, rx_h20M=1 */ + } + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R30, (UCHAR)RFValue); + + if (pATEInfo->bAutoTxAlc == FALSE) + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R47, pATEInfo->TxPower0); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R48, pATEInfo->TxPower1); + } + + /* set BW */ + /* RF_R24 is reserved bits */ + RFValue = 0; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R24, (UCHAR)RFValue); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R31, 0x80); + + /* Enable RF tuning, this must be in the last, RF_R03=RF_R07. */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R03, (PUCHAR)&RFValue); + RFValue = RFValue | 0x80; /* bit 7=vcocal_en */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R03, (UCHAR)RFValue); + + RtmpOsMsDelay(2); + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, (PUCHAR)&RFValue); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R49, RFValue & 0xfe); /* clear update flag */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, (PUCHAR)&RFValue); + + /* Antenna */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R01, (PUCHAR)&RFValue); + RFValue = (RFValue & 0x03) | 0x01; + if (pATEInfo->RxAntennaSel == 1) + { + RFValue = RFValue | 0x04; /* rx0_en */ + } + else if (pATEInfo->RxAntennaSel == 2) + { + RFValue = RFValue | 0x10; /* rx1_en */ + } + else + { + RFValue = RFValue | 0x14; /* rx0_en and rx1_en */ + } + + if (pATEInfo->TxAntennaSel == 1) + { + RFValue = RFValue | 0x08; /* tx0_en */ + } + else if (pATEInfo->TxAntennaSel == 2) + { + RFValue = RFValue | 0x20; /* tx1_en */ + } + else + { + RFValue = RFValue | 0x28; /* tx0_en and tx1_en */ + } + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R01, (UCHAR)RFValue); + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue = BbpValue & 0x24; /* clear bit 0,1,3,4,6,7 */ + + if (pATEInfo->RxAntennaSel == 1) + { + BbpValue &= ~0x3; /* BBP_R3[1:0]=00 (ADC0) */ + } + else if (pATEInfo->RxAntennaSel == 2) + { + BbpValue &= ~0x3; + BbpValue |= 0x1; /* BBP_R3[1:0]=01 (ADC1) */ + } + else + { + /* RXANT_NUM >= 2, must turn on Bit 0 and 1 for all ADCs */ + BbpValue |= 0x3; /* BBP_R3[1:0]=11 (All ADCs) */ + if (pAd->Antenna.field.RxPath == 3) + BbpValue |= (1 << 4); + else if (pAd->Antenna.field.RxPath == 2) + BbpValue |= (1 << 3); /* BBP_R3[3]=1 (2R) */ + else if (pAd->Antenna.field.RxPath == 1) + BbpValue |= (0x0); + } + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + + if (pATEInfo->TxWI.BW == BW_20) + { + /* set BBP R4 = 0x40 for BW = 20 MHz */ + BbpValue = 0x40; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BbpValue); + } + else + { + /* set BBP R4 = 0x50 for BW = 40 MHz */ + BbpValue = 0x50; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BbpValue); + } + + /* calibrate power unbalance issues */ + if (pAd->Antenna.field.TxPath == 2) + { + if (pATEInfo->TxAntennaSel == 1) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; /* DAC0 (11100111B) */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + } + else if (pATEInfo->TxAntennaSel == 2) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x08; /* DAC1 */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + } + else + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + } + } + + /* latch channel for future usage */ + pAd->LatchRfRegs.Channel = Channel; + break; + } + } + } + + /* Change BBP setting during switch from a->g, g->a */ + if (Channel <= 14) + { + UINT32 TxPinCfg = 0x00050F0A;/* 2007.10.09 by Brian : 0x0005050A ==> 0x00050F0A */ + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + + /* Gary : 2010/0721 */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x38); + + + /* Rx High power VGA offset for LNA select */ + if (pAd->NicConfig2.field.ExternalLNAForG) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + /* 2.4 G band selection PIN */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x04); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + if (pATEInfo->TxAntennaSel == 1) + { + TxPinCfg &= 0xFFFFFFF3; + } + else if (pATEInfo->TxAntennaSel == 2) + { + TxPinCfg &= 0xFFFFFFFC; + } + else + { + TxPinCfg &= 0xFFFFFFFF; + } + + if (pATEInfo->RxAntennaSel == 1) + { + TxPinCfg &= 0xFFFFF3FF; + } + else if (pATEInfo->RxAntennaSel == 2) + { + TxPinCfg &= 0xFFFFFCFF; + } + else + { + TxPinCfg &= 0xFFFFFFFF; + } + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + } + /* channel > 14 */ + else + { + UINT32 TxPinCfg = 0x00050F05;/* 2007.10.09 by Brian : 0x00050505 ==> 0x00050F05 */ + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x38);/* Gary: 2010/0721 */ + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2); + + /* Rx High power VGA offset for LNA select */ + if (pAd->NicConfig2.field.ExternalLNAForA) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R91, &BbpValue); + ASSERT((BbpValue == 0x04)); + + /* 5 G band selection PIN, bit1 and bit2 are complement */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x02); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + /* 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); + } + + ATE_CHIP_RX_VGA_GAIN_INIT(pAd); + + RtmpOsMsDelay(1); + + Value = (*((volatile u32 *)(RALINK_SYSCTL_BASE + 0x10))); + + if (Value & (1 << 20)) + { + /* Xtal=40M */ + DBGPRINT(RT_DEBUG_TRACE, ("RT3352:SwitchChannel#%d(RFIC=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", + Channel, + pAd->RfIcType, + TxPwer, + TxPwer2, + pAd->Antenna.field.TxPath, + RtmpFreqItems3020[index].N, + RtmpFreqItems3020[index].K, + RtmpFreqItems3020[index].R)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("RT3352Xtal20M:SwitchChannel#%d(RFIC=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", + Channel, + pAd->RfIcType, + TxPwer, + TxPwer2, + pAd->Antenna.field.TxPath, + FreqItems3020_Xtal20M[index].N, + FreqItems3020_Xtal20M[index].K, + FreqItems3020_Xtal20M[index].R)); + } +} + + +INT RT3352ATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index) +{ + PATE_INFO pATEInfo = &(pAd->ate); + CHAR TxPower = 0; + +#ifdef RALINK_QA + if ((pATEInfo->bQATxStart == TRUE) || (pATEInfo->bQARxStart == TRUE)) + { + return 0; + } + else +#endif /* RALINK_QA */ + if (index == 0) + { + TxPower = pATEInfo->TxPower0; + } + else if (index == 1) + { + TxPower = pATEInfo->TxPower1; + } + else + { + DBGPRINT_ERR(("%s : Only TxPower0 and TxPower1 are adjustable !\n", __FUNCTION__)); + DBGPRINT_ERR(("%s : TxPower%d is out of range !\n", __FUNCTION__, index)); + return -1; + } + + if (index == 0) + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R47, TxPower); + } + + if (index == 1) + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R48, TxPower); + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s : (TxPower%d=%d)\n", __FUNCTION__, index, TxPower)); + + return 0; +} + + +VOID RT3352ATERxVGAInit( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR R66; + CHAR LNAGain = GET_LNA_GAIN(pAd); + + if (pATEInfo->Channel <= 14) + { + /* BG band */ + if (pATEInfo->TxWI.BW == BW_20) + { + R66 = (UCHAR)(0x1C + (LNAGain*2)); + } + else + { + R66 = (UCHAR)(0x24 + (LNAGain*2)); + } + } + else + { + /* A band. Not supported. */ + DBGPRINT_ERR(("%s :Ch=%d\n", __FUNCTION__, pATEInfo->Channel)); + DBGPRINT_ERR(("%s :5 GHz band not supported !\n", __FUNCTION__)); + + return; + } + + ATEBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + + + return; +} + + +/* +========================================================================== + Description: + Set RT3352 ATE RF BW + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT RT3352_Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + INT powerIndex; + UCHAR value = 0; + UCHAR BBPCurrentBW; + + BBPCurrentBW = simple_strtol(arg, 0, 10); + + if (BBPCurrentBW == 0) + { + pATEInfo->TxWI.BW = BW_20; + } + else + { + pATEInfo->TxWI.BW = BW_40; + } + + if ((pATEInfo->TxWI.PHYMODE == MODE_CCK) && (pATEInfo->TxWI.BW == BW_40)) + { + DBGPRINT_ERR(("Set_ATE_TX_BW_Proc!! Warning!! CCK only supports 20MHZ!!\n")); + DBGPRINT_ERR(("Bandwidth switch to 20!!\n")); + pATEInfo->TxWI.BW = BW_20; + } + + if (pATEInfo->TxWI.BW == BW_20) + { + if (pATEInfo->Channel <= 14) + { + /* BW=20;G band */ + for (powerIndex=0; powerIndexTx20MPwrCfgGBand[powerIndex] == 0xffffffff) + continue; + + /* TX_PWR_CFG_0 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx20MPwrCfgGBand[powerIndex]); + RtmpOsMsDelay(5); + } + } + else + { + /* BW=20;A band */ + for (powerIndex=0; powerIndexTx20MPwrCfgABand[powerIndex] == 0xffffffff) + continue; + + /* TX_PWR_CFG_0 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx20MPwrCfgABand[powerIndex]); + RtmpOsMsDelay(5); + } + } + + /* set BW = 20 MHz */ + value = 0x40; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + value = 0; /* RF_R24 is reserved bits */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R24, (UCHAR)value); + /* Rx filter */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R31, 0x80); + + /* BW = 20 MHz */ + /* Set BBP R68=0x0B to improve Rx sensitivity. */ + value = 0x0B; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + /* Set BBP R69=0x16 */ + value = 0x12; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + /* Set BBP R70=0x08 */ + value = 0x0A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + /* Set BBP R73=0x11 */ + value = 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + + if (pATEInfo->Channel == 14) + { + INT TxMode = pATEInfo->TxWI.PHYMODE; + + if (TxMode == MODE_CCK) + { + /* when Channel==14 && Mode==CCK && BandWidth==20M, BBP R4 bit5=1 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value |= 0x20; /* set bit5=1 */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + } + } + } + /* If bandwidth = 40M, set RF Reg4 bit 21 = 0. */ + else if (pATEInfo->TxWI.BW == BW_40) + { + if (pATEInfo->Channel <= 14) + { + /* BW=40;G band */ + for (powerIndex=0; powerIndexTx40MPwrCfgGBand[powerIndex] == 0xffffffff) + continue; + + /* TX_PWR_CFG_0 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx40MPwrCfgGBand[powerIndex]); + RtmpOsMsDelay(5); + } + } + else + { + /* BW=40;A band */ + for (powerIndex=0; powerIndexTx40MPwrCfgABand[powerIndex] == 0xffffffff) + continue; + + /* TX_PWR_CFG_0 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx40MPwrCfgABand[powerIndex]); + RtmpOsMsDelay(5); + } + + if ((pATEInfo->TxWI.PHYMODE >= 2) && (pATEInfo->TxWI.MCS == 7)) + { + value = 0x28; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R67, value); + } + } + + value = 0x50; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + if (IS_RT3352(pAd) || IS_RT5350(pAd)) + { + value = 0x00; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R24, (UCHAR)value); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R31, 0x80); + } + else + { + /* set BW */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R24, (PUCHAR)&value); + value &= 0xDF; + value |= 0x20; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R24, (UCHAR)value); + + /* Rx filter */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R31, 0x2F); + } + + /* BW = 40 MHz */ + /* Set BBP R68=0x0B to improve Rx sensitivity. */ + value = 0x0B; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + /* Set BBP R69=0x16 */ + value = 0x12; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + /* Set BBP R70=0x08 */ + value = 0x0A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + /* Set BBP R73=0x11 */ + value = 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + } + + return TRUE; +} + + +INT RT3352_Set_ATE_TX_FREQ_OFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR RFFreqOffset = 0; + UCHAR RFValue = 0; + UCHAR offset = 0; + UCHAR RFValue2 = 0; + + RFFreqOffset = simple_strtol(arg, 0, 10); + + if (RFFreqOffset >= 96) + { + DBGPRINT_ERR(("Set_ATE_TX_FREQ_OFFSET_Proc::Out of range(0 ~ 95).\n")); + return FALSE; + } + + pATEInfo->RFFreqOffset = RFFreqOffset; + + /* set RF frequency offset */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R17, (PUCHAR)&RFValue); + + RFValue2 = (RFValue & 0x80) | pATEInfo->RFFreqOffset; + + if (RFValue2 > RFValue) + { + for (offset = 1; offset <= (RFValue2 - RFValue); offset++) + { + RtmpOsMsDelay(1); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R17, (UCHAR)(RFValue + offset)); + } + } + else + { + for (offset = 1; offset <= (RFValue - RFValue2); offset++) + { + RtmpOsMsDelay(1); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R17, (UCHAR)(RFValue - offset)); + } + } + + return TRUE; +} + + +VOID RT3352ATEAsicAdjustTxPower( + IN PRTMP_ADAPTER pAd) +{ + INT i, j, maxTxPwrCnt; + CHAR DeltaPwr = 0; + BOOLEAN bAutoTxAgc = FALSE; + UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep; + UCHAR BbpR49 = 0, idx; + UCHAR BbpR1 = 0; + PCHAR pTxAgcCompensate; + ULONG TxPwr[9]; /* NOTE: the TxPwr array size should be the maxima value of all supported chipset!!!! */ + CHAR Value = 0; +#ifdef RTMP_INTERNAL_TX_ALC + UINT32 MacPwr = 0; + PTX_POWER_TUNING_ENTRY_STRUCT pTxPowerTuningEntry = NULL, pTxPowerTuningEntry2 = NULL; + CHAR TotalDeltaPower = 0; /* (non-positive number) including the transmit power controlled by the MAC and the BBP R1 */ + CHAR AntennaDeltaPwr = 0, TotalDeltaPower2 = 0, MAC_PowerDelta2 = 0, TuningTableIndex2 = 0; + UCHAR RFValue2 = 0; + CHAR desiredTSSI = 0, currentTSSI = 0, TuningTableIndex = 0; + UCHAR RFValue = 0, TmpValue = 0; + CHAR Value2 = 0; +#endif /* RTMP_INTERNAL_TX_ALC */ + + maxTxPwrCnt = 5; + + if (pAd->ate.TxWI.BW == BW_40) + { + if (pAd->ate.Channel > 14) + { + for (i =0 ; i < maxTxPwrCnt; i ++) + { + TxPwr[i] = pAd->Tx40MPwrCfgABand[i]; + } + } + else + { + for (i =0 ; i < maxTxPwrCnt; i ++) + { + TxPwr[i] = pAd->Tx40MPwrCfgGBand[i]; + } + } + } + else + { + if (pAd->ate.Channel > 14) + { + for (i =0 ; i < maxTxPwrCnt; i ++) + { + TxPwr[i] = pAd->Tx20MPwrCfgABand[i]; + } + } + else + { + for (i =0 ; i < maxTxPwrCnt; i ++) + { + TxPwr[i] = pAd->Tx20MPwrCfgGBand[i]; + } + } + } + +#ifdef RTMP_INTERNAL_TX_ALC + /* Locate the internal Tx ALC tuning entry */ + if (pAd->TxPowerCtrl.bInternalTxALC == TRUE) + { + { + desiredTSSI = ATEGetDesiredTSSI(pAd); +/* + if (desiredTSSI == -1) + { + return; + } +*/ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); + + currentTSSI = BbpR49 & 0x1F; + + /* ATE always excutes extended TSSI. */ + if (1 /* pAd->TxPowerCtrl.bExtendedTssiMode == TRUE */) /* Per-channel TSSI */ + { + if ((pAd->ate.Channel >= 1) && (pAd->ate.Channel <= 14)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: bExtendedTssiMode = %d, original desiredTSSI = %d, CentralChannel = %d, PerChTxPwrOffset = %d\n", + __FUNCTION__, + pAd->TxPowerCtrl.bExtendedTssiMode, + desiredTSSI, + pAd->ate.Channel, + pAd->TxPowerCtrl.PerChTxPwrOffset[pAd->ate.Channel])); + + desiredTSSI += pAd->TxPowerCtrl.PerChTxPwrOffset[pAd->ate.Channel]; + } + } + + if (desiredTSSI < 0x00) + { + desiredTSSI = 0x00; + } + else if (desiredTSSI > 0x1F) + { + desiredTSSI = 0x1F; + } + + if (desiredTSSI > currentTSSI) + { + pAd->TxPowerCtrl.idxTxPowerTable++; + } + + if (desiredTSSI < currentTSSI) + { + pAd->TxPowerCtrl.idxTxPowerTable--; + } + + TuningTableIndex = pAd->TxPowerCtrl.idxTxPowerTable + + pAd->TxPower[pAd->ate.Channel-1].Power; + + if (TuningTableIndex < LOWERBOUND_TX_POWER_TUNING_ENTRY) + { + TuningTableIndex = LOWERBOUND_TX_POWER_TUNING_ENTRY; + } + + if (TuningTableIndex >= UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd)) + { + TuningTableIndex = UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd); + } + + /* Valid pAd->TxPowerCtrl.idxTxPowerTable: -30 ~ 61 */ + /* zero-based array */ + pTxPowerTuningEntry = &RT3352_TxPowerTuningTable[TuningTableIndex + TX_POWER_TUNING_ENTRY_OFFSET]; + + pAd->TxPowerCtrl.RF_TX_ALC = pTxPowerTuningEntry->RF_TX_ALC; + pAd->TxPowerCtrl.MAC_PowerDelta = pTxPowerTuningEntry->MAC_PowerDelta; + + DBGPRINT(RT_DEBUG_TRACE, ("TuningTableIndex = %d, pAd->TxPowerCtrl.RF_TX_ALC = %d, pAd->TxPowerCtrl.MAC_PowerDelta = %d\n", + TuningTableIndex, pAd->TxPowerCtrl.RF_TX_ALC, pAd->TxPowerCtrl.MAC_PowerDelta)); + + /* Tx power adjustment over RF */ + RFValue = (UCHAR)pAd->TxPowerCtrl.RF_TX_ALC; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R47, (UCHAR)RFValue); /* TX0_ALC */ + DBGPRINT(RT_DEBUG_TRACE, ("RF_R47 = 0x%02x\n", RFValue)); + + /* Delta Power between Tx0 and Tx1 */ + if ((pAd->TxPower[pAd->ate.Channel-1].Power) > (pAd->TxPower[pAd->ate.Channel-1].Power2)) + { + AntennaDeltaPwr = ((pAd->TxPower[pAd->ate.Channel-1].Power) + - (pAd->TxPower[pAd->ate.Channel-1].Power2)); + TuningTableIndex2 = TuningTableIndex - AntennaDeltaPwr; + } + else if ((pAd->TxPower[pAd->ate.Channel-1].Power) < (pAd->TxPower[pAd->ate.Channel-1].Power2)) + { + AntennaDeltaPwr = ((pAd->TxPower[pAd->ate.Channel-1].Power2) + - (pAd->TxPower[pAd->ate.Channel-1].Power)); + TuningTableIndex2 = TuningTableIndex + AntennaDeltaPwr; + } + else + { + TuningTableIndex2 = TuningTableIndex; + } + + if (TuningTableIndex2 < LOWERBOUND_TX_POWER_TUNING_ENTRY) + { + TuningTableIndex2 = LOWERBOUND_TX_POWER_TUNING_ENTRY; + } + + if (TuningTableIndex2 >= UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd)) + { + TuningTableIndex2 = UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd); + } + + pTxPowerTuningEntry2 = &RT3352_TxPowerTuningTable[TuningTableIndex2 + TX_POWER_TUNING_ENTRY_OFFSET]; + + RFValue2 = pTxPowerTuningEntry2->RF_TX_ALC; + MAC_PowerDelta2 = pTxPowerTuningEntry2->MAC_PowerDelta; + + DBGPRINT(RT_DEBUG_TRACE, ("Pwr0 = 0x%02x\n", (pAd->TxPower[pAd->ate.Channel-1].Power))); + DBGPRINT(RT_DEBUG_TRACE, ("Pwr1 = 0x%02x\n", (pAd->TxPower[pAd->ate.Channel-1].Power2))); + DBGPRINT(RT_DEBUG_TRACE, ("AntennaDeltaPwr = %d\n", AntennaDeltaPwr)); + DBGPRINT(RT_DEBUG_TRACE, ("TuningTableIndex = %d\n", TuningTableIndex)); + DBGPRINT(RT_DEBUG_TRACE, ("TuningTableIndex2 = %d\n", TuningTableIndex2)); + DBGPRINT(RT_DEBUG_TRACE, ("RFValue = %u\n", RFValue)); + DBGPRINT(RT_DEBUG_TRACE, ("RFValue2 = %u\n", RFValue2)); + + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R48, (UCHAR)RFValue2); /* TX1_ALC */ + DBGPRINT(RT_DEBUG_TRACE, ("RF_R48 = 0x%02x\n", RFValue2)); + + TotalDeltaPower2 += MAC_PowerDelta2; + + /* Tx power adjustment over MAC */ + TotalDeltaPower += pAd->TxPowerCtrl.MAC_PowerDelta; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSI = %d, currentTSSI = %d, TuningTableIndex = %d, {RF_TX_ALC = %d, MAC_PowerDelta = %d}\n", + __FUNCTION__, + desiredTSSI, + currentTSSI, + TuningTableIndex, + pTxPowerTuningEntry->RF_TX_ALC, + pTxPowerTuningEntry->MAC_PowerDelta)); + + /* The BBP R1 controls the transmit power for all rates */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1); + + BbpR1 &= ~ATE_MDSM_BBP_R1_STATIC_TX_POWER_CONTROL_MASK; + + if (TotalDeltaPower <= -12) + { + TotalDeltaPower += 12; + TotalDeltaPower2 += 12; + BbpR1 |= ATE_MDSM_DROP_TX_POWER_BY_12dBm; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); + + DBGPRINT(RT_DEBUG_TRACE, ("TPC: %s: Drop the transmit power by 12 dBm (BBP R1)\n", __FUNCTION__)); + } + else if ((TotalDeltaPower <= -6) && (TotalDeltaPower > -12)) + { + TotalDeltaPower += 6; + TotalDeltaPower2 += 6; + BbpR1 |= ATE_MDSM_DROP_TX_POWER_BY_6dBm; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); + + DBGPRINT(RT_DEBUG_TRACE, ("TPC: %s: Drop the transmit power by 6 dBm (BBP R1)\n", __FUNCTION__)); + } + else + { + /* Control the transmit power by using the MAC only */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); + } + } + } +#endif /* RTMP_INTERNAL_TX_ALC */ + + /* TX power compensation for temperature variation based on TSSI. */ + /* Do it per 4 seconds. */ + if (pAd->ate.OneSecPeriodicRound % 4 == 0) + { + if (pAd->ate.Channel <= 14) + { + /* bg channel */ + bAutoTxAgc = pAd->bAutoTxAgcG; + TssiRef = pAd->TssiRefG; + pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0]; + TxAgcStep = pAd->TxAgcStepG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + /* a channel */ + bAutoTxAgc = pAd->bAutoTxAgcA; + TssiRef = pAd->TssiRefA; + pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0]; + TxAgcStep = pAd->TxAgcStepA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + { + /* BbpR49 is unsigned char. */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); + + /* (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 0x10 ~ 0x40, minus is 0x60 ~ 0x90 */ + /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */ + /* if value is 0x65, tx power will be -= TxAgcStep*(2-1) */ + + if (BbpR49 > 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++) + { + /* Found the range. */ + if (BbpR49 <= pTssiMinusBoundary[idx]) + 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 R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n", + BbpR49, TssiRef, TxAgcStep, idx-1)); + } + else if (BbpR49 < 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++) + { + /* Found the range. */ + if (BbpR49 >= pTssiPlusBoundary[idx]) + 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 R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, idx-1)); + } + else + { + *pTxAgcCompensate = 0; + DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, 0)); + } + } + } + else + { + if (pAd->ate.Channel <= 14) + { + bAutoTxAgc = pAd->bAutoTxAgcG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + bAutoTxAgc = pAd->bAutoTxAgcA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + DeltaPwr += (*pTxAgcCompensate); + } + + /* Reset different new tx power for different TX rate. */ + for (i=0; i> j*4) & 0x0F); /* 0 ~ 15 */ +#ifdef RTMP_INTERNAL_TX_ALC + /* Tx power adjustment over MAC */ + if (j & 0x00000001) /* j=1, 3, 5, 7 */ + { + /* TX1 ALC */ + Value2 = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */ + } + else /* j=0, 2, 4, 6 */ + { + /* TX0 ALC */ + Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */ + } + + /* + The upper bounds of the MAC 0x1314~0x1324 + are variable when the STA uses the internal Tx ALC. + */ + if (pAd->TxPowerCtrl.bInternalTxALC == TRUE) + { + switch (TX_PWR_CFG_0 + (i * 4)) + { + case TX_PWR_CFG_0: + { + /* TX0 ALC */ + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE) + { + Value = 0xE; + } + else + { + Value += TotalDeltaPower; + } + + /* Tx power adjustment over MAC */ + /* TX1 ALC */ + if ((Value2 + TotalDeltaPower2) < 0) + { + Value2 = 0; + } + else if ((Value2 + TotalDeltaPower2) > 0xE) + { + Value2 = 0xE; + } + else + { + Value2 += TotalDeltaPower2; + } + } + break; + + case TX_PWR_CFG_1: + { + /* TX0 ALC */ + if ((j >= 0) && (j <= 3)) + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xC) + { + Value = 0xC; + } + else + { + Value += TotalDeltaPower; + } + } + else + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE) + { + Value = 0xE; + } + else + { + Value += TotalDeltaPower; + } + } + + /* Tx power adjustment over MAC */ + /* TX1 ALC */ + if ((j >= 0) && (j <= 3)) + { + if ((Value2 + TotalDeltaPower2) < 0) + { + Value2 = 0; + } + else if ((Value2 + TotalDeltaPower2) > 0xC) + { + Value2 = 0xC; + } + else + { + Value2 += TotalDeltaPower2; + } + } + else + { + if ((Value2 + TotalDeltaPower2) < 0) + { + Value2 = 0; + } + else if ((Value2 + TotalDeltaPower2) > 0xE) + { + Value2 = 0xE; + } + else + { + Value2 += TotalDeltaPower2; + } + } + } + break; + + case TX_PWR_CFG_2: + { + /* TX0 ALC */ + if ((j == 0) || (j == 2) || (j == 3)) + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xC) + { + Value = 0xC; + } + else + { + Value += TotalDeltaPower; + } + } + else + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE) + { + Value = 0xE; + } + else + { + Value += TotalDeltaPower; + } + } + + /* Tx power adjustment over MAC */ + /* TX1 ALC */ + if ((j == 0) || (j == 2) || (j == 3)) + { + if ((Value2 + TotalDeltaPower2) < 0) + { + Value2 = 0; + } + else if ((Value2 + TotalDeltaPower2) > 0xC) + { + Value2 = 0xC; + } + else + { + Value2 += TotalDeltaPower2; + } + } + else + { + if ((Value2 + TotalDeltaPower2) < 0) + { + Value2 = 0; + } + else if ((Value2 + TotalDeltaPower2) > 0xE) + { + Value2 = 0xE; + } + else + { + Value2 += TotalDeltaPower2; + } + } + } + break; + + case TX_PWR_CFG_3: + { + /* TX0 ALC */ + if ((j == 0) || (j == 2) || (j == 3) || + ((j >= 4) && (j <= 7))) + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xC) + { + Value = 0xC; + } + else + { + Value += TotalDeltaPower; + } + } + else + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE) + { + Value = 0xE; + } + else + { + Value += TotalDeltaPower; + } + } + + /* Tx power adjustment over MAC */ + /* TX1 ALC */ + if ((j == 0) || (j == 2) || (j == 3) || + ((j >= 4) && (j <= 7))) + { + if ((Value2 + TotalDeltaPower2) < 0) + { + Value2 = 0; + } + else if ((Value2 + TotalDeltaPower2) > 0xC) + { + Value2 = 0xC; + } + else + { + Value2 += TotalDeltaPower2; + } + } + else + { + if ((Value2 + TotalDeltaPower2) < 0) + { + Value2 = 0; + } + else if ((Value2 + TotalDeltaPower2) > 0xE) + { + Value2 = 0xE; + } + else + { + Value2 += TotalDeltaPower2; + } + } + } + break; + + case TX_PWR_CFG_4: + { + /* TX0 ALC */ + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xC) + { + Value = 0xC; + } + else + { + Value += TotalDeltaPower; + } + + /* Tx power adjustment over MAC */ + /* TX1 ALC */ + if ((Value2 + TotalDeltaPower2) < 0) + { + Value2 = 0; + } + else if ((Value2 + TotalDeltaPower2) > 0xC) + { + Value2 = 0xC; + } + else + { + Value2 += TotalDeltaPower2; + } + } + break; + + default: + { + /* do nothing */ + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknown register = 0x%X\n", + __FUNCTION__, + (TX_PWR_CFG_0 + (i * 4)))); + } + break; + } + } + else +#endif /* RTMP_INTERNAL_TX_ALC */ + { + if ((Value + DeltaPwr) < 0) + { + Value = 0; /* min */ + } + else if ((Value + DeltaPwr) > 0xF) + { + Value = 0xF; /* max */ + } + else + { + Value += DeltaPwr; /* temperature compensation */ + } + } + + /* fill new value to CSR offset */ +#ifdef RTMP_INTERNAL_TX_ALC + /* Tx power adjustment over MAC */ + if (j & 0x00000001) /* j=1, 3, 5, 7 */ + { + /* TX1 ALC */ + TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value2 << j*4); + } + else /* j=0, 2, 4, 6 */ + { + /* TX0 ALC */ + TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4); + } +#endif /* RTMP_INTERNAL_TX_ALC */ + } + + /* write tx power value to CSR */ + /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M + TX power for OFDM 6M/9M + TX power for CCK5.5M/11M + TX power for CCK1M/2M */ + /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + (i << 2), TxPwr[i]); + +#ifdef RTMP_INTERNAL_TX_ALC + /* Tx power adjustment over MAC */ + RTMP_IO_READ32(pAd, TX_PWR_CFG_0 + (i << 2), &MacPwr); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: MAC register = 0x%X, MacPwr = 0x%X\n", + __FUNCTION__, + (TX_PWR_CFG_0 + (i << 2)), MacPwr)); +#endif /* RTMP_INTERNAL_TX_ALC */ + } + + } + +} + + +struct _ATE_CHIP_STRUCT RALINK3352 = +{ + /* functions */ + .ChannelSwitch = RT3352ATEAsicSwitchChannel, + .TxPwrHandler = RT3352ATETxPwrHandler, + .TssiCalibration = NULL, + .ExtendedTssiCalibration = RT335xATETssiCalibrationExtend, + .RxVGAInit = RT3352ATERxVGAInit, + .AsicSetTxRxPath = NULL, + .AdjustTxPower = RT3352ATEAsicAdjustTxPower, + .AsicExtraPowerOverMAC = NULL, + + /* command handlers */ + .Set_BW_Proc = RT3352_Set_ATE_TX_BW_Proc, + .Set_FREQ_OFFSET_Proc = RT3352_Set_ATE_TX_FREQ_OFFSET_Proc, + + /* variables */ + .maxTxPwrCnt = 5, + .bBBPStoreTXCARR = TRUE, + .bBBPStoreTXCARRSUPP = TRUE, + .bBBPStoreTXCONT = TRUE, + .bBBPLoadATESTOP = TRUE, +}; + +#endif /* RT3352 */ + diff --git a/mt7620/src/ate/chips/rt3883_ate.c b/mt7620/src/ate/chips/rt3883_ate.c new file mode 100644 index 0000000..de77f38 --- /dev/null +++ b/mt7620/src/ate/chips/rt3883_ate.c @@ -0,0 +1,1143 @@ +/* + *************************************************************************** + * 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: + rt3883_ate.c + + Abstract: + Specific ATE funcitons and configurations for RT3883 + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifdef RT3883 + +#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 */ + +extern UCHAR NUM_OF_3883_CHNL; +extern FREQUENCY_ITEM FreqItems3883[]; + + +VOID RT3883_ATE_TxAntennaSelect( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 MACValue = 0; + UCHAR RFValue = 0; + UCHAR Channel; + CHAR TxAntennaSel; + BOOLEAN b5GBand; + + Channel = pATEInfo->Channel; + TxAntennaSel = pATEInfo->TxAntennaSel; + b5GBand = (Channel > 14) ? TRUE : FALSE; + + /* MAC registers */ + /* for RT3883 stream mode */ + if (IS_RT3883(pAd)) + { + if (TxAntennaSel == 1) + { + MACValue = 0x0000FFFF; + } + else if (TxAntennaSel == 2) + { + MACValue = 0x0001FFFF; + } + else if (TxAntennaSel == 3) + { + MACValue = 0x0002FFFF; + } + else + { + /* 3T */ + MACValue = 0x0003FFFF; + } + + RTMP_IO_WRITE32(pAd, TX_CHAIN_ADDR0_L, 0xFFFFFFFF); + RTMP_IO_WRITE32(pAd, TX_CHAIN_ADDR0_H, MACValue); + } + + if (TxAntennaSel == 0) + { + /* 3T */ + if (b5GBand == TRUE) + { + /* A band */ + RTMP_IO_READ32(pAd, TX_PIN_CFG, &MACValue); + MACValue &= ~(0x0300000F); + MACValue |= 0x01000005; + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, MACValue); + } + else + { + /* G band */ + RTMP_IO_READ32(pAd, TX_PIN_CFG, &MACValue); + MACValue &= ~(0x0300000F); + MACValue |= 0x0200000A; + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, MACValue); + } + } + else if (TxAntennaSel == 1) + { + /* TX 0 */ + if (b5GBand == TRUE) + { + /* A band */ + RTMP_IO_READ32(pAd, TX_PIN_CFG, &MACValue); + MACValue &= ~(0x0300000F); + MACValue |= 0x00000001; + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, MACValue); + } + else + { + /* G band */ + RTMP_IO_READ32(pAd, TX_PIN_CFG, &MACValue); + MACValue &= ~(0x0300000F); + MACValue |= 0x00000002; + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, MACValue); + } + } + else if (TxAntennaSel == 2) + { + /* TX 1 */ + if (b5GBand == TRUE) + { + /* A band */ + RTMP_IO_READ32(pAd, TX_PIN_CFG, &MACValue); + MACValue &= ~(0x0300000F); + MACValue |= 0x00000004; + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, MACValue); + } + else + { + /* G band */ + RTMP_IO_READ32(pAd, TX_PIN_CFG, &MACValue); + MACValue &= ~(0x0300000F); + MACValue |= 0x00000008; + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, MACValue); + } + } + else if (TxAntennaSel == 3) + { + /* TX 2 */ + if (b5GBand == TRUE) + { + /* A band */ + RTMP_IO_READ32(pAd, TX_PIN_CFG, &MACValue); + MACValue &= ~(0x0300000F); + MACValue |= 0x01000000; + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, MACValue); + } + else + { + /* G band */ + RTMP_IO_READ32(pAd, TX_PIN_CFG, &MACValue); + MACValue &= ~(0x0300000F); + MACValue |= 0x02000000; + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, MACValue); + } + } + else + { + DBGPRINT_ERR(("Tx antenna selected does not exist!\n")); + return; + } + + /* RF registers */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R01, (PUCHAR)&RFValue); + RFValue = (RFValue & 0x57) | 0x03; + + if (TxAntennaSel == 1) + { + /* TX 0 */ + RFValue = RFValue | (1 << 3); + } + else if (TxAntennaSel == 2) + { + /* TX 1 */ + RFValue = RFValue | (1 << 5); + } + else if (TxAntennaSel == 3) + { + /* TX 2 */ + RFValue = RFValue | (1 << 7); + } + else + { + /* TX All */ + RFValue = RFValue | ((1 << 3) | (1 << 5) | (1 << 7)); + } + + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R01, (UCHAR)RFValue); + + return; +} + + +VOID RT3883_ATE_RxAntennaSelect( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 MACValue = 0; + UCHAR BbpValue = 0; + UCHAR RFValue = 0; + UCHAR Channel; + CHAR RxAntennaSel; + BOOLEAN b5GBand; + + Channel = pATEInfo->Channel; + RxAntennaSel = pATEInfo->RxAntennaSel; + b5GBand = (Channel > 14) ? TRUE : FALSE; + + /* MAC registers */ + if ((RxAntennaSel >= 0) && (RxAntennaSel <= 3)) + { + RTMP_IO_READ32(pAd, TX_PIN_CFG, &MACValue); + MACValue |= 0x30000F00; + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, MACValue); + } + else + { + DBGPRINT_ERR(("Rx antenna selected does not exist!\n")); + return; + } + + /* BBP registers */ + if (pAd->Antenna.field.RxPath == 3) + { + if (b5GBand == FALSE) + { + BbpValue = 0x10; + } + else + { + if (pATEInfo->Channel < 132) + { + /* lower frequency channel */ + BbpValue = 0x10; + } + else + { + /* higher frequency channel */ + BbpValue = 0x30; + } + } + } + else if (pAd->Antenna.field.RxPath == 2) + { + BbpValue = 0x08; + } + else + { + ASSERT(pAd->Antenna.field.RxPath == 1); + BbpValue = 0x00; + } + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + + /* clear bit 0,1,3,4 */ + BbpValue = BbpValue & 0xE4; + if (RxAntennaSel == 1) + { + BbpValue |= 0x0; + } + else if (RxAntennaSel == 2) + { + BbpValue |= 0x1; + } + else if (RxAntennaSel == 3) + { + BbpValue |= 0x2; + } + else + { + /* assume that all RxAntenna are enabled */ + /* (Gary, 2010-06-02) */ + BbpValue |= 0x10; + } + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + + /* RF registers */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R01, &RFValue); + RFValue = (RFValue & 0xAB) | 0x03; + + if (RxAntennaSel == 1) + { + /* RX 0 */ + RFValue = RFValue | (1 << 2); + } + else if (RxAntennaSel == 2) + { + /* RX 1 */ + RFValue = RFValue | (1 << 4); + } + else if (RxAntennaSel == 3) + { + /* RX 2 */ + RFValue = RFValue | (1 << 6); + } + else + { + /* RX All */ + RFValue = RFValue | ((1 << 2) | (1 << 4) | (1 << 6)); + } + + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R01, (UCHAR)RFValue); + + return; +} + + +/* +========================================================================== + Description: + + AsicSwitchChannel() dedicated for RT3883 ATE. + +========================================================================== +*/ +VOID RT3883ATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + CHAR TxPwer = 0, TxPwer2 = 0; + UCHAR index = 0, BbpValue = 0, Channel = 0; + /* added to prevent RF register reading error */ + UCHAR RFValue = 0, RFValue2 = 0; + CHAR TxPwer3 = 0; + + SYNC_CHANNEL_WITH_QA(pATEInfo, &Channel); + + /* fill Tx power value */ + TxPwer = pATEInfo->TxPower0; + TxPwer2 = pATEInfo->TxPower1; + TxPwer3 = pATEInfo->TxPower2; + + RTMPRT3883ABandSel(Channel); + + for (index = 0; index < NUM_OF_3883_CHNL; index++) + { + if (Channel == FreqItems3883[index].Channel) + { + UCHAR diff = 0; + UCHAR BbpValue = 0; + + /* RF_R06 for A-Band L:0x80 M:0x80 H:0x40 (Gary, 2010-06-02) */ + if (Channel <= 14) + { + RFValue = 0x40; + } + else + { + if (Channel < 132) + { + RFValue = 0x80; + } + else + { + RFValue = 0x40; + } + } + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R06, (UCHAR)RFValue); + + /* programming channel parameters */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R08, FreqItems3883[index].N); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R09, FreqItems3883[index].K); + + if (Channel <= 14) + RFValue = 0x46; + else + RFValue = 0x48; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R11, (UCHAR)RFValue); + + + if (Channel <= 14) + RFValue = 0x1A;/* Gary, 2011-03-10 */ + else + RFValue = 0x52;/* Gary, 2011-03-10 */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R12, (UCHAR)RFValue); + + RFValue = 0x12; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R13, (UCHAR)RFValue); + + /* antenna selection */ + RT3883_ATE_RxAntennaSelect(pAd);/* (Gary, 2010-11-18) */ + RT3883_ATE_TxAntennaSelect(pAd);/* (Gary, 2010-11-18) */ + + if (pATEInfo->TxWI.BW == BW_20) + { + /* set BBP R4 = 0x40 for BW = 20 MHz */ + BbpValue = 0x40; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BbpValue); + } + else + { + /* set BBP R4 = 0x50 for BW = 40 MHz */ + BbpValue = 0x50; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BbpValue); + } + + /* set RF frequency offset */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R17, (PUCHAR)&RFValue); + RFValue2 = (RFValue & 0x80) | pATEInfo->RFFreqOffset; + if (RFValue2 > RFValue) + { + for (diff = 1; diff <= (RFValue2 - RFValue); diff++) + { + RtmpOsMsDelay(1); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R17, (UCHAR)(RFValue + diff)); + } + } + else + { + for (diff = 1; diff <= (RFValue - RFValue2); diff++) + { + RtmpOsMsDelay(1); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R17, (UCHAR)(RFValue - diff)); + } + } + + /* (Gary, 2010-06-02) */ + RFValue = 0x20; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R22, (UCHAR)RFValue); + + /* different default setting for A/BG bands */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R30, (PUCHAR)&RFValue); + if (pATEInfo->TxWI.BW == BW_20) + /* 20MBW Bit[2:1]=0,0 */ + RFValue &= ~(0x06); + else + RFValue |= 0x06; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R30, (UCHAR)RFValue); + + /* (Gary, 2010-06-02) */ + if (Channel <= 14) + RFValue = 0xA0; + else + RFValue = 0x80; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R31, (UCHAR)RFValue); + + /* (Gary, 2011-08-25) */ + if (pATEInfo->TxWI.BW == BW_20) + RFValue = 0xD8; + else + RFValue = 0x80; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R32, (UCHAR)RFValue); + + /* (Gary, 2011-08-25) */ + RFValue = 0x3F; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R33, (UCHAR)RFValue); + + if (Channel <= 14) + RFValue = 0x3C; + else + RFValue = 0x20; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R34, (UCHAR)RFValue); + + /* loopback RF_BS */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R36, (PUCHAR)&RFValue); + RFValue &= ~(0x1 << 7); + if (Channel <= 14) + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R36, (UCHAR)(RFValue | (0x1 << 7))); + else + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R36, (UCHAR)RFValue); + + /* RF_R39 for A-Band L:0x36 M:0x32 H:0x30 */ + if (Channel > 14) + { + if (Channel < 100) + { + RFValue = 0x36; + } + else if (Channel < 132) + { + RFValue = 0x32; + } + else + { + RFValue = 0x30; + } + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R39, (UCHAR)RFValue); + } + else + { + /* G band */ + RFValue = 0x23; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R39, (UCHAR)RFValue); + } + +#ifdef TXBF_SUPPORT + if (pATEInfo->bTxBF == TRUE) + { + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R39, (PUCHAR)&RFValue); + RFValue |= 0x40; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R39, (UCHAR)RFValue); + } +#endif /* TXBF_SUPPORT */ + + /* loopback RF_BS */ + if (Channel <= 14) + RFValue = 0x93; + else + RFValue = 0x9B; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R44, (UCHAR)RFValue); + + /* RF_R45 for A-Band L:0xEB M:0xB3 H:0x9B */ + if (Channel > 14) + { + if (Channel < 100) + { + RFValue = 0xEB; + } + else if (Channel < 132) + { + RFValue = 0xB3; + } + else + { + RFValue = 0x9B; + } + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R45, (UCHAR)RFValue); + } + else + { + /* G band */ + RFValue = 0xBB; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R45, (UCHAR)RFValue); + } + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R49, (PUCHAR)&RFValue); + if (Channel <= 14) + RFValue = 0x8E; + else + RFValue = 0x8A; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R49, (UCHAR)RFValue); + +#ifdef TXBF_SUPPORT + if (pATEInfo->bTxBF == TRUE) + { + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R49, (PUCHAR)&RFValue); + RFValue |= 0x20; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R49, (UCHAR)RFValue); + } +#endif /* TXBF_SUPPORT */ + + RFValue = 0x86; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R50, (UCHAR)RFValue); + + /* tx_mx1_ic */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R51, (PUCHAR)&RFValue); + if (Channel <= 14) + RFValue = 0x75; + else + RFValue = 0x51; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R51, (UCHAR)RFValue); + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R52, (PUCHAR)&RFValue); + if (Channel <= 14) + RFValue = 0x45; + else + RFValue = 0x05; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R52, (UCHAR)RFValue); + + /* tx0, tx1, tx2 (0.5db) */ + if (Channel <= 14) + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R53, pATEInfo->TxPower0); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R54, pATEInfo->TxPower1); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R55, pATEInfo->TxPower2); + } + else + { + /* (Gary, 2010-02-12) */ + CHAR power = 0x48 | ((pATEInfo->TxPower0 & 0x18) << 1) | (pATEInfo->TxPower0 & 0x7); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R53, power); + /* (Gary, 2010-02-12) */ + power = 0x48 | ((pATEInfo->TxPower1 & 0x18) << 1) | (pATEInfo->TxPower1 & 0x7); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R54, power); + /* (Gary, 2010-02-12) */ + power = 0x48 | ((pATEInfo->TxPower2 & 0x18) << 1) | (pATEInfo->TxPower2 & 0x7); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R55, power); + } + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R57, (PUCHAR)&RFValue); + if (Channel <= 14) + RFValue = 0x6E; + else + RFValue = 0x3E; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R57, (UCHAR)RFValue); + + /* Enable RF tuning, this must be in the last, RF_R03=RF_R07 (RT30xx). */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R03, (PUCHAR)&RFValue); + RFValue = RFValue | 0x80; /* bit 7=vcocal_en */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R03, (UCHAR)RFValue); + + RtmpOsMsDelay(2); + + /* latch channel for future usage */ + pAd->LatchRfRegs.Channel = Channel; + +#ifdef TXBF_SUPPORT + /* Do a Divider Calibration and update BBP registers */ + if (pATEInfo->bTxBF) + { + ITxBFLoadLNAComp(pAd); + ITxBFDividerCalibration(pAd, 2, 0, NULL); + } +#endif /* TXBF_SUPPORT */ + break; + } + } + + /* Change BBP setting during switch from a->g, g->a */ + if (Channel <= 14) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + + /* for peak throughput, Henry 2009-12-23 */ + if (pATEInfo->RxAntennaSel == 0) + { + /* assume that all RxAntenna are enabled */ + BbpValue = 0x46; + } + else + { + /* assume that only one RxAntenna is enabled */ + BbpValue = 0x00; + } + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, BbpValue); + + /* Rx High power VGA offset for LNA select */ + if (pAd->NicConfig2.field.ExternalLNAForG) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + /* G band */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x82); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R83, 0x8A); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R105, 0x34); + } + /* channel > 14 */ + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + + /* for peak throughput, Henry 2009-12-23 */ + if (pATEInfo->RxAntennaSel == 0) + { + /* assume that all RxAntenna are enabled */ + BbpValue = 0x46; + } + else + { + /* assume that only one RxAntenna is enabled */ + BbpValue = 0x00; + } + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, BbpValue); + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x82); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R83, 0x9A); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R105, 0x34); + } + + ATE_CHIP_RX_VGA_GAIN_INIT(pAd); + + /* + 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. + */ + RtmpOsMsDelay(1); + + DBGPRINT(RT_DEBUG_TRACE, ("RT3883:SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, Pwr2=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", + Channel, + pAd->RfIcType, + TxPwer, + TxPwer2, + TxPwer3, + pAd->Antenna.field.TxPath, + FreqItems3883[index].N, + FreqItems3883[index].K, + FreqItems3883[index].R)); +} + + +INT RT3883ATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index) +{ + PATE_INFO pATEInfo = &(pAd->ate); + CHAR TxPower = 0; + +#ifdef RALINK_QA + if ((pATEInfo->bQATxStart == TRUE) || (pATEInfo->bQARxStart == TRUE)) + { + return 0; + } + else +#endif /* RALINK_QA */ + if (index == 0) + { + TxPower = pATEInfo->TxPower0; + } + else if (index == 1) + { + TxPower = pATEInfo->TxPower1; + } +#ifdef DOT11N_SS3_SUPPORT + else if (index == 2) + { + TxPower = pATEInfo->TxPower2; + } +#endif /* DOT11N_SS3_SUPPORT */ + else + { +#ifdef DOT11N_SS3_SUPPORT + DBGPRINT_ERR(("%s : Only TxPower0, TxPower1, and TxPower2 are adjustable !\n", __FUNCTION__)); +#else + DBGPRINT_ERR(("%s : Only TxPower0 and TxPower1 are adjustable !\n", __FUNCTION__)); +#endif /* DOT11N_SS3_SUPPORT */ + DBGPRINT_ERR(("TxPower%d is out of range !\n", index)); + return -1; + } + + if (pATEInfo->Channel <= 14) + { + if (index == 0) + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R53, TxPower); + else if (index == 1) + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R54, TxPower); + else if (index == 2) + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R55, TxPower); + } + else + { + CHAR power; + power = 0x48 | ((TxPower & 0x18) << 1) | (TxPower & 0x7); + if (index == 0) + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R53, power); + else if (index == 1) + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R54, power); + else if (index == 2) + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R55, power); + } + + return 0; +} + + +VOID RT3883ATERxVGAInit( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR R66; + CHAR LNAGain = GET_LNA_GAIN(pAd); + + if (pATEInfo->Channel <= 14) + { + /* BG band */ +/* R66 = ((pATEInfo->TxWI.BW == BW_20) ? (0x30) : (0x38)); */ + R66 = (UCHAR)(0x2E + LNAGain); + } + else + { + /* A band */ + R66 = (UCHAR)(0x20 + (LNAGain * 5)/3); + } + + ATEBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + + + return; +} + + +/* +========================================================================== + Description: + Set RT3883 ATE RF BW + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT RT3883_Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + INT powerIndex; + UCHAR value = 0; + UCHAR BBPCurrentBW; + + BBPCurrentBW = simple_strtol(arg, 0, 10); + + if (BBPCurrentBW == 0) + { + pATEInfo->TxWI.BW = BW_20; + } + else + { + pATEInfo->TxWI.BW = BW_40; + } + + if ((pATEInfo->TxWI.PHYMODE == MODE_CCK) && (pATEInfo->TxWI.BW == BW_40)) + { + DBGPRINT_ERR(("Set_ATE_TX_BW_Proc!! Warning!! CCK only supports 20MHZ!!\n")); + DBGPRINT_ERR(("Bandwidth switch to 20!!\n")); + pATEInfo->TxWI.BW = BW_20; + } + + if (pATEInfo->TxWI.BW == BW_20) + { + if (pATEInfo->Channel <= 14) + { + /* BW=20;G band */ + for (powerIndex=0; powerIndexTx20MPwrCfgGBand[powerIndex] == 0xffffffff) + continue; + + /* TX_PWR_CFG_0 ~ TX_PWR_CFG_9 */ + /* TX_PWR_CFG_0_EXT ~ TX_PWR_CFG_4_EXT */ + if (powerIndex == 5) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_5, pAd->Tx20MPwrCfgGBand[powerIndex]); + } + else if (powerIndex== 6) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_6, pAd->Tx20MPwrCfgGBand[powerIndex]); + } + else if (powerIndex == 7) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_7, pAd->Tx20MPwrCfgGBand[powerIndex]); + } + else if (powerIndex == 8) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_8, pAd->Tx20MPwrCfgGBand[powerIndex]); + } + else if (powerIndex == 9) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_9, pAd->Tx20MPwrCfgGBand[powerIndex]); + } + else + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx20MPwrCfgGBand[powerIndex]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0_EXT + powerIndex*4, (pAd->Tx20MPwrCfgGBand[powerIndex] & 0xf0f0f0f0) >> 4); + } + RtmpOsMsDelay(5); + } + } + else + { + /* BW=20;A band */ + for (powerIndex=0; powerIndexTx20MPwrCfgABand[powerIndex] == 0xffffffff) + continue; + + /* TX_PWR_CFG_0 ~ TX_PWR_CFG_9 */ + /* TX_PWR_CFG_0_EXT ~ TX_PWR_CFG_4_EXT */ + if (powerIndex == 5) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_5, pAd->Tx20MPwrCfgABand[powerIndex]); + } + else if (powerIndex == 6) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_6, pAd->Tx20MPwrCfgABand[powerIndex]); + } + else if (powerIndex == 7) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_7, pAd->Tx20MPwrCfgABand[powerIndex]); + } + else if (powerIndex == 8) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_8, pAd->Tx20MPwrCfgABand[powerIndex]); + } + else if (powerIndex == 9) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_9, pAd->Tx20MPwrCfgABand[powerIndex]); + } + else + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx20MPwrCfgABand[powerIndex]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0_EXT + powerIndex*4, (pAd->Tx20MPwrCfgABand[powerIndex] & 0xf0f0f0f0) >> 4); + } + RtmpOsMsDelay(5); + } + } + + /* set BW = 20 MHz */ + /* Set BBP R4 bit[4:3]=0:0 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value &= (~0x18); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + /* Set BBP R66=0x3C */ + value = 0x3C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value); + + /* set BBP R4 = 0x40 for BW = 20 MHz */ + value = 0x40; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + /* Set BBP R68=0x0B to improve Rx sensitivity. */ + value = 0x0B; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + /* Set BBP R69=0x12 */ + value = 0x12; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + /* Set BBP R70=0x0A */ + value = 0x0A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + /* Set BBP R73=0x10 */ + value = 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + + if (pATEInfo->Channel == 14) + { + INT TxMode = pATEInfo->TxWI.PHYMODE; + + if (TxMode == MODE_CCK) + { + /* when Channel==14 && Mode==CCK && BandWidth==20M, BBP R4 bit5=1 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value |= 0x20; /* set bit5=1 */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + } + } + } + /* If bandwidth = 40M, set RF Reg4 bit 21 = 0. */ + else if (pATEInfo->TxWI.BW == BW_40) + { + if (pATEInfo->Channel <= 14) + { + /* BW=40;G band */ + for (powerIndex=0; powerIndexTx40MPwrCfgGBand[powerIndex] == 0xffffffff) + continue; + + /* TX_PWR_CFG_0 ~ TX_PWR_CFG_9 */ + /* TX_PWR_CFG_0_EXT ~ TX_PWR_CFG_4_EXT */ + if (powerIndex == 5) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_5, pAd->Tx40MPwrCfgGBand[powerIndex]); + } + else if (powerIndex == 6) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_6, pAd->Tx40MPwrCfgGBand[powerIndex]); + } + else if (powerIndex == 7) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_7, pAd->Tx40MPwrCfgGBand[powerIndex]); + } + else if (powerIndex == 8) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_8, pAd->Tx40MPwrCfgGBand[powerIndex]); + } + else if (powerIndex == 9) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_9, pAd->Tx40MPwrCfgGBand[powerIndex]); + } + else + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx40MPwrCfgGBand[powerIndex]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0_EXT + powerIndex*4, (pAd->Tx40MPwrCfgGBand[powerIndex] & 0xf0f0f0f0) >> 4); + } + RtmpOsMsDelay(5); + } + } + else + { + /* BW=40;A band */ + for (powerIndex=0; powerIndexTx40MPwrCfgABand[powerIndex] == 0xffffffff) + continue; + + /* TX_PWR_CFG_0 ~ TX_PWR_CFG_9 */ + /* TX_PWR_CFG_0_EXT ~ TX_PWR_CFG_4_EXT */ + if (powerIndex == 5) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_5, pAd->Tx40MPwrCfgABand[powerIndex]); + } + else if (powerIndex == 6) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_6, pAd->Tx40MPwrCfgABand[powerIndex]); + } + else if (powerIndex == 7) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_7, pAd->Tx40MPwrCfgABand[powerIndex]); + } + else if (powerIndex == 8) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_8, pAd->Tx40MPwrCfgABand[powerIndex]); + } + else if (powerIndex == 9) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_9, pAd->Tx40MPwrCfgABand[powerIndex]); + } + else + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx40MPwrCfgABand[powerIndex]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0_EXT + powerIndex*4, (pAd->Tx40MPwrCfgABand[powerIndex] & 0xf0f0f0f0) >> 4); + } + RtmpOsMsDelay(5); + } + + if ((pATEInfo->TxWI.PHYMODE >= 2) && (pATEInfo->TxWI.MCS == 7)) + { + value = 0x28; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R67, value); + } + } + + /* Set BBP R4 bit[4:3]=1:0 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value &= (~0x18); + value |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + /* Set BBP R66=0x3C */ + value = 0x3C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value); + + /* set BBP R4 = 0x50 for BW = 40 MHz */ + value = 0x50; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + /* Set BBP R68=0x0B to improve Rx sensitivity. */ + value = 0x0B; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + /* Set BBP R69=0x12 */ + value = 0x12; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + /* Set BBP R70=0x0A */ + value = 0x0A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + /* Set BBP R73=0x10 */ + value = 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + + } + + return TRUE; +} + + +INT RT3883_Set_ATE_TX_FREQ_OFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR RFFreqOffset = 0; + UCHAR RFValue = 0; + UCHAR diff = 0; + UCHAR RFValue2 = 0; + + RFFreqOffset = simple_strtol(arg, 0, 10); + + if (RFFreqOffset >= 96) + { + DBGPRINT_ERR(("Set_ATE_TX_FREQ_OFFSET_Proc::Out of range(0 ~ 95).\n")); + return FALSE; + } + + pATEInfo->RFFreqOffset = RFFreqOffset; + + /* Set RF offset RF_R17=RF_R23 (RT30xx) */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R17, (PUCHAR)&RFValue); + RFValue2 = (RFValue & 0x80) | pATEInfo->RFFreqOffset; + if (RFValue2 > RFValue) + { + for (diff = 1; diff <= (RFValue2 - RFValue); diff++) + { + RtmpOsMsDelay(1); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R17, (UCHAR)(RFValue + diff)); + } + } + else + { + for (diff = 1; diff <= (RFValue - RFValue2); diff++) + { + RtmpOsMsDelay(1); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R17, (UCHAR)(RFValue - diff)); + } + } + + return TRUE; +} + +struct _ATE_CHIP_STRUCT RALINK3883 = +{ + /* functions */ + .ChannelSwitch = RT3883ATEAsicSwitchChannel, + .TxPwrHandler = RT3883ATETxPwrHandler, + .TssiCalibration = NULL, + .ExtendedTssiCalibration = NULL, + .RxVGAInit = RT3883ATERxVGAInit, + .AsicSetTxRxPath = NULL, + .AdjustTxPower = DefaultATEAsicAdjustTxPower, + .AsicExtraPowerOverMAC = NULL, + + /* command handlers */ + .Set_BW_Proc = RT3883_Set_ATE_TX_BW_Proc, + .Set_FREQ_OFFSET_Proc = RT3883_Set_ATE_TX_FREQ_OFFSET_Proc, + + /* variables */ + .maxTxPwrCnt = 9, +#ifdef CONFIG_AP_SUPPORT + .bBBPStoreTXCARR = FALSE, +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + .bBBPStoreTXCARR = TRUE, +#endif /* CONFIG_STA_SUPPORT */ + .bBBPStoreTXCARRSUPP = FALSE, + .bBBPStoreTXCONT = FALSE, +#ifdef CONFIG_AP_SUPPORT + .bBBPLoadATESTOP = FALSE, +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + .bBBPLoadATESTOP = TRUE, +#endif /* CONFIG_STA_SUPPORT */ +}; + +#endif /* RT3883 */ + diff --git a/mt7620/src/ate/chips/rt5350_ate.c b/mt7620/src/ate/chips/rt5350_ate.c new file mode 100644 index 0000000..0555e8c --- /dev/null +++ b/mt7620/src/ate/chips/rt5350_ate.c @@ -0,0 +1,1646 @@ +/* + *************************************************************************** + * 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: + rt5350_ate.c + + Abstract: + Specific ATE funcitons and variables for RT5350 + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifdef RT5350 + +#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 */ + +extern FREQUENCY_ITEM FreqItems3020_Xtal20M[]; +extern FREQUENCY_ITEM RtmpFreqItems3020[]; +extern UCHAR NUM_OF_3020_CHNL; + +#ifdef RTMP_INTERNAL_TX_ALC +extern TX_POWER_TUNING_ENTRY_STRUCT RT5350_TxPowerTuningTable[]; +extern UINT32 RT5350_desiredTSSIOverCCK[4]; +/* The desired TSSI over OFDM */ +extern UINT32 RT5350_desiredTSSIOverOFDM[8]; +/* The desired TSSI over HT */ +extern UINT32 RT5350_desiredTSSIOverHT[16]; +extern UINT32 RT5350_desiredTSSIOverHT40[16]; +extern UCHAR CCK_Rate2MCS(PRTMP_ADAPTER pAd); +extern UCHAR OFDM_Rate2MCS(PRTMP_ADAPTER pAd); +extern INT32 TSSIDelta2PowDelta(UINT32 TSSI_x_10000, UINT32 TSSI_ref); + +/* +========================================================================== + Description: + Get the desired TSSI based on the latest packet + in ATE mode. + + Arguments: + pAd + pBbpR49 + + Return Value: + The desired TSSI +========================================================================== + */ +UINT32 RT5350_ATEGetDesiredTSSI( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBbpR49) +{ + UINT32 desiredTSSI = 0; + UCHAR MCS = 0; + UCHAR BbpR47 = 0; + UCHAR TssiInfo0 = 0; + UCHAR TssiInfo1 = 0; + UCHAR TssiInfo2 = 0; + UCHAR count; + UCHAR BBP_Bandwidth = 0; + UCHAR ofdm_rate = 0, dot11b_rate = 0; + + if (pAd->ate.TxWI.BW == BW_40) + { + BBP_Bandwidth = BW_40; + } + else + { + BBP_Bandwidth = BW_20; + } + + /* Get TSSI_INFO */ + for (count=0;count<100;count++) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpR47); + + if (!(BbpR47 & (1<<2))) + { + /* self-cleared when the TSSI_INFO is updated */ + /* Get TSSI_INFO0 = tssi_report[7:0] */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpR47); + BbpR47 &= ~0x3; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BbpR47 ); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &TssiInfo0); + + /* If TSSI reading is not within 0x0~0x7C, then treated it as 0. */ + if (TssiInfo0 > 0x7C) + { + DBGPRINT(RT_DEBUG_TRACE, ("TSSI: BBP_R49=%X is native value\n", TssiInfo0)); + *pBbpR49 = TssiInfo0 = 0; + } + else + { + *pBbpR49 = TssiInfo0; + } + + /* Get TSSI_INFO1 = tssi_report[15:8] */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpR47); + BbpR47 &= ~0x3; + BbpR47 |= 1; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BbpR47 ); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &TssiInfo1); + + switch (TssiInfo1 & 0x03) + { + case 0: /* CCK */ + dot11b_rate = (TssiInfo1 >> 4) & 0xF; /* tssi_report[13:12]=11b rate */ + + switch(dot11b_rate) + { + case 8: + MCS = 0; /* Long preamble CCK 1Mbps */ + break; + case 9: + MCS = 1; /* Long preamble CCK 2Mbps */ + break; + case 10: + MCS = 2; /* Long preamble CCK 5.5Mbps */ + break; + case 11: + MCS = 3; /* Long preamble CCK 11Mbps */ + break; + default: + MCS = 0; + break; + } + desiredTSSI = RT5350_desiredTSSIOverCCK[MCS]; + DBGPRINT(RT_DEBUG_INFO, ("CCK: desiredTSSI = %d, MCS = %d\n", desiredTSSI, MCS)); + break; + + case 1: /* OFDM */ + ofdm_rate = (TssiInfo1 >> 4) & 0xF; /* rssi_15:12]=ofdm_rate */ + + switch (ofdm_rate) + { + case 0xb: + MCS = 0; /* 6Mbps Rate */ + break; + case 0xf: + MCS = 1; /* 9Mbps Rate */ + break; + case 0xa: + MCS = 2; /* 12Mbps Rate */ + break; + case 0xe: + MCS = 3; /* 18Mbps Rate */ + break; + case 0x9: + MCS = 4; /* 24Mbps Rate */ + break; + case 0xd: + MCS = 5; /* 36Mbps Rate */ + break; + case 0x8: + MCS = 6; /* 48Mbps Rate */ + break; + case 0xc: + MCS = 7; /* 54Mbps Rate */ + break; + default: + MCS = 6; + break; + }; + desiredTSSI = RT5350_desiredTSSIOverOFDM[MCS]; + DBGPRINT(RT_DEBUG_INFO, ("OFDM: desiredTSSI = %d, MCS = %d\n", desiredTSSI, MCS)); + break; + + case 2: /* HT */ + DBGPRINT(RT_DEBUG_INFO, ("mixed mode or green-field mode\n")); + /* Get TSSI_INFO2 = tssi_report[23:16] */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpR47); + BbpR47 &= ~0x3; + BbpR47 |= 1<<1; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BbpR47 ); + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &TssiInfo2); + MCS = TssiInfo2 & 0x7F; /* tssi_report[22:16]=MCS */ + + if ((BBP_Bandwidth == BW_40) + && ((MCS == 5) || (MCS == 6) || (MCS == 7))) + { + desiredTSSI = RT5350_desiredTSSIOverHT40[MCS]; + } + else + { + desiredTSSI = RT5350_desiredTSSIOverHT[MCS]; + } + + DBGPRINT(RT_DEBUG_INFO, ("HT: desiredTSSI = %d, MCS = %d\n", desiredTSSI, MCS)); + break; + } + break; + } + } + + /* clear TSSI_UPDATE_REQ first */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpR47); + BbpR47 &= ~0x7; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BbpR47 ); + + /* write 1 to enable TSSI_INFO update */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpR47); + BbpR47 |= (1<<2); /* TSSI_UPDATE_REQ */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BbpR47 ); + + return desiredTSSI; +} + + +INT ATE_GET_TSSI( + IN PRTMP_ADAPTER pAd, + IN INT MODE, + IN INT MCS, + OUT PUCHAR pBbpR49) +{ + UCHAR BbpR47=0; + UCHAR TssiInfo0=0; + UCHAR TssiInfo1=0; + UCHAR TssiInfo2=0; + UCHAR i; + + if (IS_RT5350(pAd)) + { + /* clear TSSI_UPDATE_REQ first */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpR47); + BbpR47 &= ~0x7; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BbpR47); + + /* write 1 to enable TSSI_INFO update */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpR47); + BbpR47 |= (1<<2); /* TSSI_UPDATE_REQ */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BbpR47); + RtmpOsMsDelay(100); + + /* Get TSSI_INFO0 = tssi_report[7:0] */ + for (i = 0; i < 100; i++) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpR47); + if (!(BbpR47 & (1 << 2))) + { + /* self-cleared when the TSSI_INFO is updated */ + /* Get TSSI_INFO0 = tssi_report[7:0] */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpR47); + BbpR47 &= ~0x3; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BbpR47); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &TssiInfo0); + + /* If TSSI reading is not within 0x0~0x7C, then treated it as 0. */ + if (TssiInfo0 > 0x7C) + { + DBGPRINT(RT_DEBUG_TRACE, ("TSSI: BBP_R49=%X is native value\n", TssiInfo0)); + *pBbpR49 = TssiInfo0 = 0; + continue; + } + else + { + *pBbpR49 = TssiInfo0; + } + + /* Get TSSI_INFO1 = tssi_report[15:8] */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpR47); + BbpR47 &= ~0x3; + BbpR47 |= 1; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BbpR47); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &TssiInfo1); + + if ((TssiInfo1 & 0x3) != MODE) + continue; + + switch (TssiInfo1 & 0x3) + { + UCHAR pkt_MCS; + + case MODE_CCK: /* CCK */ + pkt_MCS = CCK_Rate2MCS(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("CCK: MCS = %d\n", pkt_MCS)); + if (MCS != pkt_MCS) + continue; + break; + case MODE_OFDM: /* OFDM */ + + pkt_MCS = OFDM_Rate2MCS(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("OFDM: MCS = %d\n", pkt_MCS)); + if (MCS != pkt_MCS) + continue; + break; + case MODE_HTMIX: /* HT */ + /* Get TSSI_INFO2 = tssi_report[23:16] */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpR47); + BbpR47 &= ~0x3; + BbpR47 |= 1<<1; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BbpR47); + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &TssiInfo2); + pkt_MCS = TssiInfo2 & 0x7F; /* tssi_report[22:16]=MCS */ + DBGPRINT(RT_DEBUG_TRACE, ("HT: MCS = %d\n", pkt_MCS)); + if (MCS != pkt_MCS) /* tssi_report[22:16]=MCS */ + continue; + break; + } + break; + } + } + + } + + return TRUE; +} + + +INT RT5350_ATETssiCalibrationExtend( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + INT i; + USHORT EEPData, EEPData2; + UINT32 TSSI_x_10000[15]; + INT32 TSSI_power_delta[15]; + UCHAR TSSI_CH1, TSSI_CH7, TSSI_CH13; + INT TSSI_CH1_10000, TSSI_CH7_10000, TSSI_CH13_10000; + TssiDeltaInfo TSSI_x_h, TSSI_x_l; + + if (!IS_RT5350(pAd)) + { + DBGPRINT_ERR(("Not support TSSI calibration!!!\n")); + DBGPRINT_ERR(("Not RT5350!!!\n")); + + return FALSE; + } + else + { + UCHAR BSSID_ADDR[MAC_ADDR_LEN] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + + pAd->TxPowerCtrl.bInternalTxALC = TRUE; + RT5350_InitDesiredTSSITable(pAd); + + /* update EEPROM power value to pAd struct */ + RTMPReadChannelPwr(pAd); + + /* start TX at 54Mbps Channel 1 */ + NdisZeroMemory(pATEInfo, sizeof(struct _ATE_INFO)); + pATEInfo->TxCount = 100000; + pATEInfo->TxLength = 1024; + COPY_MAC_ADDR(pATEInfo->Addr1, BROADCAST_ADDR); + COPY_MAC_ADDR(pATEInfo->Addr2, pAd->PermanentAddress); + COPY_MAC_ADDR(pATEInfo->Addr3, BSSID_ADDR); + + Set_ATE_TX_MODE_Proc(pAd, "1"); /* MODE_OFDM */ + Set_ATE_TX_MCS_Proc(pAd, "7"); /* 54Mbps */ + Set_ATE_TX_BW_Proc(pAd, "0"); /* 20MHz */ + + /* read frequency offset from EEPROM */ + RT28xx_EEPROM_READ16(pAd, EEPROM_FREQ_OFFSET, EEPData); + pATEInfo->RFFreqOffset = (UCHAR) (EEPData & 0xff); + + /* set channel 1 power value calibrated DAC */ + pATEInfo->TxPower0 = pAd->TxPower[0].Power; + pATEInfo->Channel = 1; + + Set_ATE_Proc(pAd, "TXFRAME"); + RTMPusecDelay(200000); + ATE_GET_TSSI(pAd, MODE_OFDM, 7, &TSSI_CH1); + DBGPRINT(RT_DEBUG_TRACE, ("TSSI CALIBRATION: Channel[1] TSSI=%x\n", TSSI_CH1)); + + if (TSSI_CH1 < 0x18) + { + DBGPRINT_ERR(("TSSI CALIBRATION: Channel[1] TSSI is abnormal, set to 0x18\n")); + TSSI_CH1 = 0x18; + } + + if (TSSI_CH1 > 0x33) + { + DBGPRINT_ERR(("TSSI CALIBRATION: Channel[1] TSSI is abnormal, set to 0x33\n")); + TSSI_CH1 = 0x33; + } + + /* set channel 7 power value calibrated DAC */ + pATEInfo->TxPower0 = pAd->TxPower[6].Power; + pATEInfo->Channel = 7; + + Set_ATE_Proc(pAd, "TXFRAME"); + RTMPusecDelay(200000); + ATE_GET_TSSI(pAd, MODE_OFDM, 7, &TSSI_CH7); + DBGPRINT(RT_DEBUG_TRACE, ("TSSI CALIBRATION: Channel[7] TSSI=%x\n", TSSI_CH7)); + + if (TSSI_CH7 < 0x18) + { + DBGPRINT_ERR(("TSSI CALIBRATION: Channel[7] TSSI is abnormal, set to 0x18\n")); + TSSI_CH7 = 0x18; + } + + if (TSSI_CH7 > 0x33) + { + DBGPRINT_ERR(("TSSI CALIBRATION: Channel[7] TSSI is abnormal, set to 0x33\n")); + TSSI_CH7 = 0x33; + } + + /* set channel 13 power value calibrated DAC */ + pATEInfo->TxPower0 = pAd->TxPower[12].Power; + pATEInfo->Channel = 13; + + Set_ATE_Proc(pAd, "TXFRAME"); + RTMPusecDelay(200000); + ATE_GET_TSSI(pAd, MODE_OFDM, 7, &TSSI_CH13); + DBGPRINT(RT_DEBUG_TRACE, ("TSSI CALIBRATION: Channel[13] TSSI=%x\n", TSSI_CH13)); + + if (TSSI_CH13 < 0x18) + { + DBGPRINT_ERR(("TSSI CALIBRATION: Channel[13] TSSI is abnormal, set to 0x18\n")); + TSSI_CH13 = 0x18; + } + + if (TSSI_CH13 > 0x33) + { + DBGPRINT_ERR(("TSSI CALIBRATION: Channel[13] TSSI is abnormal, set to 0x33\n")); + TSSI_CH13 = 0x33; + } + + TSSI_CH1_10000 = TSSI_CH1 * 10000; + TSSI_CH7_10000 = TSSI_CH7 * 10000; + TSSI_CH13_10000 = TSSI_CH13 * 10000; + TSSI_x_10000[1] = TSSI_CH1_10000; + TSSI_x_10000[7] = TSSI_CH7_10000; + TSSI_x_10000[13] = TSSI_CH13_10000; + + for (i = 2; i < 7; i++) + TSSI_x_10000[i] = TSSI_CH1_10000 + (i - 1) * ((TSSI_CH7_10000 - TSSI_CH1_10000) / (7 - 1)); + + for (i = 8; i <= 14; i++) + TSSI_x_10000[i] = TSSI_CH7_10000 + (i - 7) * ((TSSI_CH13_10000 - TSSI_CH7_10000) / (13 - 7)); + + for (i = 1; i <= 14; i++) + { + TSSI_power_delta[i] = TSSIDelta2PowDelta(TSSI_x_10000[i], TSSI_CH7); + DBGPRINT(RT_DEBUG_TRACE, ("TSSI CALIBRATION: Channel[%d] TSSI_x=%d\n", i, TSSI_x_10000[i])); + DBGPRINT(RT_DEBUG_TRACE, ("TSSI CALIBRATION: Channel[%d] TSSI_power_delta=%d\n", i, TSSI_power_delta[i])); + } + + /* 2.4G internal ALC reference value (channel 7) */ + EEPData = 0x0 | (TSSI_CH7_10000 / 10000); + RT28xx_EEPROM_WRITE16(pAd, EEPROM_TSSI_REF_OFFSET, EEPData); + + /* Channel 2 TSSI delta:Channel 1 TSSI delta */ + TSSI_x_l.delta = TSSI_power_delta[1]; + TSSI_x_h.delta = TSSI_power_delta[2]; + EEPData = TSSI_x_h.delta << 4 | TSSI_x_l.delta; + RT28xx_EEPROM_WRITE16(pAd, EEPROM_TSSI_DELTA_CH1_CH2, EEPData); + + /* Channel 4 TSSI delta:Channel 3 TSSI delta */ + TSSI_x_l.delta = TSSI_power_delta[3]; + TSSI_x_h.delta = TSSI_power_delta[4]; + EEPData = TSSI_x_h.delta << 4 | TSSI_x_l.delta; + RT28xx_EEPROM_WRITE16(pAd, EEPROM_TSSI_DELTA_CH3_CH4, EEPData); + + /* Channel 6 TSSI delta:Channel 5 TSSI delta */ + TSSI_x_l.delta = TSSI_power_delta[5]; + TSSI_x_h.delta = TSSI_power_delta[6]; + EEPData = TSSI_x_h.delta << 4 | TSSI_x_l.delta; + RT28xx_EEPROM_WRITE16(pAd, EEPROM_TSSI_DELTA_CH5_CH6, EEPData); + + /* Channel 8 TSSI delta:Channel 7 TSSI delta */ + TSSI_x_l.delta = TSSI_power_delta[7]; + TSSI_x_h.delta = TSSI_power_delta[8]; + EEPData = TSSI_x_h.delta << 4 | TSSI_x_l.delta; + RT28xx_EEPROM_WRITE16(pAd, EEPROM_TSSI_DELTA_CH7_CH8, EEPData); + + /* Channel 10 TSSI delta:Channel 9 TSSI delta */ + TSSI_x_l.delta = TSSI_power_delta[9]; + TSSI_x_h.delta = TSSI_power_delta[10]; + EEPData = TSSI_x_h.delta << 4 | TSSI_x_l.delta; + RT28xx_EEPROM_WRITE16(pAd, EEPROM_TSSI_DELTA_CH9_CH10, EEPData); + + /* Channel 12 TSSI delta:Channel 11 TSSI delta */ + TSSI_x_l.delta = TSSI_power_delta[11]; + TSSI_x_h.delta = TSSI_power_delta[12]; + EEPData = TSSI_x_h.delta << 4 | TSSI_x_l.delta; + RT28xx_EEPROM_WRITE16(pAd, EEPROM_TSSI_DELTA_CH11_CH12, EEPData); + + /* Channel 14 TSSI delta:Channel 13 TSSI delta */ + TSSI_x_l.delta = TSSI_power_delta[13]; + TSSI_x_h.delta = TSSI_power_delta[14]; + + RT28xx_EEPROM_READ16(pAd, EEPROM_TSSI_DELTA_CH13_CH14 + 1, EEPData2); + EEPData = (EEPData2 << 8) | (TSSI_x_h.delta << 4) | TSSI_x_l.delta; + RT28xx_EEPROM_WRITE16(pAd, EEPROM_TSSI_DELTA_CH13_CH14, EEPData); + } + + /* disable legacy ALC and set TSSI enabled and TSSI extend mode to EEPROM */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TSSI_ENABLE, EEPData); + /* disable legacy ALC */ + EEPData &= ~(1 << 1); + /* enable TSSI */ + EEPData |= (1 << 13); + RT28xx_EEPROM_WRITE16(pAd, EEPROM_TSSI_ENABLE, EEPData); + RTMPusecDelay(10); + + RT28xx_EEPROM_READ16(pAd, EEPROM_TSSI_MODE_EXTEND, EEPData); + /* set extended TSSI mode */ + EEPData |= (1 << 15); + RT28xx_EEPROM_WRITE16(pAd, EEPROM_TSSI_MODE_EXTEND, EEPData); + RTMPusecDelay(10); + + return TRUE; +} +#endif /* RTMP_INTERNAL_TX_ALC */ + + +/* +========================================================================== + Description: + + AsicSwitchChannel() dedicated for RT5350 ATE. + +========================================================================== +*/ +VOID RT5350ATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 Value = 0; + UINT32 step=0; + CHAR TxPwer = 0, TxPwer2 = 0; + UCHAR index = 0, BbpValue = 0, Channel = 0; + /* added to prevent RF register reading error */ + UCHAR RFValue = 0, RFValue2 = 0; + + SYNC_CHANNEL_WITH_QA(pATEInfo, &Channel); + + /* fill Tx power value */ + TxPwer = pATEInfo->TxPower0; + TxPwer2 = pATEInfo->TxPower1; + + for (index = 0; index < NUM_OF_3020_CHNL; index++) + { + /* Please don't change "RtmpFreqItems3020" to "FreqItems3020" ! */ + if (Channel == RtmpFreqItems3020[index].Channel) + { + /* programming channel parameters */ + step = (*((volatile u32 *)(RALINK_SYSCTL_BASE + 0x10))); + + /* Programming channel parameters */ + if(step & (1<<20)) + { + /* Xtal=40M */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R08, RtmpFreqItems3020[index].N); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R09, RtmpFreqItems3020[index].K); + RFValue = 0x9F; + } + else + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R08, FreqItems3020_Xtal20M[index].N); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R09, FreqItems3020_Xtal20M[index].K); + RFValue = 0x1F; + } + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R13, (UCHAR)RFValue); + + RFValue = 0x4A; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R11, (UCHAR)RFValue); + + RFValue = 0x46; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R12, (UCHAR)RFValue); + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R30, (PUCHAR)&RFValue); + + if (pATEInfo->TxWI.BW == BW_20) + { + RFValue &= ~(0x06); /* 20MBW tx_h20M=0,rx_h20M=0 */ + } + else + { + RFValue |= 0x06; /* 40MBW tx_h20M=1,rx_h20M=1 */ + } + + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R30, (UCHAR)RFValue); + + if (pATEInfo->TxWI.PHYMODE == MODE_CCK) + { + RFValue = 0xC0; + } + else + { + RFValue = 0x80; + } + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R32, (UCHAR)RFValue); + + RFValue = 0x04; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R53, (UCHAR)RFValue); + + if (pATEInfo->TxWI.PHYMODE == MODE_CCK) + { + RFValue = 0x47; + } + else + { + RFValue = 0x43; + } + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R55, (UCHAR)RFValue); + + RFValue = 0xC2; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R56, (UCHAR)RFValue); + + switch (Channel) + { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + RFValue = 0x0B; + break; + case 8: + case 9: + RFValue = 0x0A; + break; + case 10: + RFValue = 0x09; + break; + case 11: + RFValue = 0x08; + break; + case 12: + case 13: + RFValue = 0x07; + break; + case 14: + RFValue = 0x06; + break; + default: + RFValue = 0x0B; + break; + } + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R59, (UCHAR)RFValue); + + RFValue2 = pATEInfo->TxPower0 | (1 << 7); /* bit 7 = 1 */ + RFValue2 &= ~(1 << 6); /* bit 6 = 0 */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R49, RFValue2); + + RFValue = 0x04; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R53, (UCHAR)RFValue); + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R03, (PUCHAR)&RFValue); + RFValue = RFValue | 0x80; /* bit 7=vcocal_en */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R03, (UCHAR)RFValue); + + RTMPusecDelay(2000); + + /* set BW */ + /* RF_R24 is reserved bits */ + RFValue = 0; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R24, (UCHAR)RFValue); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R31, 0x80); + + /* Enable RF tuning, this must be in the last, RF_R03=RF_R07. */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R03, (PUCHAR)&RFValue); + RFValue = RFValue | 0x80; /* bit 7=vcocal_en */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R03, (UCHAR)RFValue); + + RtmpOsMsDelay(2); + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, (PUCHAR)&RFValue); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R49, RFValue & 0xfe); /* clear update flag */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, (PUCHAR)&RFValue); + + /* Antenna */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R01, (PUCHAR)&RFValue); + RFValue = (RFValue & 0x03) | 0x01; + if (pATEInfo->RxAntennaSel == 1) + { + RFValue = RFValue | 0x04; /* rx0_en */ + } + else if (pATEInfo->RxAntennaSel == 2) + { + RFValue = RFValue | 0x10; /* rx1_en */ + } + else + { + RFValue = RFValue | 0x14; /* rx0_en and rx1_en */ + } + + if (pATEInfo->TxAntennaSel == 1) + { + RFValue = RFValue | 0x08; /* tx0_en */ + } + else if (pATEInfo->TxAntennaSel == 2) + { + RFValue = RFValue | 0x20; /* tx1_en */ + } + else + { + RFValue = RFValue | 0x28; /* tx0_en and tx1_en */ + } + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R01, (UCHAR)RFValue); + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue = BbpValue & 0x24; /* clear bit 0,1,3,4,6,7 */ + + if (pATEInfo->RxAntennaSel == 1) + { + BbpValue &= ~0x3; /* BBP_R3[1:0]=00 (ADC0) */ + } + else if (pATEInfo->RxAntennaSel == 2) + { + BbpValue &= ~0x3; + BbpValue |= 0x1; /* BBP_R3[1:0]=01 (ADC1) */ + } + else + { + /* RXANT_NUM >= 2, must turn on Bit 0 and 1 for all ADCs */ + BbpValue |= 0x3; /* BBP_R3[1:0]=11 (All ADCs) */ + if (pAd->Antenna.field.RxPath == 3) + BbpValue |= (1 << 4); + else if (pAd->Antenna.field.RxPath == 2) + BbpValue |= (1 << 3); /* BBP_R3[3]=1 (2R) */ + else if (pAd->Antenna.field.RxPath == 1) + BbpValue |= (0x0); + } + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + + if (pATEInfo->TxWI.BW == BW_20) + { + /* set BBP R4 = 0x40 for BW = 20 MHz */ + BbpValue = 0x40; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BbpValue); + } + else + { + /* set BBP R4 = 0x50 for BW = 40 MHz */ + BbpValue = 0x50; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BbpValue); + } + + /* latch channel for future usage */ + pAd->LatchRfRegs.Channel = Channel; + break; + } + } + + /* Change BBP setting during switch from a->g, g->a */ + if (Channel <= 14) + { + UINT32 TxPinCfg = 0x00050F0A;/* 2007.10.09 by Brian : 0x0005050A ==> 0x00050F0A */ + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + + /* Gary : 2010/0721 */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x38); + + /* Rx High power VGA offset for LNA select */ + if (pAd->NicConfig2.field.ExternalLNAForG) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + /* 2.4 G band selection PIN */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x04); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + if (pATEInfo->TxAntennaSel == 1) + { + TxPinCfg &= 0xFFFFFFF3; + } + else if (pATEInfo->TxAntennaSel == 2) + { + TxPinCfg &= 0xFFFFFFFC; + } + else + { + TxPinCfg &= 0xFFFFFFFF; + } + + if (pATEInfo->RxAntennaSel == 1) + { + TxPinCfg &= 0xFFFFF3FF; + } + else if (pATEInfo->RxAntennaSel == 2) + { + TxPinCfg &= 0xFFFFFCFF; + } + else + { + TxPinCfg &= 0xFFFFFFFF; + } + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + } + + ATE_CHIP_RX_VGA_GAIN_INIT(pAd); + + RtmpOsMsDelay(1); + + Value = (*((volatile u32 *)(RALINK_SYSCTL_BASE + 0x10))); + + if (Value & (1 << 20)) + { + /* Xtal=40M */ + DBGPRINT(RT_DEBUG_TRACE, ("RT5350:SwitchChannel#%d(RFIC=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", + Channel, + pAd->RfIcType, + TxPwer, + TxPwer2, + pAd->Antenna.field.TxPath, + RtmpFreqItems3020[index].N, + RtmpFreqItems3020[index].K, + RtmpFreqItems3020[index].R)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("RT5350Xtal20M:SwitchChannel#%d(RFIC=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", + Channel, + pAd->RfIcType, + TxPwer, + TxPwer2, + pAd->Antenna.field.TxPath, + FreqItems3020_Xtal20M[index].N, + FreqItems3020_Xtal20M[index].K, + FreqItems3020_Xtal20M[index].R)); + } +} + + +INT RT5350ATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index) +{ + PATE_INFO pATEInfo = &(pAd->ate); + CHAR TxPower = 0; + UCHAR RFValue = 0; + +#ifdef RALINK_QA + if ((pATEInfo->bQATxStart == TRUE) || (pATEInfo->bQARxStart == TRUE)) + { + return 0; + } + else +#endif /* RALINK_QA */ + if (index == 0) + { + TxPower = pATEInfo->TxPower0; + } + else + { + DBGPRINT_ERR(("%s : Only TxPower0 is adjustable !\n", __FUNCTION__)); + DBGPRINT_ERR(("%s : TxPower%d is out of range !\n", __FUNCTION__, index)); + return -1; + } + + RFValue = pATEInfo->TxPower0 | (1 << 7); /* bit 7 = 1 */ + RFValue &= ~(1 << 6); /* bit 6 = 0 */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R49, RFValue); + + DBGPRINT(RT_DEBUG_TRACE, ("%s : (TxPower%d=%d, RFValue=%x)\n", __FUNCTION__, index, TxPower, RFValue)); + + return 0; +} + + +VOID RT5350ATERxVGAInit( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR R66; + CHAR LNAGain = GET_LNA_GAIN(pAd); + + /* R66 should be set according to Channel. */ + if (pATEInfo->Channel <= 14) + { + /* BG band */ + if (pATEInfo->TxWI.BW == BW_20) + { + R66 = (UCHAR)(0x1C + (LNAGain*2)); + } + else + { + R66 = (UCHAR)(0x24 + (LNAGain*2)); + } + } + else + { + /* A band. Not supported. */ + DBGPRINT_ERR(("%s :Ch=%d\n", __FUNCTION__, pATEInfo->Channel)); + DBGPRINT_ERR(("%s :5 GHz band not supported !\n", __FUNCTION__)); + + return; + } + + ATEBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + + + return; +} + + +VOID RT5350ATEAsicExtraPowerOverMAC( + 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); + + DBGPRINT(RT_DEBUG_TRACE, ("Offset = 0x13D4, TxPwr = 0x%08X, Offset = 0x13DC, TxPwr = 0x%08X\n", + (UINT)ExtraPwrOverTxPwrCfg7, + (UINT)ExtraPwrOverTxPwrCfg9)); +} + + +/* +========================================================================== + Description: + Set RT5350 ATE RF BW + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT RT5350_Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + INT powerIndex; + UCHAR value = 0; + UCHAR BBPCurrentBW; + + BBPCurrentBW = simple_strtol(arg, 0, 10); + + if (BBPCurrentBW == 0) + { + pATEInfo->TxWI.BW = BW_20; + } + else + { + pATEInfo->TxWI.BW = BW_40; + } + + if ((pATEInfo->TxWI.PHYMODE == MODE_CCK) && (pATEInfo->TxWI.BW == BW_40)) + { + DBGPRINT_ERR(("Set_ATE_TX_BW_Proc!! Warning!! CCK only supports 20MHZ!!\n")); + DBGPRINT_ERR(("Bandwidth switch to 20!!\n")); + pATEInfo->TxWI.BW = BW_20; + } + + if (pATEInfo->TxWI.BW == BW_20) + { + if (pATEInfo->Channel <= 14) + { + /* BW=20;G band */ + for (powerIndex=0; powerIndexTx20MPwrCfgGBand[powerIndex] == 0xffffffff) + continue; + + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx20MPwrCfgGBand[powerIndex]); + RtmpOsMsDelay(5); + } + } + else + { + /* BW=20;A band */ + for (powerIndex=0; powerIndexTx20MPwrCfgABand[powerIndex] == 0xffffffff) + continue; + + /* TX_PWR_CFG_0 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx20MPwrCfgABand[powerIndex]); + RtmpOsMsDelay(5); + } + } + + /* set BW = 20 MHz */ + value = 0x40; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + value = 0; /* RF_R24 is reserved bits */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R24, (UCHAR)value); + /* Rx filter */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R31, 0x80); + + /* BW = 20 MHz */ + /* Set BBP R68=0x0B to improve Rx sensitivity. */ + value = 0x0B; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + /* Set BBP R69=0x16 */ + value = 0x12; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + /* Set BBP R70=0x08 */ + value = 0x0A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + /* Set BBP R73=0x11 */ + value = 0x13; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + + if (pATEInfo->Channel == 14) + { + INT TxMode = pATEInfo->TxWI.PHYMODE; + + if (TxMode == MODE_CCK) + { + /* when Channel==14 && Mode==CCK && BandWidth==20M, BBP R4 bit5=1 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value |= 0x20; /* set bit5=1 */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + } + } + } + /* If bandwidth = 40M, set RF Reg4 bit 21 = 0. */ + else if (pATEInfo->TxWI.BW == BW_40) + { + if (pATEInfo->Channel <= 14) + { + /* BW=40;G band */ + for (powerIndex=0; powerIndexTx40MPwrCfgGBand[powerIndex] == 0xffffffff) + continue; + + /* TX_PWR_CFG_0 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx40MPwrCfgGBand[powerIndex]); + RtmpOsMsDelay(5); + } + } + else + { + /* BW=40;A band */ + for (powerIndex=0; powerIndexTx40MPwrCfgABand[powerIndex] == 0xffffffff) + continue; + + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx40MPwrCfgABand[powerIndex]); + RtmpOsMsDelay(5); + } + + if ((pATEInfo->TxWI.PHYMODE >= 2) && (pATEInfo->TxWI.MCS == 7)) + { + value = 0x28; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R67, value); + } + } + + /* Set BBP R4 bit[4:3]=1:0 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value &= (~0x18); + value |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + value = 0x00; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R24, (UCHAR)value); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R31, 0x80); + + /* BW = 40 MHz */ + /* Set BBP R68=0x0B to improve Rx sensitivity. */ + value = 0x0B; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + /* Set BBP R69=0x16 */ + value = 0x12; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + /* Set BBP R70=0x08 */ + value = 0x0A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + /* Set BBP R73=0x11 */ + value = 0x13; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + } + + return TRUE; +} + + +INT RT5350_Set_ATE_TX_FREQ_OFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR RFFreqOffset = 0; + UCHAR RFValue = 0; + UCHAR offset = 0; + UCHAR RFValue2 = 0; + + RFFreqOffset = simple_strtol(arg, 0, 10); + + if (RFFreqOffset >= 96) + { + DBGPRINT_ERR(("Set_ATE_TX_FREQ_OFFSET_Proc::Out of range(0 ~ 95).\n")); + return FALSE; + } + + pATEInfo->RFFreqOffset = RFFreqOffset; + + /* set RF frequency offset */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R17, (PUCHAR)&RFValue); + + RFValue2 = pATEInfo->RFFreqOffset & 0x7F; /* bit7 = 0 */ + + if (RFValue2 > RFValue) + { + for (offset = 1; offset <= (RFValue2 - RFValue); offset++) + { + RtmpOsMsDelay(1); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R17, (UCHAR)(RFValue + offset)); + } + } + else + { + for (offset = 1; offset <= (RFValue - RFValue2); offset++) + { + RtmpOsMsDelay(1); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R17, (UCHAR)(RFValue - offset)); + } + } + + return TRUE; +} + + +VOID RT5350ATEAsicAdjustTxPower( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + INT i, j, maxTxPwrCnt=5; + CHAR DeltaPwr = 0; + BOOLEAN bAutoTxAgc = FALSE; + UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep; + UCHAR BbpR49 = 0, idx; + PCHAR pTxAgcCompensate; + ULONG TxPwr[maxTxPwrCnt]; + CHAR Value; +#ifdef RTMP_INTERNAL_TX_ALC + /* + TotalDeltaPower: (non-positive number) including + the transmit power controlled by the MAC and the BBP R1 + */ + CHAR TotalDeltaPower = 0, TuningTableIndex = 0; + UINT32 desiredTSSI = 0, currentTSSI = 0, room_up = 0, room_down = 0; + PTX_POWER_TUNING_ENTRY_STRUCT pTxPowerTuningEntry = NULL; + UCHAR RFValue = 0; + BOOLEAN bKeepRF = FALSE; + static UCHAR LastChannel = 0; +#endif /* RTMP_INTERNAL_TX_ALC */ + + /* Get Tx Rate Offset Table which from eeprom 0xDEh ~ 0xEFh */ + if (pATEInfo->TxWI.BW == BW_40) + { + if (pATEInfo->Channel > 14) + { + for (i =0 ; i < maxTxPwrCnt; i ++) + { + TxPwr[i] = pAd->Tx40MPwrCfgABand[i]; + } + } + else + { + for (i =0 ; i < maxTxPwrCnt; i ++) + { + TxPwr[i] = pAd->Tx40MPwrCfgGBand[i]; + } + } + } + else + { + if (pATEInfo->Channel > 14) + { + for (i =0 ; i < maxTxPwrCnt; i ++) + { + TxPwr[i] = pAd->Tx20MPwrCfgABand[i]; + } + } + else + { + for (i =0 ; i < maxTxPwrCnt; i ++) + { + TxPwr[i] = pAd->Tx20MPwrCfgGBand[i]; + } + } + } + + /* Get temperature compensation Delta Power Value */ +#ifdef RTMP_INTERNAL_TX_ALC + /* Locate the internal Tx ALC tuning entry */ + if (pAd->TxPowerCtrl.bInternalTxALC == TRUE) + { + /* In ATE mode, the period of power compensation is 1 second. */ +/* if (pATEInfo->OneSecPeriodicRound % 4 == 0) */ + { + desiredTSSI = RT5350_ATEGetDesiredTSSI(pAd, &BbpR49); + + room_down = (desiredTSSI >> 5); + room_up = (desiredTSSI >> 2); + + currentTSSI = BbpR49 * 10000; + + DBGPRINT(RT_DEBUG_TRACE, ("DesiredTSSI = %d, CurrentTSSI = %d (Range: %d ~ %d, BBP_R49=0x%X)\n", + desiredTSSI, currentTSSI, desiredTSSI-room_up, + desiredTSSI+room_down, BbpR49)); + + if (LastChannel != pATEInfo->Channel) + { + pAd->TxPowerCtrl.idxTxPowerTable = 0; + } + + if (desiredTSSI-room_up > currentTSSI) + { + pAd->TxPowerCtrl.idxTxPowerTable++; + } + else if (desiredTSSI+room_down < currentTSSI) + { + pAd->TxPowerCtrl.idxTxPowerTable--; + } + else + { + bKeepRF = TRUE; + } + + LastChannel = pATEInfo->Channel; + + /* To reduce the time for TSSI compensated to target value */ + TuningTableIndex = pAd->TxPowerCtrl.idxTxPowerTable + + pAd->TxPower[pATEInfo->Channel-1].Power; + + if (TuningTableIndex < LOWERBOUND_TX_POWER_TUNING_ENTRY) + { + TuningTableIndex = LOWERBOUND_TX_POWER_TUNING_ENTRY; + } + + if (TuningTableIndex >= UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd)) + { + TuningTableIndex = UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd); + } + + /* Valid pAd->TxPowerCtrl.idxTxPowerTable: -30 ~ 61 */ + pTxPowerTuningEntry = &RT5350_TxPowerTuningTable[TuningTableIndex + TX_POWER_TUNING_ENTRY_OFFSET]; + pAd->TxPowerCtrl.RF_TX_ALC = pTxPowerTuningEntry->RF_TX_ALC; + pAd->TxPowerCtrl.MAC_PowerDelta = pTxPowerTuningEntry->MAC_PowerDelta; + + if (bKeepRF == FALSE) + { + /* Tx power adjustment over RF is needed */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R49, (PUCHAR)(&RFValue)); /* TX0_ALC */ + RFValue &= ~0x3F; /* clear RF_R49[5:0] */ + RFValue |= pAd->TxPowerCtrl.RF_TX_ALC; + + /* The valid range of the RF R49 (<5:0>tx0_alc<5:0>) is 0x00~0x27 */ + if ((RFValue & 0x3F) > 0x27) + { + RFValue = ((RFValue & ~0x3F) | 0x27); + } + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R49, (UCHAR)RFValue); /* TX0_ALC */ + + DBGPRINT(RT_DEBUG_TRACE, ("RF_R49 = %u\n", RFValue)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("Pwr0 = 0x%02x\n", (pAd->TxPower[pATEInfo->Channel-1].Power))); + DBGPRINT(RT_DEBUG_TRACE, ("TuningTableIndex = %d\n", TuningTableIndex)); + + /* Tx power adjustment over MAC */ + TotalDeltaPower = pAd->TxPowerCtrl.MAC_PowerDelta; + + DBGPRINT(RT_DEBUG_TRACE, ("Current index of tuning table = %d {RF_TX_ALC = 0x%02x, MAC_PowerDelta = %d}\n", + (TuningTableIndex + TX_POWER_TUNING_ENTRY_OFFSET), + pAd->TxPowerCtrl.RF_TX_ALC, + pAd->TxPowerCtrl.MAC_PowerDelta)); + + DBGPRINT(RT_DEBUG_TRACE, ("\n\n")); + + } + } +#endif /* RTMP_INTERNAL_TX_ALC */ + + /* Legacy Tx power compensation for temperature variation based on TSSI. */ + /* Do it per 4 seconds. */ + if (pATEInfo->OneSecPeriodicRound % 4 == 0) + { + if (pATEInfo->Channel <= 14) + { + /* bg channel */ + bAutoTxAgc = pAd->bAutoTxAgcG; + TssiRef = pAd->TssiRefG; + pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0]; + TxAgcStep = pAd->TxAgcStepG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + /* a channel */ + bAutoTxAgc = pAd->bAutoTxAgcA; + TssiRef = pAd->TssiRefA; + pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0]; + TxAgcStep = pAd->TxAgcStepA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + { + /* BbpR49 is unsigned char. */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); + + /* (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 0x10 ~ 0x40, minus is 0x60 ~ 0x90 */ + /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */ + /* if value is 0x65, tx power will be -= TxAgcStep*(2-1) */ + + if (BbpR49 > 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++) + { + /* Found the range. */ + if (BbpR49 <= pTssiMinusBoundary[idx]) + break; + } + + /* The index is the step we should decrease, idx = 0 means there is nothing to compensate. */ +/* if (R3 > (ULONG) (TxAgcStep * (idx-1))) */ + *pTxAgcCompensate = -(TxAgcStep * (idx-1)); +/* else */ +/* *pTxAgcCompensate = -((UCHAR)R3); */ + + DeltaPwr += (*pTxAgcCompensate); + DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n", + BbpR49, TssiRef, TxAgcStep, idx-1)); + } + else if (BbpR49 < 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++) + { + /* Found the range. */ + if (BbpR49 >= pTssiPlusBoundary[idx]) + 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 R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, idx-1)); + } + else + { + *pTxAgcCompensate = 0; + DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, 0)); + } + } + } + else + { + if (pATEInfo->Channel <= 14) + { + bAutoTxAgc = pAd->bAutoTxAgcG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + bAutoTxAgc = pAd->bAutoTxAgcA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + DeltaPwr += (*pTxAgcCompensate); + } + + /* Reset different new tx power for different TX rate. */ + for (i=0; i> j*4) & 0x0F); /* 0 ~ 15 */ + +#ifdef RTMP_INTERNAL_TX_ALC + /* + The upper bounds of the MAC 0x1314~0x1324 + are variable when the STA uses the internal Tx ALC. + */ + if (pAd->TxPowerCtrl.bInternalTxALC == TRUE) + { + switch (TX_PWR_CFG_0 + (i * 4)) + { + case TX_PWR_CFG_0: + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE) + { + Value = 0xE; + } + else + { + Value += TotalDeltaPower; + } + } + break; + + case TX_PWR_CFG_1: + { + if ((j >= 0) && (j <= 3)) + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xC) + { + Value = 0xC; + } + else + { + Value += TotalDeltaPower; + } + } + else + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE) + { + Value = 0xE; + } + else + { + Value += TotalDeltaPower; + } + } + } + break; + + case TX_PWR_CFG_2: + { + if ((j == 0) || (j == 2) || (j == 3)) + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xC) + { + Value = 0xC; + } + else + { + Value += TotalDeltaPower; + } + } + else + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE) + { + Value = 0xE; + } + else + { + Value += TotalDeltaPower; + } + } + } + break; + + case TX_PWR_CFG_3: + { + if ((j == 0) || (j == 2) || (j == 3) || + ((j >= 4) && (j <= 7))) + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xC) + { + Value = 0xC; + } + else + { + Value += TotalDeltaPower; + } + } + else + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE) + { + Value = 0xE; + } + else + { + Value += TotalDeltaPower; + } + } + } + break; + + case TX_PWR_CFG_4: + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xC) + { + Value = 0xC; + } + else + { + Value += TotalDeltaPower; + } + } + break; + + default: + { + /* do nothing */ + DBGPRINT_ERR(("%s: unknown register = 0x%X\n", + __FUNCTION__, + (TX_PWR_CFG_0 + (i * 4)))); + } + break; + } + } + else +#endif /* RTMP_INTERNAL_TX_ALC */ + { + if ((Value + DeltaPwr) < 0) + { + Value = 0; /* min */ + } + else if ((Value + DeltaPwr) > 0xF) + { + Value = 0xF; /* max */ + } + else + { + Value += DeltaPwr; /* temperature compensation */ + } + } + + /* fill new value to CSR offset */ + TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4); + } + + /* write tx power value to CSR */ + /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M + TX power for OFDM 6M/9M + TX power for CCK5.5M/11M + TX power for CCK1M/2M */ + /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + (i << 2), TxPwr[i]); + } + } + +} + +struct _ATE_CHIP_STRUCT RALINK5350 = +{ + /* functions */ + .ChannelSwitch = RT5350ATEAsicSwitchChannel, + .TxPwrHandler = RT5350ATETxPwrHandler, + .TssiCalibration = NULL, + .ExtendedTssiCalibration = RT5350_ATETssiCalibrationExtend, + .RxVGAInit = RT5350ATERxVGAInit, + .AsicSetTxRxPath = NULL, + .AdjustTxPower = RT5350ATEAsicAdjustTxPower, + .AsicExtraPowerOverMAC = RT5350ATEAsicExtraPowerOverMAC, + + /* command handlers */ + .Set_BW_Proc = RT5350_Set_ATE_TX_BW_Proc, + .Set_FREQ_OFFSET_Proc = RT5350_Set_ATE_TX_FREQ_OFFSET_Proc, + + /* variables */ + .maxTxPwrCnt = 5, + .bBBPStoreTXCARR = TRUE, + .bBBPStoreTXCARRSUPP = TRUE, + .bBBPStoreTXCONT = TRUE, + .bBBPLoadATESTOP = TRUE, +}; + +#endif /* RT5350 */ + +/* End of rt5350.c */ + diff --git a/mt7620/src/ate/chips/rt6352_ate.c b/mt7620/src/ate/chips/rt6352_ate.c new file mode 100644 index 0000000..e7de746 --- /dev/null +++ b/mt7620/src/ate/chips/rt6352_ate.c @@ -0,0 +1,2331 @@ +/* + *************************************************************************** + * 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: + rt6352_ate.c + + Abstract: + Specific ATE 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 */ + +extern REG_PAIR RT6352_RFCentralRegTable[]; +extern REG_PAIR RT6352_RFChannelRegTable[]; +extern REG_PAIR RT6352_RFDCCalRegTable[]; +extern REG_PAIR_BW RT6352_RFDCCal_BW[]; +extern REG_PAIR RT6352_BBPRegTable[]; +extern REG_PAIR RT6352_BBP_GLRT[]; +extern REG_PAIR_BW RT6352_BBP_GLRT_BW[]; +extern RT635x_FREQUENCY_ITEM FreqItems6352[]; + +extern UCHAR RT6352_NUM_RF_CENTRAL_REG_PARMS; +extern UCHAR RT6352_NUM_RF_CHANNEL_REG_PARMS; +extern UCHAR RT6352_NUM_RF_DCCAL_REG_PARMS; +extern UCHAR RT6352_NUM_RF_DCCAL_BW; +extern UCHAR RT6352_NUM_BBP_REG_PARMS; +extern UCHAR RT6352_NUM_BBP_GLRT; +extern UCHAR RT6352_NUM_BBP_GLRT_BW; +extern UCHAR NUM_OF_6352_CHNL; + +#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 + +/* not used yet */ +VOID RT635xATEFilterCalibration( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR FilterTarget = 0x00; + UCHAR RFValue, BBPValue; + UCHAR CalRF57_PassBand = 0x00; + UCHAR CalRF57_StopBand = 0x00; + UINT loop = 0, count = 0, loopcnt = 0, ReTry = 0; + UCHAR tx_agc_fc = 0x00; + + /* Rx filter coef. offset */ + //pATEInfo->rx_agc_fc_offset20M = 0x08; + //pATEInfo->rx_agc_fc_offset40M = 0x04; + + //pATEInfo->CaliBW20RfR24 = 0x10; + //pATEInfo->CaliBW40RfR24 = 0x10; + + /* Enable abb_test */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R30, &RFValue); + RFValue &= ~0xC0; + RFValue |= 0x40; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R30, RFValue); + + do + { + if (loop == 1) + { + /* + * tx_h20M = 20MHz + */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R30, &RFValue); + RFValue |= 0x02; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R30, RFValue); + + tx_agc_fc = 0x00; + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R32, &RFValue); + RFValue &= ~0xF8; + RFValue |= (tx_agc_fc << 3); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R32, RFValue); + + FilterTarget = 0x12; + + /* When calibrate BW40, BBP mask must set to BW40 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= ~0x18; + BBPValue |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + + /* + * rx_h20M = 20MHz + */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R30, &RFValue); + RFValue |= 0x04; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R30, RFValue); + } + else + { + /* + * tx_h20M = 10MHz + */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R30, &RFValue); + RFValue &= ~0x02; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R30, RFValue); + + tx_agc_fc = 0x00; + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R32, &RFValue); + RFValue &= ~0xF8; + RFValue |= (tx_agc_fc << 3); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R32, RFValue); + + /* + The main change is to set 20M BW target value to 0x11. + That can provide more margin for 20M BW flatness. + */ + FilterTarget = 0x11; + + /* + * rx_h20M = 20MHz + */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R30, &RFValue); + RFValue &= ~0x04; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R30, RFValue); + } + + /* + * Enable BB loopback + */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R36, &RFValue); + RFValue |= 0x02; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R36, RFValue); + + /* + * transmit tone frequency control of passband test tone + */ + BBPValue = 0x02; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBPValue); + BBPValue = 0x00; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BBPValue); + + /* + * Enable RF calibration + */ + BBPValue = 0x00; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBPValue); + BBPValue = 0x82; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BBPValue); + + ReTry = 0; + + do + { + RtmpOsMsDelay(1); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &BBPValue); + DBGPRINT(RT_DEBUG_OFF, ("Wait RF calibration done BBP_R0 value = 0x%02x\n", BBPValue)); + } while((ReTry++ < 100 && (BBPValue & 0x80) == 0x80)); + + /* + * Read Rx0 signal strnegth for RF loop back RX gain + */ + BBPValue = 0x39; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBPValue); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &BBPValue); + CalRF57_PassBand = BBPValue & 0xFF; + + DBGPRINT(RT_DEBUG_OFF, ("Retry = %d, CalRF57_PassBand = 0x%02x\n", ReTry, CalRF57_PassBand)); + + /* + * transmit tone frequency control of stopband test tone + */ + BBPValue = 0x02; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBPValue); + BBPValue = 0x06; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BBPValue); + + while (TRUE) + { + + /* + * Enable RF calibration + */ + BBPValue = 0x00; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBPValue); + BBPValue = 0x82; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BBPValue); + + RtmpOsMsDelay(1); + + /* + * Read Rx0 signal strnegth for RF loop back RX gain + */ + BBPValue = 0x39; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBPValue); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &BBPValue); + BBPValue &= 0xFF; + CalRF57_StopBand = BBPValue; + + DBGPRINT(RT_DEBUG_OFF, ("loopcnt = %d, CalRF57_StopBand = 0x%x,\ + tx_agc_fc = 0x%0x, CalRF57_PassBand = 0x%0x,\ + FilterTarget = 0x%0x, (CalRF57_PassBand - CalRF57_StopBand) = 0x%0x\n", + loopcnt, CalRF57_StopBand, tx_agc_fc, CalRF57_PassBand, FilterTarget, + (CalRF57_PassBand - CalRF57_StopBand))); + + if ((CalRF57_PassBand - CalRF57_StopBand) < FilterTarget) + { + tx_agc_fc++; + } + else if ((CalRF57_PassBand - CalRF57_StopBand) == FilterTarget) + { + tx_agc_fc++; + count++; + } + else + { + loopcnt = 0; + break; + } + + if (loopcnt++ > 100) + { + DBGPRINT_ERR(("%s - can not find a valid value, loopcnt = %d\ + stop calibration\n", __FUNCTION__,loopcnt)); + break; + } + + if (loop == 0) + { + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R30, &RFValue); + RFValue &= ~0x02; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R30, RFValue); + + } + else + { + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R30, &RFValue); + RFValue |= 0x02; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R30, RFValue); + } + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R32, &RFValue); + RFValue &= ~0xF8; + RFValue |= (tx_agc_fc << 3); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R32, RFValue); + } + + if (count > 0) + tx_agc_fc = tx_agc_fc - ((count) ? 1 : 0); + + /* Store for future usage */ + if (loopcnt < 100) + { + if (loop++ == 0) + { + pATEInfo->CaliBW20RfR24 = tx_agc_fc; + } + else + { + pATEInfo->CaliBW40RfR24 = tx_agc_fc; + break; + } + + } + else + break; + + if (loop == 0) + { + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R30, &RFValue); + RFValue &= ~0x02; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R30, RFValue); + } + else + { + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R30, &RFValue); + RFValue |= 0x02; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R30, RFValue); + } + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R32, &RFValue); + RFValue &= ~0xF8; + RFValue |= (tx_agc_fc << 3); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R32, RFValue); + + count = 0; + } while (TRUE); + + /* + * Set back to initial state + */ + BBPValue = 0x02; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBPValue); + BBPValue = 0x00; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BBPValue); + + /* + * Disable BB loopback + */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R36, &RFValue); + RFValue &= ~0x02; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R36, RFValue); + + /* + * Set BBP back to BW20 + */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= ~0x18; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + + /* + * Disable abb_test + */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R30, &RFValue); + RFValue &= ~0xC0; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R30, RFValue); + + DBGPRINT(RT_DEBUG_OFF, ("%s CaliBW20RfR24 = 0x%x, CaliBW40RfR24 = 0x%x\n", + __FUNCTION__, pATEInfo->CaliBW20RfR24, pATEInfo->CaliBW40RfR24)); +} + + + +#ifdef RTMP_INTERNAL_TX_ALC +/* results of TSSI DC calibration */ +extern INT32 rt635x_tssi0_dc; +extern INT32 rt635x_tssi1_dc; +extern INT32 rt635x_tssi0_dc_hvga; +extern INT32 rt635x_tssi1_dc_hvga; +extern INT32 rt635x_tssi0_db_hvga; +extern INT32 rt635x_tssi1_db_hvga; + +/* TSSI tables */ +extern INT32 RT635x_McsPowerOverCCK[4]; +extern INT32 RT635x_McsPowerOverOFDM[8]; +extern INT32 RT635x_McsPowerOverHT[16]; +extern INT32 RT635x_McsPowerOverHTSTBC[8]; +extern UCHAR RT635x_RfPaModeOverCCK[4]; +extern UCHAR RT635x_RfPaModeOverOFDM[8]; +extern UCHAR RT635x_RfPaModeOverHT[16]; +/* extern UCHAR RT635x_RfPaModeOverHTSTBC[8]; */ + +/* read tssi_slope and tssi_offset from eeprom/efuse */ +static VOID RT635xATEGetTssiInfo( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + ATE_CHIP_STRUCT *pChip = (pATEInfo->pChipStruct); + USHORT offset, value; + CHAR temp; + + /* get tssi slope 0 */ + offset = 0x6E; + RT28xx_EEPROM_READ16(pAd, offset, value); + pChip->tssi_slope[0] = (INT32)(value & 0x00FF); + + /* get tssi_offset 0 */ + temp = (CHAR)((value & 0xFF00)>>8); + pChip->tssi_offset[GROUP1_2G][0] = (INT32)temp; + + offset = 0x70; + RT28xx_EEPROM_READ16(pAd, offset, value); + temp = (CHAR)(value & 0x00FF); + pChip->tssi_offset[GROUP2_2G][0] = (INT32)temp; + temp = (CHAR)((value & 0xFF00)>>8); + pChip->tssi_offset[GROUP3_2G][0] = (INT32)temp; + + /* get tssi slope 1 */ + offset = 0x72; + RT28xx_EEPROM_READ16(pAd, offset, value); + pChip->tssi_slope[1] = (INT32)(value & 0x00FF); + + /* get tssi_offset 1 */ + temp = (CHAR)((value & 0xFF00)>>8); + pChip->tssi_offset[GROUP1_2G][1] = (INT32)temp; + + offset = 0x74; + RT28xx_EEPROM_READ16(pAd, offset, value); + temp = (CHAR)(value & 0x00FF); + pChip->tssi_offset[GROUP2_2G][1] = (INT32)temp; + temp = (CHAR)((value & 0xFF00)>>8); + pChip->tssi_offset[GROUP3_2G][1] = (INT32)temp; + + /* get tx0/tx1 power offset */ + offset = 0x76; + RT28xx_EEPROM_READ16(pAd, offset, value); + temp = (CHAR)(value & 0x00FF); + pChip->ant_pwr_offset[0] = (INT32)(temp * 1024); /* 8192/8 */ + temp = (CHAR)((value & 0xFF00)>>8); + pChip->ant_pwr_offset[1] = (INT32)(temp * 1024); /* 8192/8 */ + + return; +} + + +static VOID RT635xATETssiCompensation( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + ATE_CHIP_STRUCT *pChip = (pATEInfo->pChipStruct); + 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]; + UCHAR RFValue, BBPValue, BBPR4, tssi_use_hvga[max_ant]; + UCHAR wait, ch_group, mcs, pa_mode, chain; + CHAR temp[max_ant]; + CHAR BBPR49; + INT32 cur_comp_power; + + /* TSSI compensation */ + /* 0. get base power from 0x13B0 */ + RT635xInitMcsPowerTable(pAd); + RT635xInitRfPaModeTable(pAd); + + 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; chainTxAntennaSel != ANT_ALL) + && ((chain + 1) != (UCHAR)pATEInfo->TxAntennaSel)) + { + continue; + } + + 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; + } + } + + /* 1. set TSSI mode */ + if (tssi_use_hvga[0] == 1) + { + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK5, RF_R03, &RFValue); + RFValue &= (~0x1F); + RFValue |= (0x11); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK5, RF_R03, RFValue); + } + else + { + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK5, RF_R03, &RFValue); + RFValue &= (~0x1F); + RFValue |= (0x08); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK5, RF_R03, RFValue); + } + + /* for 2T2R */ + if (tssi_use_hvga[1] == 1) + { + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK7, RF_R03, &RFValue); + RFValue &= (~0x1F); + RFValue |= (0x11); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK7, RF_R03, RFValue); + } + else + { + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK7, RF_R03, &RFValue); + RFValue &= (~0x1F); + RFValue |= (0x08); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK7, RF_R03, RFValue); + } + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= ~((1<<6)|(1<<5)); + BBPValue |= ((1<<6)|(0<<5)); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R58, 0x00); + + /* enable TSSI for next reading */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + + if (!(BBPValue & (1<<4))) + { + BBPValue |= (1<<4); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + } + +/* ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); */ + + /* 3. polling BBP_R47 */ + for (wait=0; wait<200; wait++) + { + RTMPusecDelay(100); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + + if (!(BBPValue & (1<<4))) + { + break; + } + } + + ASSERT(wait < 200); + if ((BBPValue & 0x10) != 0) + return; + + /* 4. read TSSI */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= (~0x07); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + /* get tssi0_linear */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + tssi_read[0] = (INT32)BBPR49; + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= (~0x07); + BBPValue |= 0x05; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + /* get tssi1_linear */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); + tssi_read[1] = (INT32)BBPR49; + + /* 5. read temperature */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= (~0x07); + BBPValue |= 0x04; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + /* save temperature */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49); +/* pChip->curr_temperature = (INT32)BBPR49; */ + pAd->CurrTemperature = (INT32)BBPR49; + DBGPRINT(RT_DEBUG_TRACE, ("%s: Current Temperature from BBP_R49=0x%x\n", __FUNCTION__, pAd->CurrTemperature)); + + /* 6. estimate the target power */ + /* get packet type */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= (~0x07); + BBPValue |= (0x01); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + /* read BBP_R178 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R178, &BBPValue); + /* read BBP_R4 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPR4); + ATE_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 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= (~0x07); + BBPValue |= (0x02); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + ATE_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; + } + + /* 7. estimate delta power */ + /* read tssi_slope and tssi_offset from efuse */ + RT635xATEGetTssiInfo(pAd); + + ch_group = GET_2G_CHANNEL_GROUP(pATEInfo->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; chainTxAntennaSel != ANT_ALL) + && ((chain + 1) != (UCHAR)pATEInfo->TxAntennaSel)) + { + continue; + } + + 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, ("tssi_linear %x\n", tssi_read[chain])); + tssi_m_dc = tssi_read[chain] - tssi_dc; + tssi_db = 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*(pChip->tssi_slope[chain])) + + (pChip->tssi_offset[ch_group][chain] << 9); + + DBGPRINT(RT_DEBUG_TRACE, ("tssi_slope %x\n", pChip->tssi_slope[chain])); + DBGPRINT(RT_DEBUG_TRACE, ("tssi offset %x\n", pChip->tssi_offset[ch_group][chain])); + + /* read BBP_R1 */ + ATE_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, ("pa mode %8d\n", pa_mode)); + DBGPRINT(RT_DEBUG_TRACE, ("base power %8d\n", base_power[0])); + DBGPRINT(RT_DEBUG_TRACE, ("mcs_power %8d\n", mcs_power)); + DBGPRINT(RT_DEBUG_TRACE, ("pa mode used %8d\n", pa_mode_used)); + DBGPRINT(RT_DEBUG_TRACE, ("bbp_6db_power %8d\n", bbp_6db_power)); + DBGPRINT(RT_DEBUG_TRACE, ("pChip->ant_pwr_offset[chain] %8d\n", pChip->ant_pwr_offset[chain])); + DBGPRINT(RT_DEBUG_TRACE, ("pkt_type delta %8d\n", pkt_type_delta)); + 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 + pChip->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 = pChip->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]; + } + + pChip->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 ((pChip->tssi_slope[chain] > 0xa0) && (pChip->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 if((chain + 1) == (UCHAR)pATEInfo->TxAntennaSel) + _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) || ((chain + 1) == (UCHAR)pATEInfo->TxAntennaSel)) + { + 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; + } + + /* 8. write compensation value back */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &MacValue); /* MAC 0x13B4 */ + MacValue = MacValue & (~0x3f); + + if((pATEInfo->TxAntennaSel == ANT_ALL) || ((chain + 1) == (UCHAR)pATEInfo->TxAntennaSel)) + MacValue = MacValue | (comp_power[0] & 0x3f); + else + MacValue = MacValue | (comp_power[pATEInfo->TxAntennaSel-1] & 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 & (~0x3f00); + if(pATEInfo->TxAntennaSel == ANT_ALL) + 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; +} +#endif /* RTMP_INTERNAL_TX_ALC */ + + +#ifdef RTMP_TEMPERATURE_COMPENSATION +/* specifically for MT7620A EP */ +static VOID RT635xATETemperatureCompensation( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + INT32 base_power[max_ant]; + UINT32 MacValue; + PCHAR pTxAgcCompensate, pTssiMinusBoundary, pTssiPlusBoundary; + CHAR TssiRef, TxAgcStep; + CHAR delta_pwr = 0, idx, BbpR49 = 0; + BOOLEAN bAutoTxAgc = FALSE; + UCHAR wait, chain, BBPValue, RFValue, RFB0R2Value; + + /* temperature compensation */ + /* 1. 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; chainTxAntennaSel != ANT_ALL) + && ((chain + 1) != (UCHAR)pATEInfo->TxAntennaSel)) + { + continue; + } + + DBGPRINT(RT_DEBUG_TRACE, ("\nchain %d: base_power is %d\n", chain, base_power[chain])); + } + + /* 2. set BBP R47[4]=1 to enable TSSI for next reading */ + /* enable RF before reading temperature sensor */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R02, &RFValue); + RFB0R2Value = RFValue; /* keep it for recovery later */ + RFValue |= 0x10; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R02, RFValue); + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + + if (!(BBPValue & (1<<4))) + { + BBPValue |= (1<<4); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + } + + /* 3. polling BBP_R47 until BBP R47[4]==0 */ + for (wait=0; wait<200; wait++) + { + RTMPusecDelay(2000); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + + if (!(BBPValue & (1<<4))) + { + break; + } + } + + if ((BBPValue & 0x10) != 0) + return; + + /* 4. set BBP R47[3:0]=4 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= ~(0x0F); + BBPValue |= (0x04); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + /* 5. fetch temperature reading */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); + pAd->CurrTemperature = (INT32)BbpR49; + DBGPRINT(RT_DEBUG_TRACE, ("%s: Current Temperature from BBP_R49=0x%x\n", __FUNCTION__, pAd->CurrTemperature)); + + /* recover RF after reading temperature sensor */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R02, RFB0R2Value); + + /* TX power compensation for temperature variation based on TSSI. try per 0.1 seconds */ + if (TRUE) + { + /* MT7620 is G band only */ + bAutoTxAgc = pAd->bAutoTxAgcG; + TssiRef = pAd->TssiRefG; /* e2p[75h]: the zero reference */ + ASSERT(TssiRef == pAd->TssiCalibratedOffset); + pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0]; + /* e2p[77h]: reserved */ +/* TxAgcStep = pAd->TxAgcStepG; */ + TxAgcStep = 2; /* the unit of MAC 0x13B4 is 0.5 dB */ + pTxAgcCompensate = &pAd->TxAgcCompensateG; + + /* ATE ALC is not controlled by e2p */ + if (TRUE /* bAutoTxAgc */) + { + if (BbpR49 < pTssiMinusBoundary[1]) + { + /* Reading is larger than the reference value */ + /* check for how large we need to decrease the Tx power */ + for (idx = 1; idx < 8; idx++) + { + if (BbpR49 >= pTssiMinusBoundary[idx]) /* the range has been found */ + break; + } + + /* The index is the step we should decrease, idx = 0 means there is nothing to compensate */ + *pTxAgcCompensate = -(TxAgcStep * (idx-1)); + delta_pwr = (*pTxAgcCompensate); + DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n", + BbpR49, TssiRef, TxAgcStep, idx-1)); + } + else if (BbpR49 > pTssiPlusBoundary[1]) + { + /* Reading is smaller than the reference value */ + /* check for how large we need to increase the Tx power */ + for (idx = 1; idx < 8; idx++) + { + if (BbpR49 <= pTssiPlusBoundary[idx]) /* the range has been found */ + break; + } + + /* The index is the step we should increase, idx = 0 means there is nothing to compensate */ + *pTxAgcCompensate = TxAgcStep * (idx-1); + delta_pwr = (*pTxAgcCompensate); + DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, idx-1)); + } + else + { + *pTxAgcCompensate = 0; + DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, 0)); + } + } + } + + /* adjust compensation value by MP temperature readings(i.e., e2p[77h]) */ + delta_pwr = delta_pwr - pAd->mp_delta_pwr; + /* delta_pwr (unit: 0.5dB) will be compensated by MAC 0x13B4 */ + DBGPRINT(RT_DEBUG_TRACE, ("** delta_pwr =%d **\n", delta_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("%s - delta_pwr = %d, TssiCalibratedOffset = %d, TssiMpOffset = %d\n", + __FUNCTION__, delta_pwr, pAd->TssiCalibratedOffset, pAd->mp_delta_pwr)); + + /* 8-bit representation ==> 6-bit representation (2's complement) */ + if ((delta_pwr & 0x80) == 0x00) /* positive number */ + delta_pwr &= 0x3F; + else /* 0x80: negative number */ + delta_pwr = (delta_pwr & 0x1F) | 0x20; + + /* 6. write compensation value into TX_ALG_CFG_1 */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &MacValue); /* MAC 0x13B4 */ + MacValue = MacValue & (~0x3f); + MacValue = MacValue | (delta_pwr & 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); + + return; +} +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + + +VOID RT635xATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 reg_index = 0; /* BbpReg, Value; */ + CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; /* Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER; */ + UCHAR index, RFValue, Channel = 0; + UCHAR BBPValue; + + reg_index = reg_index; /* avoid compile warning */ + RFValue = 0; + + SYNC_CHANNEL_WITH_QA(pATEInfo, &Channel); + + /* fill Tx power value */ + TxPwer = pATEInfo->TxPower0; + TxPwer2 = pATEInfo->TxPower1; + + DBGPRINT(RT_DEBUG_TRACE, + (" [%s] Channel = %d\n pATEInfo->TxWI.BW = %d\n pATEInfo->RFFreqOffset = %d\n " + "pATEInfo->TxPower0 = %d\n pATEInfo->TxPower1 = %d\n", + __FUNCTION__, Channel, pATEInfo->TxWI.BW, pATEInfo->RFFreqOffset, + pATEInfo->TxPower0, pATEInfo->TxPower1)); + + for (index = 0; index < NUM_OF_6352_CHNL; index++) + { + if (Channel == FreqItems6352[index].Channel) + { + UINT32 macStatus, saveMacSysCtrl; + USHORT k_count = 0; + + /* Frequeny plan setting */ + + /* Rdiv setting + * R13[1:0] + */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R13, &RFValue); + RFValue = RFValue & (~0x03); + RFValue |= (FreqItems6352[index].Rdiv & 0x3); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0,RF_R13, RFValue); + + /* + * N setting + * R21[0], R20[7:0] + */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R20, &RFValue); + RFValue = (FreqItems6352[index].N & 0x00ff); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R20, RFValue); + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R21, &RFValue); + RFValue = RFValue & (~0x01); + RFValue |= ((FreqItems6352[index].N & 0x0100) >> 8); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R21, RFValue); + + + /* + * K setting + * R16[3:0] (RF PLL freq selection) + */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R16, &RFValue); + RFValue = RFValue & (~0x0f); + RFValue |= (FreqItems6352[index].K & 0x0f); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R16, RFValue); + + /* + * D setting + * R22[2:0] (D=15, R22[2:0]=<111>) + */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R22, &RFValue); + RFValue = RFValue & (~0x07); + RFValue |= (FreqItems6352[index].D & 0x07); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R22, RFValue); + + /* + * Ksd setting + * R21[0], R20[7:0] + */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R17, &RFValue); + RFValue = (FreqItems6352[index].Ksd & 0x000000ff); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R17, RFValue); + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R18, &RFValue); + RFValue = ((FreqItems6352[index].Ksd & 0x0000ff00) >> 8); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R18, RFValue); + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R19, &RFValue); + RFValue = RFValue & (~0x03); + RFValue |= ((FreqItems6352[index].Ksd & 0x00030000) >> 16); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R19, RFValue); + + if (pAd->CommonCfg.Chip_VerID > 1) + { + /* Default: XO=20MHz , SDM mode */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R16, &RFValue); + RFValue = RFValue & (~0xE0); + RFValue |= 0x80; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R16, RFValue); + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R21, &RFValue); + RFValue |= 0x80; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R21, RFValue); + } + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R01, &RFValue); + if (pAd->Antenna.field.TxPath == 1) + RFValue &= (~0x2); + else + RFValue |= 0x2; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R01, RFValue); + + ATE_RF_IO_READ8_BY_REG_ID(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; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R02, RFValue); + + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R42, &RFValue); + if (pAd->Antenna.field.TxPath == 1) + RFValue &= (~0x40); + else + RFValue |= 0x40; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R42, RFValue); + + /* RF for DC Cal BW */ + for (reg_index = 0; reg_index < RT6352_NUM_RF_DCCAL_BW; reg_index++) + { + if(pATEInfo->TxWI.BW == RT6352_RFDCCal_BW[reg_index].BW) + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK5, RT6352_RFDCCal_BW[reg_index].Register, RT6352_RFDCCal_BW[reg_index].Value); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK7, RT6352_RFDCCal_BW[reg_index].Register, RT6352_RFDCCal_BW[reg_index].Value); + } + } + + if (pAd->CommonCfg.Chip_VerID > 1) + { + if (pATEInfo->TxWI.BW == BW_20) + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK5, RF_R58, 0x28); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK7, RF_R58, 0x28); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK5, RF_R59, 0x28); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK7, RF_R59, 0x28); + } + else + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK5, RF_R58, 0x08); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK7, RF_R58, 0x08); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK5, RF_R59, 0x08); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK7, RF_R59, 0x08); + } + } + + { + /* 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, ("Wait MAC Status to MAX !!!\n")); + } + + if ((pAd->CommonCfg.Chip_VerID > 1) && (pAd->CommonCfg.Chip_E_Number >= 2)) + { + UINT8 BBPValue; + + /* ADC clcok selection */ + DBGPRINT(RT_DEBUG_ERROR, ("ADC clock selection for E3 !!!\n")); + { + if (Channel > 10) + { + DBGPRINT(RT_DEBUG_ERROR, ("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_ERROR, ("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); + } + + /* BandWidth Filter Calibration */ + if (pATEInfo->TxWI.BW == 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); + } + + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R05, 0x40); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R04, 0x0C); + + ATE_RF_IO_READ8_BY_REG_ID(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. */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R04, RFValue); + RtmpOsMsDelay(2); + + 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)); + + /* latch channel for future usage */ + pAd->LatchRfRegs.Channel = Channel; + break; + } + } + +#ifdef RTMP_INTERNAL_TX_ALC + if (pATEInfo->bAutoTxAlc == TRUE) + { + OS_SEM_LOCK(&(pATEInfo->TssiSemLock)); + RT635xTssiDcCalibration(pAd); + OS_SEM_UNLOCK(&(pATEInfo->TssiSemLock)); + } +#endif /* RTMP_INTERNAL_TX_ALC */ + + /* DPD_Calibration & Rx DCOC Calibration*/ + pAd->Tx0_DPD_ALC_tag0 = 0; + pAd->Tx0_DPD_ALC_tag1 = 0; + pAd->Tx1_DPD_ALC_tag0 = 0; + pAd->Tx1_DPD_ALC_tag1 = 0; + /* Rx DCOC Calibration */ + RxDCOC_Calibration(pAd); + + /* BBP setting */ + if (pATEInfo->TxWI.BW == BW_20) + { + /* set BBP R4 = 0x40 for BW = 20 MHz */ + BBPValue = 0x40; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + } + else + { + /* set BBP R4 = 0x50 for BW = 40 MHz */ + BBPValue = 0x50; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + } + + /* BBP setting */ + if (Channel <= 14) + { + ULONG TxPinCfg = 0x00150F0A; /* Gary 2007/08/09 0x050A0A */ + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_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; + + if (IS_RT6352(pAd)) + TxPinCfg |= 0x100000; + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + + /* This job has been done by SetJapanFilter() */ +/* RtmpUpdateFilterCoefficientControl(pAd, Channel); */ + } + + /* BBP for GLRT BW */ + for (reg_index = 0; reg_index < RT6352_NUM_BBP_GLRT_BW; reg_index++) + { + if(pATEInfo->TxWI.BW == RT6352_BBP_GLRT_BW[reg_index].BW) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, RT6352_BBP_GLRT_BW[reg_index].Register); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, RT6352_BBP_GLRT_BW[reg_index].Value); + } + } + +#ifdef RT6352_EL_SUPPORT + if ((pAd->CommonCfg.PKG_ID == 1) && (pAd->NicConfig2.field.ExternalLNAForG)) + { + if(pATEInfo->TxWI.BW == BW_20) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BBP_R141); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x15); + } + } +#endif /* RT6352_EL_SUPPORT */ + + + ATEAsicSetTxRxPath(pAd); + + /* R66 should be set according to channel and bandwidth. */ + /* AGC VGA init value */ + ATE_CHIP_RX_VGA_GAIN_INIT(pAd); + + RtmpOsMsDelay(1); + +} + + +INT RT635xATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 MacValue = 0; + USHORT value = 0; + CHAR TxPower = 0; + CHAR bw_power_delta = 0; + +#ifdef RALINK_QA + if (pATEInfo->bQAEnabled == TRUE) + { + return 0; + } +#endif /* RALINK_QA */ + + if (pATEInfo->TxWI.BW == BW_40) + { + /* get 40 MHz power delta from e2p 50h */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_DELTA, value); + /* sanity check */ + if ((value & 0xFF) != 0xFF) + { + if ((value & 0x80)) + bw_power_delta = (value & 0x3F); + + if ((value & 0x40) == 0) + bw_power_delta = (-1) * bw_power_delta; + } + } + + /* + bit<5:0> range from 0x0~0x27 + */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &MacValue); + + if (index == 0) + { + TxPower = pATEInfo->TxPower0; + + if ((pATEInfo->TxWI.BW == BW_40) && (pATEInfo->bAutoTxAlc == TRUE)) + { + TxPower += (bw_power_delta); + } + + MacValue &= (~0x0000003F); + MacValue |= TxPower; + } + else if (index == 1) + { + TxPower = pATEInfo->TxPower1; + + if ((pATEInfo->TxWI.BW == BW_40) && (pATEInfo->bAutoTxAlc == TRUE)) + { + TxPower += (bw_power_delta); + } + + MacValue &= (~0x00003F00); + MacValue |= (TxPower << 8); + } + else + { + DBGPRINT_ERR(("%s : Only TxPower0 and TxPower1 are adjustable !\n", __FUNCTION__)); + DBGPRINT_ERR(("%s : TxPower%d is out of range !\n", __FUNCTION__, index)); + return -1; + } + + MacValue |= (0x2F << 16); + MacValue |= (0x2F << 24); + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_0, MacValue); + + DBGPRINT(RT_DEBUG_TRACE, ("%s : (TxPower%d=%d)\n", __FUNCTION__, index, TxPower)); + + /* when TSSI is disabled, 20MHz/40MHz power delta is performed on MAC 0x13B4 */ + if (pATEInfo->bAutoTxAlc == FALSE) + { + /* clean up MAC 0x13B4 bit[5:0] */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &MacValue); + MacValue &= 0xFFFFFFC0; + + if (pATEInfo->TxWI.BW == BW_40) + { + CHAR diff; + + diff = bw_power_delta; + + /* MAC 0x13B4 is 6-bit signed value */ + if (bw_power_delta < 0) + { + MacValue |= 0x20; + } + + if (diff > 20) + diff = 20; + + MacValue |= (diff & 0x1F); + } + + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_1, MacValue); + DBGPRINT(RT_DEBUG_TRACE, ("bw_power_delta=%d, MAC 0x13B4 is 0x%08x\n", bw_power_delta, MacValue)); + } + + return 0; +} + + +/* for RT6352 */ +VOID RT635xATERxVGAInit( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR R66 = 0; + CHAR LNAGain = GET_LNA_GAIN(pAd); + + if (pATEInfo->Channel <= 14) + { + R66 = 0x04 + (2 * LNAGain); + } + else + { + R66 = 0x04 + (2 * LNAGain); + } + + ATEBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + + // TODO: + /* RX AGC LNA MM Select threshold */ +/* ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R83, 0x7A); */ + + + return; +} + + +VOID RT635xATEAsicExtraPowerOverMAC( + 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_TRACE, ("Offset =0x13D8, TxPwr = 0x%08X, ", (UINT)ExtraPwrOverTxPwrCfg8)); + + DBGPRINT(RT_DEBUG_TRACE, ("Offset = 0x13D4, TxPwr = 0x%08X, Offset = 0x13DC, TxPwr = 0x%08X\n", + (UINT)ExtraPwrOverTxPwrCfg7, + (UINT)ExtraPwrOverTxPwrCfg9)); +} + + +VOID RT635xATEAsicGetTxPowerOffset( + IN PRTMP_ADAPTER pAd, + IN PULONG TxPwr) +{ + PATE_INFO pATEInfo = &(pAd->ate); + CONFIGURATION_OF_TX_POWER_CONTROL_OVER_MAC CfgOfTxPwrCtrlOverMAC; + + DBGPRINT(RT_DEBUG_INFO, ("-->%s\n", __FUNCTION__)); + + NdisZeroMemory(&CfgOfTxPwrCtrlOverMAC, sizeof(CfgOfTxPwrCtrlOverMAC)); + + CfgOfTxPwrCtrlOverMAC.NumOfEntries = 5; /* MAC 0x1314, 0x1318, 0x131C, 0x1320 and 1324 */ + + if (pATEInfo->TxWI.BW == BW_40) + { + 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 + { + 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_TRACE, ("<--%s\n", __FUNCTION__)); +} + + +VOID RT635xATEAsicCompensatePowerViaBBP( + IN PRTMP_ADAPTER pAd, + INOUT PCHAR pTotalDeltaPower) +{ + UCHAR BbpR1 = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: TotalDeltaPower = %d dBm\n", __FUNCTION__, *pTotalDeltaPower)); + + /* The BBP R1 controls the transmit power for all rates */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1); + BbpR1 &= ~MDSM_BBP_R1_STATIC_TX_POWER_CONTROL_MASK; + + if (*pTotalDeltaPower <= -12) + { + *pTotalDeltaPower += 12; + BbpR1 |= MDSM_DROP_TX_POWER_BY_12dBm; + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Drop the transmit power by 12 dBm (BBP R1)\n", __FUNCTION__)); + } + else if ((*pTotalDeltaPower <= -6) && (*pTotalDeltaPower > -12)) + { + *pTotalDeltaPower += 6; + BbpR1 |= MDSM_DROP_TX_POWER_BY_6dBm; + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Drop the transmit power by 6 dBm (BBP R1)\n", __FUNCTION__)); + } + else + { + /* Control the the transmit power by using the MAC only */ + ATE_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)); +} + + +/* +========================================================================== + Description: + Set RT5572/RT5592 ATE RF BW + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT RT635x_Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR value = 0; + UCHAR BBPCurrentBW; + + BBPCurrentBW = simple_strtol(arg, 0, 10); + + if (BBPCurrentBW == 0) + { + pATEInfo->TxWI.BW = BW_20; + } + else + { + pATEInfo->TxWI.BW = BW_40; + } + + /* Turn on BBP 20MHz mode by request here. */ + if (pATEInfo->TxWI.BW == BW_20) + { + if (pATEInfo->Channel == 14) + { + INT TxMode = pATEInfo->TxWI.PHYMODE; + + if (TxMode == MODE_CCK) + { + /* when Channel==14 && Mode==CCK && BandWidth==20M, BBP R4 bit5=1 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value |= 0x20; /* set bit5=1 */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + } + } + } + + return TRUE; +} + + +VOID RT635xATEAsicSetTxRxPath( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR RFValue1 = 0, RFValue2 = 0, BbpValue = 0; + UINT32 TxPinCfg = 0; + UINT32 Value = 0; + + if ((pATEInfo->Mode == ATE_TXCONT) || (pATEInfo->Mode == ATE_TXCARR) + || (pATEInfo->Mode == ATE_TXCARRSUPP)) + { + /* store the original value of TX_PIN_CFG */ + RTMP_IO_READ32(pAd, TX_PIN_CFG, &(pATEInfo->Default_TX_PIN_CFG)); + + /* + Bank0.R01: + [1] for enable channel 1 + [0] for enable channel 0 + */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R01, &RFValue1); + RFValue1 &= (~((1 << 1) | (1 << 0))); /* clear bit 1:0 */ + + /* + Bank0.R02: + [5]: enable Tx1 + [4]: enable Tx0 + [1]: enable Rx1 + [0]: enable Rx0 + */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R02, &RFValue2); + RFValue2 &= (~((1 << 5) | (1 << 4) | (1 << 1) | (1 << 0))); /* clear bit 5:4:1:0 */ + + BbpValue = 0x30; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R142, BbpValue); + /* [4] is set as 0 to disable MAC Tx path selection */ + BbpValue = 0xF7; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R143, BbpValue); + + /* G band */ + switch (pATEInfo->TxAntennaSel) + { + case ANT_ALL: /* both TX0/TX1 */ + TxPinCfg = 0x000C00A0; + break; + case ANT_0: /* TX0 */ + TxPinCfg = 0x000C0020; + break; + case ANT_1: /* TX1 */ + TxPinCfg = 0x000C0080; + break; + } + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + + /* Set TX path, pAd->TxAntennaSel : 0 -> All, 1 -> TX0, 2 -> TX1 */ + switch(pAd->Antenna.field.TxPath) + { + case 1: /* 1T */ + switch (pATEInfo->TxAntennaSel) + { + case ANT_0: + /* set BBP R1, bit 4:3 = 00 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; /* 11100111B */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + + /* set RF Bank0 R1, bit 1:0 = 01 */ + RFValue1 = RFValue1 | 0x03; + + /* set RF Bank0 R2, bit 5:4 = 01 */ + RFValue2 = RFValue2 | 0x10; + break; + case ANT_1: + /* set BBP R1, bit 4:3 = 01 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + + /* set RF Bank0 R1, bit 1:0 = 10 */ + RFValue1 = RFValue1 | 0x03; + + /* set RF Bank0 R2, bit 5:4 = 10 */ + RFValue2 = RFValue2 | 0x20; + break; + default: /* ANT_ALL */ + /* set BBP R1, bit 4:3 = 10 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + + /* set RF Bank0 R1, bit 1:0 = 11 */ + RFValue1 = RFValue1 | 0x03; + + /* set RF Bank0 R2, bit 5:4 = 11 */ + RFValue2 = RFValue2 | 0x30; + break; + } + break; + + case 2: /* 2T */ + switch (pATEInfo->TxAntennaSel) + { + case ANT_0: + /* set BBP R1, bit 4:3 = 00 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; /* 11100111B */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + + /* set RF Bank0 R1, bit 1:0 = 01 */ + RFValue1 = RFValue1 | 0x03; + + /* set RF Bank0 R2, bit 5:4 = 01 */ + RFValue2 = RFValue2 | 0x10; + break; + case ANT_1: + /* set BBP R1, bit 4:3 = 01 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + + /* set RF Bank0 R1, bit 1:0 = 10 */ + RFValue1 = RFValue1 | 0x03; + + /* set RF Bank0 R2, bit 5:4 = 10 */ + RFValue2 = RFValue2 | 0x20; + break; + default: /* ANT_ALL */ + /* set BBP R1, bit 4:3 = 10 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + + /* set RF Bank0 R1, bit 1:0 = 11 */ + RFValue1 = RFValue1 | 0x03; + + /* set RF Bank0 R2, bit 5:4 = 11 */ + RFValue2 = RFValue2 | 0x30; + break; + } + break; + + default: + break; + } + + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R01, RFValue1); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R02, RFValue2); + } + else if (pATEInfo->Mode == ATE_TXFRAME) + { + /* store the original value of TX_PIN_CFG */ + RTMP_IO_READ32(pAd, TX_PIN_CFG, &(pATEInfo->Default_TX_PIN_CFG)); + + /* + Bank0.R01: + [1] for enable channel 1 + [0] for enable channel 0 + */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R01, &RFValue1); + RFValue1 &= (~((1 << 1) | (1 << 0))); /* clear bit 1:0 */ + + /* + Bank0.R02: + [5]: enable Tx1 + [4]: enable Tx0 + [1]: enable Rx1 + [0]: enable Rx0 + */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R02, &RFValue2); + RFValue2 &= (~((1 << 5) | (1 << 4) | (1 << 1) | (1 << 0))); /* clear bit 5:4:1:0 */ + + BbpValue = 0x30; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R142, BbpValue); + /* [4] is set as 0 to disable MAC Tx path selection */ + BbpValue = 0xF7; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R143, BbpValue); + + Value = (pATEInfo->Default_TX_PIN_CFG & (~0x0000000F)); + + /* G band */ + switch (pATEInfo->TxAntennaSel) + { + case ANT_ALL: /* both TX0/TX1 */ + TxPinCfg = Value | 0x0F; + break; + case ANT_0: /* TX0 */ + TxPinCfg = Value | 0x03; + break; + case ANT_1: /* TX1 */ + TxPinCfg = Value | 0x0C; + break; + } + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + + /* Set TX path, pAd->TxAntennaSel : 0 -> All, 1 -> TX0, 2 -> TX1 */ + switch(pAd->Antenna.field.TxPath) + { + case 1: /* 1T */ + switch (pATEInfo->TxAntennaSel) + { + case ANT_0: + /* set BBP R1, bit 4:3 = 00 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; /* 11100111B */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + + /* set RF Bank0 R1, bit 1:0 = 01 */ + RFValue1 = RFValue1 | 0x03; + + /* set RF Bank0 R2, bit 5:4 = 01 */ + RFValue2 = RFValue2 | 0x10; + break; + case ANT_1: + /* set BBP R1, bit 4:3 = 01 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + + /* set RF Bank0 R1, bit 1:0 = 10 */ + RFValue1 = RFValue1 | 0x03; + + /* set RF Bank0 R2, bit 5:4 = 10 */ + RFValue2 = RFValue2 | 0x20; + break; + default: /* ANT_ALL */ + /* set BBP R1, bit 4:3 = 10 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + + /* set RF Bank0 R1, bit 1:0 = 11 */ + RFValue1 = RFValue1 | 0x03; + + /* set RF Bank0 R2, bit 5:4 = 11 */ + RFValue2 = RFValue2 | 0x30; + break; + } + break; + + case 2: /* 2T */ + switch (pATEInfo->TxAntennaSel) + { + case ANT_0: + /* set BBP R1, bit 4:3 = 00 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; /* 11100111B */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + + /* set RF Bank0 R1, bit 1:0 = 01 */ + RFValue1 = RFValue1 | 0x03; + + /* set RF Bank0 R2, bit 5:4 = 01 */ + RFValue2 = RFValue2 | 0x10; + break; + case ANT_1: + /* set BBP R1, bit 4:3 = 01 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + + /* set RF Bank0 R1, bit 1:0 = 10 */ + RFValue1 = RFValue1 | 0x03; + + /* set RF Bank0 R2, bit 5:4 = 10 */ + RFValue2 = RFValue2 | 0x20; + break; + default: /* ANT_ALL */ + /* set BBP R1, bit 4:3 = 10 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + + /* set RF Bank0 R1, bit 1:0 = 11 */ + RFValue1 = RFValue1 | 0x03; + + /* set RF Bank0 R2, bit 5:4 = 11 */ + RFValue2 = RFValue2 | 0x30; + break; + } + break; + + default: + break; + } + + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R01, RFValue1); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R02, RFValue2); + } + else if (pATEInfo->Mode == ATE_RXFRAME) + { + /* store the original value of TX_PIN_CFG */ + RTMP_IO_READ32(pAd, TX_PIN_CFG, &(pATEInfo->Default_TX_PIN_CFG)); + + /* + Bank0.R01: + [1] for enable channel 1 + [0] for enable channel 0 + */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R01, &RFValue1); + RFValue1 &= (~((1 << 1) | (1 << 0))); /* clear bit 1:0 */ + + /* + Bank0.R02: + [5]: enable Tx1 + [4]: enable Tx0 + [1]: enable Rx1 + [0]: enable Rx0 + */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R02, &RFValue2); + RFValue2 &= (~((1 << 5) | (1 << 4) | (1 << 1) | (1 << 0))); /* clear bit 5:4:1:0 */ + + Value = (pATEInfo->Default_TX_PIN_CFG & (~0x0000000F)); + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, Value); + + /* Set RX path, pAd->RxAntennaSel : 0 -> All, 1 -> RX0, 2 -> RX1, 3 -> RX2 */ + switch (pAd->Antenna.field.RxPath) + { + case 1: /* 1R */ + switch (pATEInfo->RxAntennaSel) + { + case ANT_0: + /* set BBP R3, bit 4:3:1:0 = 0000 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x00; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + + BbpValue = 0x1A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R95, BbpValue); + + BbpValue = BBP_R170; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BbpValue); + BbpValue = 0x12; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, BbpValue); + + BbpValue = BBP_R171; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BbpValue); + BbpValue = 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, BbpValue); + + BbpValue = BBP_R128; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BbpValue); + BbpValue = 0xA0; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, BbpValue); + + Value = 0x00000200; /* force RF RX STBY1 = 1'b1 */ + RTMP_IO_WRITE32(pAd, RF_BYPASS0, Value); + Value = 0x00000200; + RTMP_IO_WRITE32(pAd, RF_CONTROL0, Value); + + /* set RF Bank0 R1, bit 1:0 = 01 */ + RFValue1 = RFValue1 | 0x03; + + /* set RF Bank0 R2, bit 1:0 = 01 */ + RFValue2 = RFValue2 | 0x01; + break; + case ANT_1: + /* set BBP R3, bit 4:3:1:0 = 0001 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x01; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + + BbpValue = 0x1A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R95, BbpValue); + + BbpValue = BBP_R170; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BbpValue); + BbpValue = 0x12; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, BbpValue); + + BbpValue = BBP_R171; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BbpValue); + BbpValue = 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, BbpValue); + + BbpValue = BBP_R128; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BbpValue); + BbpValue = 0xA0; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, BbpValue); + + Value = 0x00000100; /* force RF RX STBY0 = 1'b1 */ + RTMP_IO_WRITE32(pAd, RF_BYPASS0, Value); + Value = 0x00000100; + RTMP_IO_WRITE32(pAd, RF_CONTROL0, Value); + + /* set RF Bank0 R1, bit 1:0 = 10 */ + RFValue1 = RFValue1 | 0x03; + + /* set RF Bank0 R2, bit 1:0 = 10 */ + RFValue2 = RFValue2 | 0x02; + break; + default: /* ANT_ALL */ + /* set BBP R3, bit 4:3:1:0 = 0100 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + + BbpValue = 0x9A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R95, BbpValue); + + BbpValue = BBP_R170; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BbpValue); + BbpValue = 0x30; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, BbpValue); + + BbpValue = BBP_R171; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BbpValue); + BbpValue = 0x30; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, BbpValue); + + BbpValue = BBP_R128; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BbpValue); + BbpValue = 0xE0; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, BbpValue); + + Value = 0x00000000; + RTMP_IO_WRITE32(pAd, RF_BYPASS0, Value); + Value = 0x00000000; + RTMP_IO_WRITE32(pAd, RF_CONTROL0, Value); + + /* set RF Bank0 R1, bit 1:0 = 11 */ + RFValue1 = RFValue1 | 0x03; + + /* set RF Bank0 R2, bit 1:0 = 11 */ + RFValue2 = RFValue2 | 0x03; + break; + } + break; + + case 2: /* 2R */ + switch (pATEInfo->RxAntennaSel) + { + case ANT_0: + /* set BBP R3, bit 4:3:1:0 = 0000 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x00; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + + BbpValue = 0x1A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R95, BbpValue); + + BbpValue = BBP_R170; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BbpValue); + BbpValue = 0x12; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, BbpValue); + + BbpValue = BBP_R171; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BbpValue); + BbpValue = 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, BbpValue); + + BbpValue = BBP_R128; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BbpValue); + BbpValue = 0xA0; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, BbpValue); + + Value = 0x00000200; /* force RF RX STBY1 = 1'b1 */ + RTMP_IO_WRITE32(pAd, RF_BYPASS0, Value); + Value = 0x00000200; + RTMP_IO_WRITE32(pAd, RF_CONTROL0, Value); + + /* set RF Bank0 R1, bit 1:0 = 01 */ + RFValue1 = RFValue1 | 0x03; + + /* set RF Bank0 R2, bit 1:0 = 01 */ + RFValue2 = RFValue2 | 0x01; + break; + case ANT_1: + /* set BBP R3, bit 4:3:1:0 = 0001 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x01; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + + BbpValue = 0x1A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R95, BbpValue); + + BbpValue = BBP_R170; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BbpValue); + BbpValue = 0x12; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, BbpValue); + + BbpValue = BBP_R171; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BbpValue); + BbpValue = 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, BbpValue); + + BbpValue = BBP_R128; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BbpValue); + BbpValue = 0xA0; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, BbpValue); + + Value = 0x00000100; /* force RF RX STBY0 = 1'b1 */ + RTMP_IO_WRITE32(pAd, RF_BYPASS0, Value); + Value = 0x00000100; + RTMP_IO_WRITE32(pAd, RF_CONTROL0, Value); + + /* set RF Bank0 R1, bit 1:0 = 10 */ + RFValue1 = RFValue1 | 0x03; + + /* set RF Bank0 R2, bit 1:0 = 10 */ + RFValue2 = RFValue2 | 0x02; + break; + default: /* ANT_ALL */ + /* set BBP R3, bit 4:3:1:0 = 0100 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + + BbpValue = 0x9A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R95, BbpValue); + + BbpValue = BBP_R170; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BbpValue); + BbpValue = 0x30; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, BbpValue); + + BbpValue = BBP_R171; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BbpValue); + BbpValue = 0x30; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, BbpValue); + + BbpValue = BBP_R128; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, BbpValue); + BbpValue = 0xE0; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, BbpValue); + + Value = 0x00000000; + RTMP_IO_WRITE32(pAd, RF_BYPASS0, Value); + Value = 0x00000000; + RTMP_IO_WRITE32(pAd, RF_CONTROL0, Value); + + /* set RF Bank0 R1, bit 1:0 = 11 */ + RFValue1 = RFValue1 | 0x03; + + /* set RF Bank0 R2, bit 1:0 = 11 */ + RFValue2 = RFValue2 | 0x03; + break; + } + break; + + default: + break; + } + + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R01, RFValue1); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R02, RFValue2); + } +} + + +/* +========================================================================== + Description: + Set RT5572/RT5592 ATE RF central frequency offset + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT RT635x_Set_ATE_TX_FREQ_OFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR RFFreqOffset = 0; + UCHAR RFValue = 0; + UCHAR PreRFValue = 0; + + RFFreqOffset = simple_strtol(arg, 0, 10); + pATEInfo->RFFreqOffset = RFFreqOffset; + + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R12, &RFValue); + PreRFValue = RFValue; + + /* xo_code (C1 value control) - Crystal calibration */ + RFValue = ((RFValue & ~0xFF) | (pATEInfo->RFFreqOffset & 0xFF)); + RFValue = min((INT)RFValue, 0xFF); + + if (PreRFValue != RFValue) + { + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R12, RFValue); + } + + + return TRUE; +} + +#ifdef RTMP_MAC_PCI +struct _ATE_CHIP_STRUCT RALINK6352 = +{ + /* functions */ + .ChannelSwitch = RT635xATEAsicSwitchChannel, + .TxPwrHandler = RT635xATETxPwrHandler, + .TssiCalibration = NULL, + .ExtendedTssiCalibration = NULL, + .RxVGAInit = RT635xATERxVGAInit, + .AsicSetTxRxPath = RT635xATEAsicSetTxRxPath, +#ifdef RTMP_INTERNAL_TX_ALC + .AdjustTxPower = RT635xATETssiCompensation, +#endif /* RTMP_INTERNAL_TX_ALC */ +#ifdef RTMP_TEMPERATURE_COMPENSATION + .AdjustTxPower = RT635xATETemperatureCompensation, +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + .AsicExtraPowerOverMAC = RT635xATEAsicExtraPowerOverMAC, + + /* command handlers */ + .Set_BW_Proc = RT635x_Set_ATE_TX_BW_Proc, + .Set_FREQ_OFFSET_Proc = RT635x_Set_ATE_TX_FREQ_OFFSET_Proc, + + /* variables */ + .maxTxPwrCnt = 5, + .bBBPStoreTXCARR = FALSE, + .bBBPStoreTXCARRSUPP = FALSE, + .bBBPStoreTXCONT = FALSE, + .bBBPLoadATESTOP = FALSE, +}; +#endif /* RTMP_MAC_PCI */ +#endif /* RT6352 */ + +/* End of rt6352_ate.c */ diff --git a/mt7620/src/ate/common/ate_pci.c b/mt7620/src/ate/common/ate_pci.c new file mode 100644 index 0000000..303507c --- /dev/null +++ b/mt7620/src/ate/common/ate_pci.c @@ -0,0 +1,427 @@ +/* + *************************************************************************** + * 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: + ate_pci.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ + +#ifdef RTMP_MAC_PCI + +#include "rt_config.h" + +/* 802.11 MAC Header, Type:Data, Length:24bytes + 6 bytes QOS/HTC + 2 bytes padding */ +extern UCHAR TemplateFrame[32]; + +INT TxDmaBusy( + IN PRTMP_ADAPTER pAd) +{ + INT result; + WPDMA_GLO_CFG_STRUC GloCfg; + + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); /* disable DMA */ + result = (GloCfg.field.TxDMABusy) ? TRUE : FALSE; + + return result; +} + + +INT RxDmaBusy( + IN PRTMP_ADAPTER pAd) +{ + INT result; + WPDMA_GLO_CFG_STRUC GloCfg; + + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); /* disable DMA */ + result = (GloCfg.field.RxDMABusy) ? TRUE : FALSE; + + return result; +} + + +VOID RtmpDmaEnable( + IN PRTMP_ADAPTER pAd, + IN INT Enable) +{ + BOOLEAN value; + ULONG WaitCnt; + WPDMA_GLO_CFG_STRUC GloCfg; + + value = Enable > 0 ? 1 : 0; + + /* check if DMA is in busy mode or not. */ + WaitCnt = 0; + + while (TxDmaBusy(pAd) || RxDmaBusy(pAd)) + { + RTMPusecDelay(10); + + if (WaitCnt++ > 100) + break; + } + + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); /* disable DMA */ + GloCfg.field.EnableTxDMA = value; + GloCfg.field.EnableRxDMA = value; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); /* abort all TX rings */ + RtmpOsMsDelay(5); + + return; +} + + +/* +======================================================================== + Routine Description: + Write TxWI for ATE mode. + + Return Value: + None +======================================================================== +*/ +VOID ATEWriteTxWI( + IN PRTMP_ADAPTER pAd, + IN PTXWI_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 BOOLEAN CfAck, + IN HTTRANSMIT_SETTING *pTransmit) +{ + TXWI_STRUC TxWI; + PTXWI_STRUC pTxWI; + UINT8 TXWISize = pAd->chipCap.TXWISize; + + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + NdisZeroMemory(&TxWI, TXWISize); + pTxWI = &TxWI; + + pTxWI->FRAG= FRAG; + + pTxWI->CFACK = CFACK; + pTxWI->TS= InsTimestamp; + pTxWI->AMPDU = AMPDU; + pTxWI->ACK = Ack; + pTxWI->txop= Txopmode; + + pTxWI->NSEQ = NSeq; + + if ( BASize >7 ) + BASize =7; + + pTxWI->BAWinSize = BASize; + pTxWI->WirelessCliID = WCID; + pTxWI->MPDUtotalByteCount = Length; + pTxWI->PacketId = PID; + + /* If CCK or OFDM, BW must be 20 */ + pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); + pTxWI->ShortGI = pTransmit->field.ShortGI; + pTxWI->STBC = pTransmit->field.STBC; + + pTxWI->MCS = pTransmit->field.MCS; + pTxWI->PHYMODE = pTransmit->field.MODE; + pTxWI->CFACK = CfAck; + pTxWI->MIMOps = 0; + pTxWI->MpduDensity = 0; + + pTxWI->PacketId = pTxWI->MCS; + NdisMoveMemory(pOutTxWI, &TxWI, TXWISize); + + return; +} + + +/* +========================================================================== + Description: + Setup Frame format. + NOTE: + This routine should only be used in ATE mode. +========================================================================== +*/ +INT ATESetUpFrame( + IN PRTMP_ADAPTER pAd, + IN UINT32 TxIdx) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT pos = 0; + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; +#endif + PNDIS_PACKET pPacket=NULL; + PUCHAR pDest=NULL; + PVOID AllocVa=NULL; + NDIS_PHYSICAL_ADDRESS AllocPa; + HTTRANSMIT_SETTING TxHTPhyMode; + + PRTMP_TX_RING pTxRing = &pAd->TxRing[QID_AC_BE]; + PTXWI_STRUC pTxWI = (PTXWI_STRUC) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + PUCHAR pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + UINT8 TXWISize = pAd->chipCap.TXWISize; + +#ifdef RALINK_QA + PHEADER_802_11 pHeader80211; +#endif /* RALINK_QA */ + + /* fill TxWI */ + TxHTPhyMode.field.BW = pATEInfo->TxWI.BW; + TxHTPhyMode.field.ShortGI = pATEInfo->TxWI.ShortGI; + TxHTPhyMode.field.STBC = pATEInfo->TxWI.STBC; + TxHTPhyMode.field.MCS = pATEInfo->TxWI.MCS; + TxHTPhyMode.field.MODE = pATEInfo->TxWI.PHYMODE; + + if (pATEInfo->bQATxStart == TRUE) + { + /* always use QID_AC_BE and FIFO_EDCA */ + ATEWriteTxWI(pAd, pTxWI, pATEInfo->TxWI.FRAG, pATEInfo->TxWI.CFACK, + pATEInfo->TxWI.TS, pATEInfo->TxWI.AMPDU, pATEInfo->TxWI.ACK, + pATEInfo->TxWI.NSEQ, pATEInfo->TxWI.BAWinSize, 0, + pATEInfo->TxWI.MPDUtotalByteCount, pATEInfo->TxWI.PacketId, 0, 0, + pATEInfo->TxWI.txop/*IFS_HTTXOP*/, pATEInfo->TxWI.CFACK/*FALSE*/, + &TxHTPhyMode); + +#ifdef TXBF_SUPPORT + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + { + /* Must copy rsv bits to actual TxWI */ + pTxWI->rsv = pATEInfo->TxWI.rsv; + pTxWI->iTxBF = pATEInfo->TxWI.iTxBF; + pTxWI->Sounding = pATEInfo->TxWI.Sounding; + pTxWI->eTxBF = pATEInfo->TxWI.eTxBF; + pTxWI->Autofallback = pATEInfo->TxWI.Autofallback; + pTxWI->NDPSndBW = pATEInfo->TxWI.NDPSndBW; + pTxWI->NDPSndRate = pATEInfo->TxWI.NDPSndRate; + } +#endif /* TXBF_SUPPORT */ + } + else + { + ATEWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + 4, 0, pATEInfo->TxLength, 0, 0, 0, IFS_HTTXOP, FALSE, &TxHTPhyMode); + +#ifdef TXBF_SUPPORT + if (pATEInfo->bTxBF == 1) + { + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + { + pTxWI->rsv = 0; + pTxWI->iTxBF = pATEInfo->TxWI.iTxBF; + pTxWI->Sounding = (pATEInfo->txSoundingMode == 1 ? 1 : 0); + pTxWI->eTxBF = pATEInfo->TxWI.eTxBF; + pTxWI->Autofallback = pATEInfo->TxWI.Autofallback; + pTxWI->NDPSndBW = pATEInfo->TxWI.BW; + if (pATEInfo->txSoundingMode == 3) + pTxWI->NDPSndRate = 2; + else if (pATEInfo->txSoundingMode == 2) + pTxWI->NDPSndRate = 1; + else + pTxWI->NDPSndRate = 0; + } + } +#endif /* TXBF_SUPPORT */ + } + + /* fill 802.11 header */ +#ifdef RALINK_QA + if (pATEInfo->bQATxStart == TRUE) + { + NdisMoveMemory(pDMAHeaderBufVA + TXWISize, pATEInfo->Header, pATEInfo->HLen); + } + else +#endif /* RALINK_QA */ + { + pATEInfo->HLen = LENGTH_802_11; +#ifdef TXBF_SUPPORT + TemplateFrame[0] = 0x08; /* Data */ + TemplateFrame[1] = 0x00; + if (pATEInfo->bTxBF && pATEInfo->txSoundingMode!=0) + { + /* QoS Data */ + pATEInfo->HLen = 32; + TemplateFrame[0] = 0x88; + TemplateFrame[1] = 0x80; + + switch (pATEInfo->txSoundingMode) + { + case 1: + /* Data Sounding */ + TemplateFrame[28] = pAd->CommonCfg.ETxBfNoncompress? 0x80: 0xc0; + TemplateFrame[29] = 0x00; + break; + case 2: + case 3: + /* 2 or 3 Stream NDP */ + TemplateFrame[28] = pAd->CommonCfg.ETxBfNoncompress? 0x80: 0xc0; + TemplateFrame[29] = 0x01; /* NDP Announce */ + break; + default: + TemplateFrame[28] = TemplateFrame[29] = 0x0; + } + } +#endif /* TXBF_SUPPORT */ + NdisMoveMemory(pDMAHeaderBufVA + TXWISize, TemplateFrame, pATEInfo->HLen); + NdisMoveMemory(pDMAHeaderBufVA + TXWISize + 4, pATEInfo->Addr1, ETH_LENGTH_OF_ADDRESS); + NdisMoveMemory(pDMAHeaderBufVA + TXWISize + 10, pATEInfo->Addr2, ETH_LENGTH_OF_ADDRESS); + NdisMoveMemory(pDMAHeaderBufVA + TXWISize + 16, pATEInfo->Addr3, ETH_LENGTH_OF_ADDRESS); + } + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (((PUCHAR)pDMAHeaderBufVA) + TXWISize), DIR_READ, FALSE); +#endif /* RT_BIG_ENDIAN */ + + /* alloc buffer for payload */ +#ifdef RALINK_QA + if ((pATEInfo->bQATxStart == TRUE) && (pATEInfo->DLen != 0)) + { + pPacket = RTMP_AllocateRxPacketBuffer(pAd, ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + pATEInfo->DLen + 0x100, FALSE, &AllocVa, &AllocPa); + } + else +#endif /* RALINK_QA */ + { + pPacket = RTMP_AllocateRxPacketBuffer(pAd, ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + pATEInfo->TxLength, FALSE, &AllocVa, &AllocPa); + } + + if (pPacket == NULL) + { + pATEInfo->TxCount = 0; + DBGPRINT_ERR(("%s : fail to alloc packet space.\n", __FUNCTION__)); + return -1; + } + + pTxRing->Cell[TxIdx].pNextNdisPacket = pPacket; + pDest = (PUCHAR) AllocVa; + +#ifdef RALINK_QA + if ((pATEInfo->bQATxStart == TRUE) && (pATEInfo->DLen != 0)) + { + GET_OS_PKT_LEN(pPacket) = pATEInfo->DLen; +#ifndef LINUX + GET_OS_PKT_TOTAL_LEN(pPacket) = pATEInfo->DLen; +#endif /* LIMUX */ + } + else +#endif /* RALINK_QA */ + { + GET_OS_PKT_LEN(pPacket) = pATEInfo->TxLength - LENGTH_802_11; +#ifndef LINUX + GET_OS_PKT_TOTAL_LEN(pPacket) = pATEInfo->TxLength - LENGTH_802_11; +#endif /* LINUX */ + } + + /* prepare frame payload */ +#ifdef RALINK_QA + if ((pATEInfo->bQATxStart == TRUE) && (pATEInfo->DLen != 0)) + { + /* copy pattern to payload */ + if ((pATEInfo->PLen != 0)) + { + for (pos = 0; pos < pATEInfo->DLen; pos += pATEInfo->PLen) + { + memcpy(GET_OS_PKT_DATAPTR(pPacket) + pos, pATEInfo->Pattern, pATEInfo->PLen); + } + } + } + else +#endif /* RALINK_QA */ + { + for (pos = 0; pos < GET_OS_PKT_LEN(pPacket); pos++) + { + /* default payload is 0xA5 */ + pDest[pos] = pATEInfo->Payload; + } + } + + /* build Tx descriptor */ +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; +#else + pDestTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; +#endif /* !RT_BIG_ENDIAN */ + +#ifdef RALINK_QA + if (pATEInfo->bQATxStart == TRUE) + { + /* prepare TxD */ + NdisZeroMemory(pTxD, TXD_SIZE); + RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); + /* build Tx descriptor */ + pTxD->SDPtr0 = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); + pTxD->SDLen0 = TXWISize + pATEInfo->HLen; + pTxD->SDPtr1 = AllocPa; + pTxD->SDLen1 = GET_OS_PKT_LEN(pPacket); + pTxD->LastSec0 = (pTxD->SDLen1 == 0) ? 1 : 0; + pTxD->LastSec1 = 1; + + pDest = (PUCHAR)pTxWI; + pDest += TXWISize; + pHeader80211 = (PHEADER_802_11)pDest; + + /* modify sequence number... */ + if (pATEInfo->TxDoneCount == 0) + pATEInfo->seq = pHeader80211->Sequence; + else + pHeader80211->Sequence = ++pATEInfo->seq; + } + else +#endif /* RALINK_QA */ + { + NdisZeroMemory(pTxD, TXD_SIZE); + RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); + /* build Tx descriptor */ + pTxD->SDPtr0 = RTMP_GetPhysicalAddressLow (pTxRing->Cell[TxIdx].DmaBuf.AllocPa); + pTxD->SDLen0 = TXWISize + LENGTH_802_11; + pTxD->LastSec0 = 0; + pTxD->SDPtr1 = AllocPa; + pTxD->SDLen1 = GET_OS_PKT_LEN(pPacket); + pTxD->LastSec1 = 1; + } + +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, (PUCHAR)pTxWI, 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 */ + + return 0; +} + +#endif /* RTMP_MAC_PCI */ + diff --git a/mt7620/src/ate/common/rt_ate.c b/mt7620/src/ate/common/rt_ate.c new file mode 100644 index 0000000..5e6dcce --- /dev/null +++ b/mt7620/src/ate/common/rt_ate.c @@ -0,0 +1,7222 @@ +/* + *************************************************************************** + * 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_ate.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ +#include "rt_config.h" + +#define ATE_BBP_REG_NUM 168 +UCHAR restore_BBP[ATE_BBP_REG_NUM]={0}; + +/* 802.11 MAC Header, Type:Data, Length:24bytes + 6 bytes QOS/HTC + 2 bytes padding */ +UCHAR TemplateFrame[32] = {0x08,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x00,0xAA,0xBB,0x12,0x34,0x56,0x00,0x11,0x22,0xAA,0xBB,0xCC,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + +extern FREQUENCY_ITEM *FreqItems3020; +extern UCHAR NUM_OF_3020_CHNL; + +#define TXCONT_TX_PIN_CFG_A 0x040C0050 +#define TXCONT_TX_PIN_CFG_G 0x080C00A0 + +#define ATE_TASK_EXEC_INTV 100 +#define ATE_TASK_EXEC_MULTIPLE 10 + +static CHAR CCKRateTable[] = {0, 1, 2, 3, 8, 9, 10, 11, -1}; /* CCK Mode. */ +static CHAR OFDMRateTable[] = {0, 1, 2, 3, 4, 5, 6, 7, -1}; /* OFDM Mode. */ +#ifdef DOT11N_SS3_SUPPORT +static CHAR HTMIXRateTable3T3R[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, -1}; /* HT Mix Mode for 3*3. */ +#endif /* DOT11N_SS3_SUPPORT */ +static CHAR HTMIXRateTable[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 32, -1}; /* HT Mix Mode. */ + +#ifdef RTMP_INTERNAL_TX_ALC + +/* The desired TSSI over CCK */ +extern CHAR desiredTSSIOverCCK[4]; + +/* The desired TSSI over OFDM */ +extern CHAR desiredTSSIOverOFDM[8]; + +#ifdef RT3352 +/* The desired TSSI over HT */ +extern CHAR desiredTSSIOverHT[16]; +#else +/* The desired TSSI over HT */ +extern CHAR desiredTSSIOverHT[8]; +#endif /* RT3352 */ + +/* The desired TSSI over HT using STBC */ +extern CHAR desiredTSSIOverHTUsingSTBC[8]; + +/* The Tx power tuning entry*/ +extern TX_POWER_TUNING_ENTRY_STRUCT TxPowerTuningTable[]; + +/* +========================================================================== + Description: + Get the desired TSSI based on ATE setting. + + Arguments: + pAd + + Return Value: + The desired TSSI +========================================================================== + */ +CHAR ATEGetDesiredTSSI( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + CHAR desiredTSSI = 0; + UCHAR MCS = 0; + UCHAR MaxMCS = 7; + + MCS = (UCHAR)(pATEInfo->TxWI.MCS); + + if (pATEInfo->TxWI.PHYMODE == MODE_CCK) + { + if (MCS > 3) /* boundary verification */ + { + DBGPRINT_ERR(("%s: incorrect MCS: MCS = %d\n", + __FUNCTION__, + MCS)); + + MCS = 0; + } + + desiredTSSI = desiredTSSIOverCCK[MCS]; + } + else if (pATEInfo->TxWI.PHYMODE == MODE_OFDM) + { + if (MCS > 7) /* boundary verification */ + { + DBGPRINT_ERR(("%s: incorrect MCS: MCS = %d\n", + __FUNCTION__, + MCS)); + + MCS = 0; + } + + desiredTSSI = desiredTSSIOverOFDM[MCS]; + } + else if ((pATEInfo->TxWI.PHYMODE == MODE_HTMIX) || (pATEInfo->TxWI.PHYMODE == MODE_HTGREENFIELD)) + { + if (pATEInfo->TxWI.STBC == STBC_NONE) + { +#ifdef RT3352 + if (IS_RT3352(pAd)) + MaxMCS = 15; +#endif /* RT3352 */ + if (MCS > MaxMCS) /* boundary verification */ + { + DBGPRINT_ERR(("%s: incorrect MCS: MCS = %d\n", + __FUNCTION__, + MCS)); + + MCS = 0; + } + + desiredTSSI = desiredTSSIOverHT[MCS]; + } + else + { + if (MCS > MaxMCS) /* boundary verification */ + { + DBGPRINT_ERR(("%s: incorrect MCS: MCS = %d\n", + __FUNCTION__, + MCS)); + + MCS = 0; + } + + desiredTSSI = desiredTSSIOverHTUsingSTBC[MCS]; + } + + + /* + For HT BW40 MCS 7 with/without STBC configuration, + the desired TSSI value should subtract one from the formula. + */ + if ((pATEInfo->TxWI.BW == BW_40) && (MCS == MCS_7)) + { + desiredTSSI -= 1; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSI = %d, Latest Tx setting: MODE = %d, MCS = %d, STBC = %d\n", + __FUNCTION__, + desiredTSSI, + pATEInfo->TxWI.PHYMODE, + pATEInfo->TxWI.MCS, + pATEInfo->TxWI.STBC)); + + + return desiredTSSI; +} + + +#ifdef RT5350 +extern UINT32 RT5350_GetDesiredTSSI( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBbpR49); +#endif /* RT5350 */ +#endif /* RTMP_INTERNAL_TX_ALC */ + + +/* +========================================================================== + Description: + Gives CCK TX rate 2 more dB TX power. + This routine works only in ATE mode. + + calculate desired Tx power in RF R3.Tx0~5, should consider - + 0. TxPowerPercentage + 1. auto calibration based on TSSI feedback + 2. extra 2 db for CCK + 3. -10 db upon very-short distance (AvgRSSI >= -40db) to AP + +========================================================================== +*/ +VOID DefaultATEAsicAdjustTxPower( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + PATE_CHIP_STRUCT pChipStruct = pATEInfo->pChipStruct; + INT index = 0, inner_index = 0, maxTxPwrCnt; + CHAR DeltaPwr = 0; + BOOLEAN bAutoTxAgc = FALSE; + UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep; + UCHAR BbpR49 = 0, idx; + PCHAR pTxAgcCompensate; + ULONG TxPwr[9]; /* NOTE: the TxPwr array size should be the maxima value of all supported chipset!!!! */ + CHAR Value; +#ifdef RTMP_INTERNAL_TX_ALC + /* (non-positive number) including the transmit power controlled by the MAC and the BBP R1 */ + CHAR TotalDeltaPower = 0; + UCHAR desiredTSSI = 0, currentTSSI = 0; + const TX_POWER_TUNING_ENTRY_STRUCT *TxPowerTuningTable = pAd->chipCap.TxPowerTuningTable_2G; + PTX_POWER_TUNING_ENTRY_STRUCT pTxPowerTuningEntry = NULL; + UCHAR RFValue = 0, TmpValue = 0; +#endif /* RTMP_INTERNAL_TX_ALC */ + + maxTxPwrCnt = pChipStruct->maxTxPwrCnt; + + if (pATEInfo->TxWI.BW == BW_40) + { + if (pATEInfo->Channel > 14) + { + for (index =0 ; index < maxTxPwrCnt; index ++) + { + TxPwr[index] = pAd->Tx40MPwrCfgABand[index]; + } + } + else + { + for (index =0 ; index < maxTxPwrCnt; index ++) + { + TxPwr[index] = pAd->Tx40MPwrCfgGBand[index]; + } + } + } + else + { + if (pATEInfo->Channel > 14) + { + for (index =0 ; index < maxTxPwrCnt; index ++) + { + TxPwr[index] = pAd->Tx20MPwrCfgABand[index]; + } + } + else + { + for (index =0 ; index < maxTxPwrCnt; index ++) + { + TxPwr[index] = pAd->Tx20MPwrCfgGBand[index]; + } + } + } + +#ifdef RTMP_INTERNAL_TX_ALC + /* Locate the internal Tx ALC tuning entry */ + if (pAd->TxPowerCtrl.bInternalTxALC == TRUE) + { + { + desiredTSSI = ATEGetDesiredTSSI(pAd); + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); + + currentTSSI = BbpR49 & 0x1F; + + if (pAd->TxPowerCtrl.bExtendedTssiMode == TRUE) /* Per-channel TSSI */ + { + if ((pATEInfo->Channel >= 1) && (pATEInfo->Channel <= 14)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: bExtendedTssiMode = %d, original desiredTSSI = %d, CentralChannel = %d, PerChTxPwrOffset = %d\n", + __FUNCTION__, + pAd->TxPowerCtrl.bExtendedTssiMode, + desiredTSSI, + pATEInfo->Channel, + pAd->TxPowerCtrl.PerChTxPwrOffset[pATEInfo->Channel])); + + desiredTSSI += pAd->TxPowerCtrl.PerChTxPwrOffset[pATEInfo->Channel]; + } + } + + if (desiredTSSI > 0x1F) + { + desiredTSSI = 0x1F; + } + + if (desiredTSSI > currentTSSI) + { + pAd->TxPowerCtrl.idxTxPowerTable++; + } + + if (desiredTSSI < currentTSSI) + { + pAd->TxPowerCtrl.idxTxPowerTable--; + } + + if (pAd->TxPowerCtrl.idxTxPowerTable < LOWERBOUND_TX_POWER_TUNING_ENTRY) + { + pAd->TxPowerCtrl.idxTxPowerTable = LOWERBOUND_TX_POWER_TUNING_ENTRY; + } + + if (pAd->TxPowerCtrl.idxTxPowerTable >= UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd)) + { + pAd->TxPowerCtrl.idxTxPowerTable = UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd); + } + + /* Valid pAd->TxPowerCtrl.idxTxPowerTable: -30 ~ 45 */ + pTxPowerTuningEntry = &TxPowerTuningTable[pAd->TxPowerCtrl.idxTxPowerTable + TX_POWER_TUNING_ENTRY_OFFSET]; /* zero-based array */ + pAd->TxPowerCtrl.RF_TX_ALC = pTxPowerTuningEntry->RF_TX_ALC; + pAd->TxPowerCtrl.MAC_PowerDelta = pTxPowerTuningEntry->MAC_PowerDelta; + + DBGPRINT(RT_DEBUG_TRACE, ("pAd->TxPowerCtrl.idxTxPowerTable = %d, pAd->TxPowerCtrl.RF_TX_ALC = %d, pAd->TxPowerCtrl.MAC_PowerDelta = %d\n", + pAd->TxPowerCtrl.idxTxPowerTable, pAd->TxPowerCtrl.RF_TX_ALC, pAd->TxPowerCtrl.MAC_PowerDelta )); + + /* Tx power adjustment over RF */ + /* In ATE mode, only adjust TX0_ALC by default. */ + if (IS_RT5350(pAd)) + { + RT30xxReadRFRegister(pAd, RF_R49, (PUCHAR)(&RFValue)); + RFValue &= ~0x3F; /* clear RF_R49[5:0] */ + RFValue |= pAd->TxPowerCtrl.RF_TX_ALC; + DBGPRINT(RT_DEBUG_TRACE, ("Write RF_R49 = 0x%x\n", RFValue)); + RT30xxWriteRFRegister(pAd, RF_R49, (UCHAR)RFValue); + } + else if (IS_RT3352(pAd)) + { + RT30xxReadRFRegister(pAd, RF_R47, (PUCHAR)(&RFValue)); + RFValue &= ~0x1F; /* clear RF_R47[4:0] */ + RFValue |= pAd->TxPowerCtrl.RF_TX_ALC; + DBGPRINT(RT_DEBUG_TRACE, ("Write RF_R47 = 0x%x\n", RFValue)); + RT30xxWriteRFRegister(pAd, RF_R47, (UCHAR)RFValue); + } + else + { + RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)(&RFValue)); + TmpValue = (RFValue & 0xE0); + RFValue = (TmpValue | (pAd->TxPowerCtrl.RF_TX_ALC & 0x1F)); + DBGPRINT(RT_DEBUG_TRACE, ("Write RF_R12 = 0x%x\n", RFValue)); + RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)(RFValue)); + } + + /* Tx power adjustment over MAC */ + TotalDeltaPower += pAd->TxPowerCtrl.MAC_PowerDelta; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSI = %d, currentTSSI = %d, idxTxPowerTable = %d, {RF_TX_ALC = %d, MAC_PowerDelta = %d}\n", + __FUNCTION__, + desiredTSSI, + currentTSSI, + pAd->TxPowerCtrl.idxTxPowerTable, + pTxPowerTuningEntry->RF_TX_ALC, + pTxPowerTuningEntry->MAC_PowerDelta)); + } + } +#endif /* RTMP_INTERNAL_TX_ALC */ + + /* TX power compensation for temperature variation based on TSSI. */ + /* Do it per 4 seconds. */ + if (pATEInfo->OneSecPeriodicRound % 4 == 0) + { + if (pATEInfo->Channel <= 14) + { + /* bg channel */ + bAutoTxAgc = pAd->bAutoTxAgcG; + TssiRef = pAd->TssiRefG; + pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0]; + TxAgcStep = pAd->TxAgcStepG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + /* a channel */ + bAutoTxAgc = pAd->bAutoTxAgcA; + TssiRef = pAd->TssiRefA; + pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0]; + TxAgcStep = pAd->TxAgcStepA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + { + /* BbpR49 is unsigned char. */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); + + /* (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 0x10 ~ 0x40, minus is 0x60 ~ 0x90 */ + /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */ + /* if value is 0x65, tx power will be -= TxAgcStep*(2-1) */ + + if (BbpR49 > 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++) + { + /* Found the range. */ + if (BbpR49 <= pTssiMinusBoundary[idx]) + 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 R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n", + BbpR49, TssiRef, TxAgcStep, idx-1)); + } + else if (BbpR49 < 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++) + { + /* Found the range. */ + if (BbpR49 >= pTssiPlusBoundary[idx]) + 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 R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, idx-1)); + } + else + { + *pTxAgcCompensate = 0; + DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, 0)); + } + } + } + else + { + if (pATEInfo->Channel <= 14) + { + bAutoTxAgc = pAd->bAutoTxAgcG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + bAutoTxAgc = pAd->bAutoTxAgcA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + DeltaPwr += (*pTxAgcCompensate); + } + + /* Reset different new tx power for different TX rate. */ + for (index=0; index> inner_index*4) & 0x0F); /* 0 ~ 15 */ + +#ifdef RTMP_INTERNAL_TX_ALC + /* + The upper bounds of the MAC 0x1314~0x1324 + are variable when the STA uses the internal Tx ALC. + */ + if (pAd->TxPowerCtrl.bInternalTxALC == TRUE) + { + switch (TX_PWR_CFG_0 + (index * 4)) + { + case TX_PWR_CFG_0: + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE) + { + Value = 0xE; + } + else + { + Value += TotalDeltaPower; + } + } + break; + + case TX_PWR_CFG_1: + { + if ((inner_index >= 0) && (inner_index <= 3)) + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xC) + { + Value = 0xC; + } + else + { + Value += TotalDeltaPower; + } + } + else + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE) + { + Value = 0xE; + } + else + { + Value += TotalDeltaPower; + } + } + } + break; + + case TX_PWR_CFG_2: + { + if ((inner_index == 0) || (inner_index == 2) || (inner_index == 3)) + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xC) + { + Value = 0xC; + } + else + { + Value += TotalDeltaPower; + } + } + else + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE) + { + Value = 0xE; + } + else + { + Value += TotalDeltaPower; + } + } + } + break; + + case TX_PWR_CFG_3: + { + if ((inner_index == 0) || (inner_index == 2) || (inner_index == 3) || + ((inner_index >= 4) && (inner_index <= 7))) + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xC) + { + Value = 0xC; + } + else + { + Value += TotalDeltaPower; + } + } + else + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE) + { + Value = 0xE; + } + else + { + Value += TotalDeltaPower; + } + } + } + break; + + case TX_PWR_CFG_4: + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xC) + { + Value = 0xC; + } + else + { + Value += TotalDeltaPower; + } + } + break; + + default: + { + /* do nothing */ + DBGPRINT_ERR(("%s : unknown register = 0x%X\n", + __FUNCTION__, + (TX_PWR_CFG_0 + (index << 2)))); + } + break; + } + } + else +#endif /* RTMP_INTERNAL_TX_ALC */ + { + if ((Value + DeltaPwr) < 0) + { + Value = 0; /* min */ + } + else if ((Value + DeltaPwr) > 0xF) + { + Value = 0xF; /* max */ + } + else + { + Value += DeltaPwr; /* temperature compensation */ + } + } + + /* fill new value to CSR offset */ + TxPwr[index] = (TxPwr[index] & ~(0x0000000F << inner_index*4)) | (Value << inner_index*4); + } + + /* write tx power value to CSR */ + /* + TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M + TX power for OFDM 6M/9M + TX power for CCK5.5M/11M + TX power for CCK1M/2M + */ + /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */ +#ifdef DOT11N_SS3_SUPPORT + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + { + if (index == 5) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_5, TxPwr[index]); + } + else if (index == 6) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_6, TxPwr[index]); + } +#ifdef RT3883 + else if ((IS_RT3883(pAd)) && (index == 7)) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_7, TxPwr[index]); + } + else if ((IS_RT3883(pAd)) && (index == 8)) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_8, TxPwr[index]); + } +#endif /* RT3883 */ + else + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + (index << 2), TxPwr[index]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0_EXT + (index << 2), (TxPwr[index] & 0xf0f0f0f0) >> 4); + } + } + else + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + (index << 2), TxPwr[index]); + } +#else + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + (index << 2), TxPwr[index]); +#endif /* DOT11N_SS3_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("ATEAsicAdjustTxPower - DeltaPwr=%d, offset=0x%x, TxPwr=%lx, BbpR1=%x, round=%ld, pTxAgcCompensate=%d \n", + DeltaPwr, TX_PWR_CFG_0 + (index << 2), TxPwr[index], BbpR49, pATEInfo->OneSecPeriodicRound, *pTxAgcCompensate)); + + } + } + +} + + +/* +========================================================================== + Description: + Gives CCK TX rate 2 more dB TX power. + This routine works only in ATE mode. + + calculate desired Tx power in RF R3.Tx0~5, should consider - + 0. TxPowerPercentage + 1. auto calibration based on TSSI feedback + 2. extra 2 db for CCK + 3. -10 db upon very-short distance (AvgRSSI >= -40db) to AP + +========================================================================== +*/ +VOID ATEAsicAdjustTxPower( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + if (pATEInfo->pChipStruct->AdjustTxPower != NULL) + pATEInfo->pChipStruct->AdjustTxPower(pAd); + else + DBGPRINT_ERR(("%s: AdjustTxPower() for this chipset does not exist !\n", __FUNCTION__)); + + return; +} + + +CHAR ATEConvertToRssi( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi, + IN UCHAR RssiNumber) +{ + UCHAR RssiOffset, LNAGain; + CHAR BaseVal; + + /* Rssi equals to zero should be an invalid value */ + if (Rssi == 0) + return -99; + + LNAGain = GET_LNA_GAIN(pAd); + if (pAd->LatchRfRegs.Channel > 14) + { + if (RssiNumber == 0) + RssiOffset = pAd->ARssiOffset0; + else if (RssiNumber == 1) + RssiOffset = pAd->ARssiOffset1; + else + RssiOffset = pAd->ARssiOffset2; + } + else + { + if (RssiNumber == 0) + RssiOffset = pAd->BGRssiOffset0; + else if (RssiNumber == 1) + RssiOffset = pAd->BGRssiOffset1; + else + RssiOffset = pAd->BGRssiOffset2; + } + + BaseVal = -12; + +#ifdef RT6352 + if (IS_RT6352(pAd)) + BaseVal = -2; +#endif /* RT6352 */ + + return (BaseVal - RssiOffset - LNAGain - Rssi); +} + + +VOID ATESampleRssi( + IN PRTMP_ADAPTER pAd, + IN PRXWI_STRUC pRxWI) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + if (pRxWI->RSSI0 != 0) + { + pATEInfo->LastRssi0 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI0, RSSI_0); + pATEInfo->AvgRssi0X8 = (pATEInfo->AvgRssi0X8 - pATEInfo->AvgRssi0) + pATEInfo->LastRssi0; + pATEInfo->AvgRssi0 = pATEInfo->AvgRssi0X8 >> 3; + } + + if (pRxWI->RSSI1 != 0) + { + pATEInfo->LastRssi1 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI1, RSSI_1); + pATEInfo->AvgRssi1X8 = (pATEInfo->AvgRssi1X8 - pATEInfo->AvgRssi1) + pATEInfo->LastRssi1; + pATEInfo->AvgRssi1 = pATEInfo->AvgRssi1X8 >> 3; + } + + if (pRxWI->RSSI2 != 0) + { + pATEInfo->LastRssi2 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI2, RSSI_2); + pATEInfo->AvgRssi2X8 = (pATEInfo->AvgRssi2X8 - pATEInfo->AvgRssi2) + pATEInfo->LastRssi2; + pATEInfo->AvgRssi2 = pATEInfo->AvgRssi2X8 >> 3; + } + + pATEInfo->LastSNR0 = (CHAR)(pRxWI->SNR0); + pATEInfo->LastSNR1 = (CHAR)(pRxWI->SNR1); +#ifdef DOT11N_SS3_SUPPORT + pATEInfo->LastSNR2 = (CHAR)(pRxWI->SNR2); +#endif /* DOT11N_SS3_SUPPORT */ + + pATEInfo->NumOfAvgRssiSample ++; + + return; +} + + +VOID rt_ee_read_all(PRTMP_ADAPTER pAd, USHORT *Data) +{ + USHORT offset = 0; + USHORT value; + +#ifdef RTMP_FLASH_SUPPORT + { + rtmp_ee_flash_read_all(pAd, Data); + return; + } +#endif /* RTMP_FLASH_SUPPORT */ + + for (offset = 0; offset < (EEPROM_SIZE >> 1);) + { + RT28xx_EEPROM_READ16(pAd, (offset << 1), value); + Data[offset] = value; + offset++; + } + + return; +} + + +VOID rt_ee_write_all(PRTMP_ADAPTER pAd, USHORT *Data) +{ + USHORT offset = 0; + USHORT value; + +#ifdef RTMP_FLASH_SUPPORT + { + rtmp_ee_flash_write_all(pAd, Data); + return; + } +#endif /* RTMP_FLASH_SUPPORT */ + + + for (offset = 0; offset < (EEPROM_SIZE >> 1);) + { + value = Data[offset]; + RT28xx_EEPROM_WRITE16(pAd, (offset << 1), value); + offset++; + } + + return; +} + + +VOID rt_ee_write_bulk(PRTMP_ADAPTER pAd, USHORT *Data, USHORT offset, USHORT length) +{ + USHORT pos; + USHORT value; + USHORT len = length; + +#ifdef RTMP_FLASH_SUPPORT + { + for (pos = 0; pos < (len >> 1);) + { + value = Data[pos]; + rtmp_ee_flash_write(pAd, offset+(pos*2), value); + pos++; + } + + return; + } +#endif /* RTMP_FLASH_SUPPORT */ + + for (pos = 0; pos < (len >> 1);) + { + value = Data[pos]; + RT28xx_EEPROM_WRITE16(pAd, offset+(pos*2), value); + pos++; + } + + return; +} + + +VOID RtmpRfIoWrite( + IN PRTMP_ADAPTER pAd) +{ + /* Set RF value 1's set R3[bit2] = [0] */ + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + RTMPusecDelay(200); + + /* Set RF value 2's set R3[bit2] = [1] */ + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04)); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + RTMPusecDelay(200); + + /* Set RF value 3's set R3[bit2] = [0] */ + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + return; +} + + +VOID DefaultATEAsicSetTxRxPath( + IN PRTMP_ADAPTER pAd) +{ + +} + + +VOID ATEAsicSetTxRxPath( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + if (pATEInfo->pChipStruct->AsicSetTxRxPath != NULL) + pATEInfo->pChipStruct->AsicSetTxRxPath(pAd); + + return; +} + + +/* +========================================================================== + Description: + + Default AsicSwitchChannel() dedicated for ATE. + +========================================================================== +*/ +VOID DefaultATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 Value = 0; + CHAR TxPwer = 0, TxPwer2 = 0; + UCHAR BbpValue = 0, R66 = 0x30, Channel = 0; + + SYNC_CHANNEL_WITH_QA(pATEInfo, &Channel); + + /* fill Tx power value */ + TxPwer = pATEInfo->TxPower0; + TxPwer2 = pATEInfo->TxPower1; + + /* Change BBP setting during switch from a->g, g->a */ + if (Channel <= 14) + { + UINT32 TxPinCfg = 0x00050F0A;/* 2007.10.09 by Brian : 0x0005050A ==> 0x00050F0A */ + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + + /* Rx High power VGA offset for LNA select */ + if (pAd->NicConfig2.field.ExternalLNAForG) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + /* 2.4 G band selection PIN */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x04); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + /* 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; + } + + /* calibration power unbalance issues */ + if (pAd->Antenna.field.TxPath == 2) + { + if (pATEInfo->TxAntennaSel == 1) + { + TxPinCfg &= 0xFFFFFFF7; + } + else if (pATEInfo->TxAntennaSel == 2) + { + TxPinCfg &= 0xFFFFFFFD; + } + } + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + } + /* channel > 14 */ + else + { + UINT32 TxPinCfg = 0x00050F05;/* 2007.10.09 by Brian : 0x00050505 ==> 0x00050F05 */ + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + + /* According the Rory's suggestion to solve the middle range issue. */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0); + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2); + + /* Rx High power VGA offset for LNA select */ + if (pAd->NicConfig2.field.ExternalLNAForA) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R91, &BbpValue); + ASSERT((BbpValue == 0x04)); + + /* 5 G band selection PIN, bit1 and bit2 are complement */ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x02); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + /* 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); + } + + /* R66 should be set according to Channel. */ + if (Channel <= 14) + { + /* BG band */ + R66 = 0x2E + GET_LNA_GAIN(pAd); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + else + { + /* A band, BW == 20 */ + if (pATEInfo->TxWI.BW == BW_20) + { + R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + else + { + /* A band, BW == 40 */ + R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + } + + RtmpOsMsDelay(1); + +} + + +/* +========================================================================== + Description: + + AsicSwitchChannel() dedicated for ATE. + +========================================================================== +*/ +VOID ATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + if (pATEInfo->pChipStruct->ChannelSwitch != NULL) + pATEInfo->pChipStruct->ChannelSwitch(pAd); + + return; +} + + +VOID BbpSoftReset( + IN PRTMP_ADAPTER pAd) +{ + UCHAR BbpData = 0; + + /* Soft reset, set BBP R21 bit0=1->0 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &BbpData); + BbpData |= 0x00000001; /* set bit0=1 */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BbpData); + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &BbpData); + BbpData &= ~(0x00000001); /* set bit0=0 */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BbpData); + + return; +} + + +static VOID BbpHardReset( + IN PRTMP_ADAPTER pAd) +{ + UINT32 MacData = 0; + + + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); + MacData = MacData | 0x00000002; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); + + RtmpOsMsDelay(10); + + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); + MacData = MacData & ~(0x00000002); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); + + return; +} + + +static int CheckMCSValid( + IN PRTMP_ADAPTER pAd, + IN UCHAR Mode, + IN UCHAR Mcs) +{ + int index; + PCHAR pRateTab = NULL; + + switch (Mode) + { + case MODE_CCK: + pRateTab = CCKRateTable; + break; + case MODE_OFDM: + pRateTab = OFDMRateTable; + break; + + case 2: /*MODE_HTMIX*/ + case 3: /*MODE_HTGREENFIELD*/ +#ifdef DOT11N_SS3_SUPPORT + if (IS_RT2883(pAd) || IS_RT3883(pAd) || IS_RT3593(pAd)) + pRateTab = HTMIXRateTable3T3R; + else +#endif /* DOT11N_SS3_SUPPORT */ + pRateTab = HTMIXRateTable; + break; + + default: + DBGPRINT_ERR(("unrecognizable Tx Mode %d\n", Mode)); + return -1; + break; + } + + index = 0; + while (pRateTab[index] != -1) + { + if (pRateTab[index] == Mcs) + return 0; + index++; + } + + return -1; +} + + +INT DefaultATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index) +{ + PATE_INFO pATEInfo = &(pAd->ate); + CHAR TxPower = 0; +#ifdef RTMP_RF_RW_SUPPORT +#ifndef RF_BANK + UCHAR RFValue = 0; +#endif /* !RF_BANK */ +#endif /* RTMP_RF_RW_SUPPORT */ + +#ifdef RALINK_QA + if ((pATEInfo->bQATxStart == TRUE) || (pATEInfo->bQARxStart == TRUE)) + { + /* + When QA is used for Tx, pATEInfo->TxPower0/1 and real tx power + are not synchronized. + */ + return 0; + } + else +#endif /* RALINK_QA */ + + if (index == 0) + { + TxPower = pATEInfo->TxPower0; + } + else if (index == 1) + { + TxPower = pATEInfo->TxPower1; + } + else + { + DBGPRINT_ERR(("%s : Only TxPower0 and TxPower1 are adjustable !\n", __FUNCTION__)); + DBGPRINT_ERR(("TxPower%d is out of range !\n", index)); + return -1; + } + +#ifdef RTMP_RF_RW_SUPPORT + + if ((IS_RT30xx(pAd) || IS_RT3390(pAd))) + { + { +#ifndef RF_BANK + /* Set Tx Power */ + UCHAR ANT_POWER_INDEX=RF_R12+index; + ATE_RF_IO_READ8_BY_REG_ID(pAd, ANT_POWER_INDEX, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xE0) | TxPower; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, ANT_POWER_INDEX, (UCHAR)RFValue); + DBGPRINT(RT_DEBUG_TRACE, ("3070 or 2070:%s (TxPower[%d]=%d, RFValue=%x)\n", __FUNCTION__, index,TxPower, RFValue)); +#endif /* RF_BANK */ + } + } + else +#endif /* RTMP_RF_RW_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("<--- %s\n", __FUNCTION__)); + + return 0; +} + + +INT ATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + if (pATEInfo->pChipStruct->TxPwrHandler != NULL) + pATEInfo->pChipStruct->TxPwrHandler(pAd, index); + + return 0; +} + + +/* +======================================================================== + + Routine Description: + Set Japan filter coefficients if needed. + Note: + This routine should only be called when + entering TXFRAME mode or TXCONT mode. + +======================================================================== +*/ +static VOID SetJapanFilter( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR BbpData = 0; + + /* + If Channel=14 and Bandwidth=20M and Mode=CCK, set BBP R4 bit5=1 + (Japan Tx filter coefficients)when (TXFRAME or TXCONT). + */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BbpData); + + if ((pATEInfo->TxWI.PHYMODE == MODE_CCK) && (pATEInfo->Channel == 14) && (pATEInfo->TxWI.BW == BW_20)) + { + BbpData |= 0x20; /* turn on */ + DBGPRINT(RT_DEBUG_TRACE, ("SetJapanFilter!!!\n")); + } + else + { + BbpData &= 0xdf; /* turn off */ + DBGPRINT(RT_DEBUG_TRACE, ("ClearJapanFilter!!!\n")); + } + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BbpData); + + return; +} + + +/* +======================================================================== + + Routine Description: + Disable protection for ATE. +======================================================================== +*/ +VOID ATEDisableAsicProtect( + IN PRTMP_ADAPTER pAd) +{ + PROT_CFG_STRUC ProtCfg, ProtCfg4; + UINT32 Protect[6]; + USHORT offset; + UCHAR step; + UINT32 MacReg = 0; + + /* Config ASIC RTS threshold register */ + RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg); + MacReg &= 0xFF0000FF; + MacReg |= (0xFFF << 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; + + /* Handle legacy(B/G) protection */ + ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; + ProtCfg.field.ProtectCtrl = 0; + Protect[0] = ProtCfg.word; + Protect[1] = ProtCfg.word; + /* CTS-self is not used */ + pAd->FlgCtsEnabled = 0; + + /* + NO PROTECT + 1.All STAs in the BSS are 20/40 MHz HT + 2. in a 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; + + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; + + offset = CCK_PROT_CFG; + for (step = 0;step < 6;step++) + RTMP_IO_WRITE32(pAd, offset + step*4, Protect[step]); + + return; +} + + +#ifdef CONFIG_AP_SUPPORT +/* +========================================================================== + Description: + Used only by ATE to disassociate all STAs and stop AP service. + Note: +========================================================================== +*/ +VOID ATEAPStop( + IN PRTMP_ADAPTER pAd) +{ + BOOLEAN Cancelled; + UINT32 Value = 0; + INT apidx = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("!!! ATEAPStop !!!\n")); + + /* To prevent MCU to modify BBP registers w/o indications from driver. */ +#ifdef DFS_SUPPORT + NewRadarDetectionStop(pAd); +#endif /* DFS_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef CARRIER_DETECTION_SUPPORT + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + { + CarrierDetectionStop(pAd); + } +#endif /* CARRIER_DETECTION_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef MESH_SUPPORT + if (MESH_ON(pAd)) + MeshDown(pAd, TRUE); +#endif /* MESH_SUPPORT */ + +#ifdef WDS_SUPPORT + WdsDown(pAd); +#endif /* WDS_SUPPORT */ + +#ifdef APCLI_SUPPORT + ApCliIfDown(pAd); +#endif /* APCLI_SUPPORT */ + + MacTableReset(pAd); + + /* 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); + + ATEDisableAsicProtect(pAd); + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + AsicDisableSync(pAd); + +#ifdef LED_CONTROL_SUPPORT + /* Set LED */ + RTMPSetLED(pAd, LED_LINK_DOWN); +#endif /* LED_CONTROL_SUPPORT */ + } + + + for (apidx = 0; apidx < MAX_MBSSID_NUM(pAd); apidx++) + { + if (pAd->ApCfg.MBSSID[apidx].REKEYTimerRunning == TRUE) + { + RTMPCancelTimer(&pAd->ApCfg.MBSSID[apidx].REKEYTimer, &Cancelled); + pAd->ApCfg.MBSSID[apidx].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); + + if (pAd->ApCfg.ApQuickResponeForRateUpTimerRunning == TRUE) + RTMPCancelTimer(&pAd->ApCfg.ApQuickResponeForRateUpTimer, &Cancelled); + +#ifdef IDS_SUPPORT + /* if necessary, cancel IDS timer */ + RTMPIdsStop(pAd); +#endif /* IDS_SUPPORT */ + + +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPEnable == TRUE) + { + RTMP_CHIP_DISABLE_AP_MIMOPS(pAd); + pAd->ApCfg.GreenAPLevel=GREENAP_WITHOUT_ANY_STAS_CONNECT; + pAd->ApCfg.bGreenAPEnable = FALSE; + } +#endif /* GREENAP_SUPPORT */ + + + +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x00); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x00); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x00); + +#ifdef DYNAMIC_VGA_SUPPORT + if (pAd->CommonCfg.MO_Cfg.bDyncVGAEnable == TRUE) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x83); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x32); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x86); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x19); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x9c); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x3d); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x9d); + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x40); + else + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x2F); + + ATEBBPWriteWithRxChain(pAd, BBP_R66, pAd->CommonCfg.MO_Cfg.Stored_BBP_R66, RX_CHAIN_ALL); + } +#endif /* DYNAMIC_VGA_SUPPORT */ + } +#endif /* RT6352 */ +} +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT +VOID RTMPStationStop( + IN PRTMP_ADAPTER pAd) +{ + DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPStationStop\n")); + +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x00); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x00); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x00); + } +#endif /* RT6352 */ + + /* Do nothing. */ + + DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPStationStop\n")); +} + + +VOID RTMPStationStart( + IN PRTMP_ADAPTER pAd) +{ + DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPStationStart\n")); + +#ifdef RTMP_MAC_PCI + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; +#endif /* RTMP_MAC_PCI */ + + DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPStationStart\n")); +} +#endif /* CONFIG_STA_SUPPORT */ + + + + +static NDIS_STATUS ATESTART( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 MacData=0, atemode=0, temp=0; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; +#ifdef RTMP_MAC_PCI + UINT32 ring_index=0; + PTXD_STRUC pTxD = NULL; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD = NULL; + TXD_STRUC TxD; +#endif /* RT_BIG_ENDIAN */ +#endif /* RTMP_MAC_PCI */ + UCHAR BbpData = 0; + PATE_CHIP_STRUCT pChipStruct = pATEInfo->pChipStruct; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("ATE : ===> %s\n", __FUNCTION__)); + + +#ifdef RTMP_MAC_PCI +#ifndef RTMP_RBUS_SUPPORT + /* check if we have removed the firmware */ + if (!(ATE_ON(pAd))) + { + NICEraseFirmware(pAd); + } +#endif /* RTMP_RBUS_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + + atemode = pATEInfo->Mode; + pATEInfo->Mode = ATE_START; +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + UINT32 mac_value; + + /* reset/disable DPD */ + pATEInfo->bDPDEnable = FALSE; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x00); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x00); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x00); + 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; + + if (atemode == ATE_STOP) + { + RT6352_RTMPReadTxPwrPerRate(pAd); + RTMP_CHIP_ASIC_EXTRA_POWER_OVER_MAC(pAd); + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &mac_value); + mac_value &= 0xFFFFFFC0; + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_1, mac_value); + } + } +#endif /* RT6352 */ + + if ((atemode == ATE_STOP) && (!IS_RT6352(pAd))) + { + /* DUT just enters ATE mode from normal mode. */ + /* Only at this moment, we need to switch back to the channel of normal mode. */ + } + + + /* Disable Rx */ + ATE_MAC_RX_DISABLE(pAd, MAC_SYS_CTRL, &MacData); + + /* Disable auto responder */ + RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &temp); + temp = temp & 0xFFFFFFFE; + RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, temp); + + ATE_MAC_TX_CTS_DISABLE(pAd, MAC_SYS_CTRL, &MacData); + + if (atemode == ATE_TXCARR) + { + if (pChipStruct->bBBPStoreTXCARR == TRUE) + { + UINT32 bbp_index=0; + UCHAR RestoreRfICType=pAd->RfIcType; + + BbpHardReset(pAd); + + /* Restore All BBP Value */ + for (bbp_index=0;bbp_indexRfIcType=RestoreRfICType; + } + + if (pATEInfo->TxMethod == TX_METHOD_1) + { + /* No Carrier Test set BBP R22 bit6=0, bit[5~0]=0x0 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= 0xFFFFFF80; /* clear bit6, bit[5~0] */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + + BbpSoftReset(pAd); + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, (pATEInfo->Default_TX_PIN_CFG)); + } + else + { + /* No Carrier Test set BBP R22 bit7=0, bit6=0, bit[5~0]=0x0 */ + ATE_BBP_RESET_TX_MODE(pAd, BBP_R22, &BbpData); + } + } + else if (atemode == ATE_TXCARRSUPP) + { + if (pChipStruct->bBBPStoreTXCARRSUPP == TRUE) + { + UINT32 bbp_index=0; + UCHAR RestoreRfICType=pAd->RfIcType; + + BbpHardReset(pAd); + + /* Restore All BBP Value */ + for (bbp_index=0;bbp_indexRfIcType=RestoreRfICType; + } + +#ifdef RT6352 + /* No Carrier Suppression set BBP R21 bit4=0 */ + if (IS_RT6352(pAd)) + { + BbpData = 0x00; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BbpData); + } +#endif /* RT6352 */ + + /* No Cont. TX set BBP R22 bit7=0 */ + ATE_BBP_STOP_CTS_TX_MODE(pAd, BBP_R22, &BbpData); + + /* No Carrier Suppression set BBP R24 bit0=0 */ + ATE_BBP_CTS_TX_SIN_WAVE_DISABLE(pAd, BBP_R24, &BbpData); + + if (pATEInfo->TxMethod == TX_METHOD_1) + { + BbpSoftReset(pAd); + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, (pATEInfo->Default_TX_PIN_CFG)); + } + } + + /* + We should free some resource which was allocated + when ATE_TXFRAME , ATE_STOP, and ATE_TXCONT. + */ + else if ((atemode & ATE_TXFRAME) || (atemode == ATE_STOP)) + { +#ifdef RTMP_MAC_PCI + PRTMP_TX_RING pTxRing = &pAd->TxRing[QID_AC_BE]; +#endif /* RTMP_MAC_PCI */ + if (atemode == ATE_TXCONT) + { + if (pChipStruct->bBBPStoreTXCONT == TRUE) + { + UINT32 bbp_index=0; + UCHAR RestoreRfICType=pAd->RfIcType; + + BbpHardReset(pAd); + + /* Restore All BBP Value */ + for (bbp_index=0;bbp_indexRfIcType=RestoreRfICType; + } +#ifdef RT305x + if (IS_RT3050(pAd)) + { + /* fix RT3050S ATE SWITCH Mode */ + /* suggestion from Arvin Wang at 01/28/2010 */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, 0x38); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + } +#endif /* RT305x */ + + /* Not Cont. TX anymore, so set BBP R22 bit7=0 */ + ATE_BBP_STOP_CTS_TX_MODE(pAd, BBP_R22, &BbpData); + + if (pATEInfo->TxMethod == TX_METHOD_1) + { + BbpSoftReset(pAd); + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, (pATEInfo->Default_TX_PIN_CFG)); + } + } + + /* Abort Tx, Rx DMA. */ + RtmpDmaEnable(pAd, 0); +#ifdef RTMP_MAC_PCI + for (ring_index=0; ring_indexTxRing[QID_AC_BE].Cell[ring_index].AllocVa; +#else + pDestTxD = (PTXD_STRUC)pAd->TxRing[QID_AC_BE].Cell[ring_index].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif /* !RT_BIG_ENDIAN */ + pTxD->DMADONE = 0; + pPacket = pTxRing->Cell[ring_index].pNdisPacket; + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + + /* Always assign pNdisPacket as NULL after clear */ + pTxRing->Cell[ring_index].pNdisPacket = NULL; + + pPacket = pTxRing->Cell[ring_index].pNextNdisPacket; + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + + /* Always assign pNextNdisPacket as NULL after clear */ + pTxRing->Cell[ring_index].pNextNdisPacket = NULL; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif /* RT_BIG_ENDIAN */ + } +#endif /* RTMP_MAC_PCI */ + + /* Start Tx, RX DMA */ + RtmpDmaEnable(pAd, 1); + } + + + /* reset Rx statistics. */ + pATEInfo->LastSNR0 = 0; + pATEInfo->LastSNR1 = 0; +#ifdef DOT11N_SS3_SUPPORT + pATEInfo->LastSNR2 = 0; +#endif /* DOT11N_SS3_SUPPORT */ + pATEInfo->LastRssi0 = 0; + pATEInfo->LastRssi1 = 0; + pATEInfo->LastRssi2 = 0; + pATEInfo->AvgRssi0 = 0; + pATEInfo->AvgRssi1 = 0; + pATEInfo->AvgRssi2 = 0; + pATEInfo->AvgRssi0X8 = 0; + pATEInfo->AvgRssi1X8 = 0; + pATEInfo->AvgRssi2X8 = 0; + pATEInfo->NumOfAvgRssiSample = 0; + +#ifdef RALINK_QA + /* Tx frame */ + pATEInfo->bQATxStart = FALSE; + pATEInfo->bQARxStart = FALSE; + pATEInfo->seq = 0; + + /* counters */ + pATEInfo->U2M = 0; + pATEInfo->OtherData = 0; + pATEInfo->Beacon = 0; + pATEInfo->OtherCount = 0; + pATEInfo->TxAc0 = 0; + pATEInfo->TxAc1 = 0; + pATEInfo->TxAc2 = 0; + pATEInfo->TxAc3 = 0; + pATEInfo->TxHCCA = 0; + pATEInfo->TxMgmt = 0; + pATEInfo->RSSI0 = 0; + pATEInfo->RSSI1 = 0; + pATEInfo->RSSI2 = 0; + pATEInfo->SNR0 = 0; + pATEInfo->SNR1 = 0; +#ifdef DOT11N_SS3_SUPPORT + pATEInfo->SNR2 = 0; +#endif /* DOT11N_SS3_SUPPORT */ + /* control */ + pATEInfo->TxDoneCount = 0; + /* TxStatus : 0 --> task is idle, 1 --> task is running */ + pATEInfo->TxStatus = 0; +#endif /* RALINK_QA */ + +#if !defined(RT3883) && !defined(RT3593) + if (!IS_RT6352(pAd)) + { + /* Soft reset BBP. */ + BbpSoftReset(pAd); + } +#endif /* !defined(RT3883) && !defined(RT3593) */ + +#ifdef CONFIG_AP_SUPPORT + if (atemode == ATE_STOP) + ATEAPStop(pAd); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + AsicDisableSync(pAd); + ATEDisableAsicProtect(pAd); + RTMPStationStop(pAd); +#endif /* CONFIG_STA_SUPPORT */ + + if ((atemode == ATE_STOP) && (pATEInfo->PeriodicTimer.State == FALSE)) + { + /* Do it for the first time entering ATE mode */ + pATEInfo->PeriodicTimer.State = TRUE; + } + + if (pATEInfo->PeriodicTimer.State == TRUE) + { + /* + For rx statistics, we cancel pAd->Mlme.PeriodicTimer + and set pAd->ate.PeriodicTimer. + */ + RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled); + /* Init ATE periodic timer */ + RTMPInitTimer(pAd, &pAd->ate.PeriodicTimer, GET_TIMER_FUNCTION(ATEPeriodicExec), pAd, TRUE); + /* Set ATE periodic timer */ + RTMPSetTimer(&pAd->ate.PeriodicTimer, ATE_TASK_EXEC_INTV); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("We are still in ATE mode, ")); + DBGPRINT(RT_DEBUG_TRACE, ("so we keep ATE periodic timer running.\n")); + } + +#ifdef LED_CONTROL_SUPPORT +#endif /* LED_CONTROL_SUPPORT */ + +#ifdef RTMP_MAC_PCI + /* Disable Tx */ + ATE_MAC_TX_DISABLE(pAd, MAC_SYS_CTRL, &MacData); + + /* Disable Rx */ + ATE_MAC_RX_DISABLE(pAd, MAC_SYS_CTRL, &MacData); + + +#endif /* RTMP_MAC_PCI */ + + + DBGPRINT(RT_DEBUG_TRACE, ("ATE : <=== %s\n", __FUNCTION__)); + return Status; +} + + +static NDIS_STATUS ATESTOP( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 MacData=0, ring_index=0; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; +#ifdef RTMP_MAC_PCI +#ifdef RT_BIG_ENDIAN + PRXD_STRUC pDestRxD; + RXD_STRUC RxD; +#endif /* RT_BIG_ENDIAN */ + PRXD_STRUC pRxD = NULL; +#endif /* RTMP_MAC_PCI */ + UCHAR BbpData = 0; + PATE_CHIP_STRUCT pChipStruct = pATEInfo->pChipStruct; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("ATE : ===> %s\n", __FUNCTION__)); + + if (pChipStruct->bBBPLoadATESTOP == TRUE) + { + UINT32 bbp_index=0; + UCHAR RestoreRfICType=pAd->RfIcType; + + BbpHardReset(pAd); + + /* Supposed that we have had a record in restore_BBP[] */ + /* restore all BBP value */ + for (bbp_index=0;bbp_indexRfIcType=RestoreRfICType; + } + + /* Default value in BBP R22 is 0x0. */ + ATE_BBP_RESET_TX_MODE(pAd, BBP_R22, &BbpData); + + /* Clear bit4 to stop continuous Tx production test. */ + ATE_MAC_TX_CTS_DISABLE(pAd, MAC_SYS_CTRL, &MacData); + + /* Disable Rx */ + ATE_MAC_RX_DISABLE(pAd, MAC_SYS_CTRL, &MacData); + + /* Abort Tx, RX DMA */ + RtmpDmaEnable(pAd, 0); + + /* Disable Tx */ + ATE_MAC_TX_DISABLE(pAd, MAC_SYS_CTRL, &MacData); + +#ifdef RTMP_MAC_PCI + if (IS_PCI_INF(pAd)) + { + pATEInfo->bFWLoading = TRUE; + Status = NICLoadFirmware(pAd); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("NICLoadFirmware failed, Status[=0x%08x]\n", Status)); + return Status; + } + } + pATEInfo->Mode = ATE_STOP; + BbpSoftReset(pAd); + + RTMP_ASIC_INTERRUPT_DISABLE(pAd); +#endif /* RTMP_MAC_PCI */ + + if (pATEInfo->PeriodicTimer.State == FALSE) + { + /* + For rx statistics, we cancel pAd->Mlme.PeriodicTimer + and set pATEInfo->PeriodicTimer in stead of. + Now we recover it before we leave ATE mode. + */ + RTMPCancelTimer(&pATEInfo->PeriodicTimer, &Cancelled); + /* 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); + } + else + { + /* ATE periodic timer has been cancelled. */ + Status = NDIS_STATUS_FAILURE; + DBGPRINT_ERR(("Initialization of MLME periodic timer failed, Status[=0x%08x]\n", Status)); + + return Status; + } + +#ifdef RTMP_MAC_PCI + NICInitializeAdapter(pAd, TRUE); + + for (ring_index = 0; ring_index < RX_RING_SIZE; ring_index++) + { +#ifdef RT_BIG_ENDIAN + pDestRxD = (PRXD_STRUC) pAd->RxRing.Cell[ring_index].AllocVa; + RxD = *pDestRxD; + pRxD = &RxD; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + /* Point to Rx indexed rx ring descriptor */ + pRxD = (PRXD_STRUC) pAd->RxRing.Cell[ring_index].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 */ + } + + /* We should read EEPROM for all cases. */ + NICReadEEPROMParameters(pAd, NULL); + NICInitAsicFromEEPROM(pAd); + +#ifdef RT6352 + if (IS_RT6352(pAd)) + { +#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%lu)\n", SysRegValue)); + } + } + + RT6352_Restore_RF_BBP(pAd); +#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 */ + + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, TRUE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + /* TX 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) + { + ULONG SysRegValue; + + /* Check the gpio setting first */ + RTMP_SYS_IO_READ32(0xb0000060, &SysRegValue); + if ((SysRegValue & 0x100000) == 0x100000) + { + SysRegValue &= (~0x100000); + RTMP_SYS_IO_WRITE32(0xb0000060, SysRegValue); + DBGPRINT(RT_DEBUG_ERROR,("Change as Normal Mode(0x%lu)\n", SysRegValue)); + } + } + + RT6352_Init_ExtPA_ExtLNA(pAd, TRUE); +#endif /* defined(RT6352_EP_SUPPORT) || defined(RT6352_EL_SUPPORT) */ + } +#endif /* RT6352 */ + + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + + /* empty function */ + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + +#ifdef RTMP_INTERNAL_TX_ALC +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + if (pATEInfo->bAutoTxAlc == TRUE) + { + OS_SEM_LOCK(&(pATEInfo->TssiSemLock)); + RT635xTssiDcCalibration(pAd); + OS_SEM_UNLOCK(&(pATEInfo->TssiSemLock)); + + RT635xInitMcsPowerTable(pAd); + RT635xInitRfPaModeTable(pAd); + } + } +#endif /* RT6352 */ +#endif /* RTMP_INTERNAL_TX_ALC */ + + /* clear garbage interrupts */ + RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, 0xffffffff); + /* Enable Interrupt */ + RTMP_ASIC_INTERRUPT_ENABLE(pAd); +#endif /* RTMP_MAC_PCI */ + + +#ifdef CONFIG_AP_SUPPORT + /* restore RX_FILTR_CFG */ + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, APNORMAL); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + /* restore RX_FILTR_CFG due to that QA maybe set it to 0x3 */ + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); +#endif /* CONFIG_STA_SUPPORT */ + + /* Enable Tx */ + ATE_MAC_TX_ENABLE(pAd, MAC_SYS_CTRL, &MacData); + + /* Enable Tx, Rx DMA. */ + RtmpDmaEnable(pAd, 1); + + /* Enable Rx */ + ATE_MAC_RX_ENABLE(pAd, MAC_SYS_CTRL, &MacData); + +#ifdef RTMP_MAC_PCI +#ifdef CONFIG_AP_SUPPORT + APStartUp(pAd); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + RTMPStationStart(pAd); +#endif /* CONFIG_STA_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + + DBGPRINT(RT_DEBUG_TRACE, ("ATE : <=== %s\n", __FUNCTION__)); + return Status; +} + + +static NDIS_STATUS TXCARR( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 MacData=0; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + UCHAR BbpData = 0; + PATE_CHIP_STRUCT pChipStruct = pATEInfo->pChipStruct; + + DBGPRINT(RT_DEBUG_TRACE, ("ATE : ===> %s\n", __FUNCTION__)); + + pATEInfo->Mode = ATE_TXCARR; + + if (pChipStruct->bBBPStoreTXCARR == TRUE) + { + UINT32 bbp_index=0; + + /* Zero All BBP Value */ + for (bbp_index=0;bbp_indexbQATxStart == FALSE) + { + if ((!IS_RT3883(pAd)) && (!IS_RT3352(pAd)) && (!IS_RT5350(pAd)) && (!IS_RT3593(pAd))) + BbpSoftReset(pAd);/* Soft reset BBP. */ + + if (pATEInfo->TxMethod == TX_METHOD_1) + { + if (!IS_RT5592(pAd)) + { + /* store the original value of TX_PIN_CFG */ + RTMP_IO_READ32(pAd, TX_PIN_CFG, &(pATEInfo->Default_TX_PIN_CFG)); + + /* give TX_PIN_CFG(0x1328) a proper value. */ + if (pATEInfo->Channel <= 14) + { + /* G band */ + MacData = TXCONT_TX_PIN_CFG_G; + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, MacData); + } + else + { + /* A band */ + MacData = TXCONT_TX_PIN_CFG_A; + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, MacData); + } + } + + /* Carrier Test set BBP R22 bit6=1, bit[5~0]=0x01 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= 0xFFFFFF80; /* bit6, bit[5~0] */ + BbpData |= 0x00000041; /* set bit6=1, bit[5~0]=0x01 */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + } + else + { + /* Carrier Test set BBP R22 bit7=1, bit6=1, bit[5~0]=0x01 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= 0xFFFFFF00; /* clear bit7, bit6, bit[5~0] */ + BbpData |= 0x000000C1; /* set bit7=1, bit6=1, bit[5~0]=0x01 */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + + /* Set MAC_SYS_CTRL(0x1004) Continuous Tx Production Test (bit4) = 1. */ + ATE_MAC_TX_CTS_ENABLE(pAd, MAC_SYS_CTRL, &MacData); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("ATE : <=== %s\n", __FUNCTION__)); + return Status; +} + + +static NDIS_STATUS TXCONT( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 MacData=0; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; +#ifdef RTMP_MAC_PCI + UINT32 ring_index=0; + PTXD_STRUC pTxD = NULL; + PRTMP_TX_RING pTxRing = &pAd->TxRing[QID_AC_BE]; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD = NULL; + TXD_STRUC TxD; +#endif /* RT_BIG_ENDIAN */ +#endif /* RTMP_MAC_PCI */ + UCHAR BbpData = 0; + PATE_CHIP_STRUCT pChipStruct = pATEInfo->pChipStruct; + + DBGPRINT(RT_DEBUG_TRACE, ("ATE : ===> %s\n", __FUNCTION__)); + + pATEInfo->Mode = ATE_TXCONT; + + if (pATEInfo->bQATxStart == TRUE) + { + /* + set MAC_SYS_CTRL(0x1004) bit4(Continuous Tx Production Test) + and bit2(MAC TX enable) back to zero. + */ + ATE_MAC_TX_CTS_DISABLE(pAd, MAC_SYS_CTRL, &MacData); + ATE_MAC_TX_DISABLE(pAd, MAC_SYS_CTRL, &MacData); + + /* set BBP R22 bit7=0 */ + ATE_BBP_STOP_CTS_TX_MODE(pAd, BBP_R22, &BbpData); + } + else + { + if (pATEInfo->TxMethod == TX_METHOD_1) + { + if (!IS_RT5592(pAd)) + { + /* store the original value of TX_PIN_CFG */ + RTMP_IO_READ32(pAd, TX_PIN_CFG, &(pATEInfo->Default_TX_PIN_CFG)); + } + } + } + + if (pChipStruct->bBBPStoreTXCONT == TRUE) + { + UINT32 bbp_index=0; + + /* Zero All BBP Value */ + for(bbp_index=0;bbp_indexTxCount = 50; + + if ((!IS_RT3883(pAd)) && (!IS_RT3352(pAd)) && (!IS_RT5350(pAd)) && (!IS_RT3593(pAd))) + BbpSoftReset(pAd);/* Soft reset BBP. */ + + /* Abort Tx, RX DMA. */ + RtmpDmaEnable(pAd, 0); + +#ifdef RTMP_MAC_PCI + { + RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QID_AC_BE * 0x10, &pTxRing->TxDmaIdx); + pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx; + pTxRing->TxCpuIdx = pTxRing->TxDmaIdx; + RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * 0x10, pTxRing->TxCpuIdx); + } +#endif /* RTMP_MAC_PCI */ + + /* Do it after Tx/Rx DMA is aborted. */ + pATEInfo->TxDoneCount = 0; + + /* Only needed if we have to send some normal frames. */ + SetJapanFilter(pAd); + +#ifdef RTMP_MAC_PCI + for (ring_index = 0; (ring_index < TX_RING_SIZE-1) && (ring_index < pATEInfo->TxCount); ring_index++) + { + PNDIS_PACKET pPacket; + UINT32 TxIdx = pTxRing->TxCpuIdx; + +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; +#else + pDestTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif /* !RT_BIG_ENDIAN */ + + /* Clear current cell. */ + pPacket = pTxRing->Cell[TxIdx].pNdisPacket; + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + + /* Always assign pNdisPacket as NULL after clear */ + pTxRing->Cell[TxIdx].pNdisPacket = NULL; + + pPacket = pTxRing->Cell[TxIdx].pNextNdisPacket; + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + + /* Always assign pNextNdisPacket as NULL after clear */ + pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif /* RT_BIG_ENDIAN */ + + if (ATESetUpFrame(pAd, TxIdx) != 0) + return NDIS_STATUS_FAILURE; + + INC_RING_INDEX(pTxRing->TxCpuIdx, TX_RING_SIZE); + } + + ATESetUpFrame(pAd, pTxRing->TxCpuIdx); +#endif /* RTMP_MAC_PCI */ + + + /* Enable Tx */ + ATE_MAC_TX_ENABLE(pAd, MAC_SYS_CTRL, &MacData); + + /* Disable Rx */ + ATE_MAC_RX_DISABLE(pAd, MAC_SYS_CTRL, &MacData); + + /* Start Tx, Rx DMA. */ + RtmpDmaEnable(pAd, 1); + + +#ifdef RALINK_QA + if (pATEInfo->bQATxStart == TRUE) + { + pATEInfo->TxStatus = 1; + } +#endif /* RALINK_QA */ + +#ifdef RTMP_MAC_PCI + /* kick Tx Ring */ + RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * RINGREG_DIFF, pAd->TxRing[QID_AC_BE].TxCpuIdx); + + RtmpOsMsDelay(5); +#endif /* RTMP_MAC_PCI */ + + + if (pATEInfo->TxMethod == TX_METHOD_1) + { + if (!IS_RT5592(pAd)) + { + /* give TX_PIN_CFG(0x1328) a proper value. */ + if (pATEInfo->Channel <= 14) + { + /* G band */ + MacData = TXCONT_TX_PIN_CFG_G; + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, MacData); + } + else + { + /* A band */ + MacData = TXCONT_TX_PIN_CFG_A; + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, MacData); + } + } + + /* Cont. TX set BBP R22 bit7=1 */ + ATE_BBP_START_CTS_TX_MODE(pAd, BBP_R22, &BbpData); + +#ifdef RT5592EP_SUPPORT + /* enable continuous tx production test */ + if (pAd->chipCap.Priv == RT5592_TYPE_EP) + ATE_MAC_TX_CTS_ENABLE(pAd, MAC_SYS_CTRL, &MacData); +#endif /* RT5592EP_SUPPORT */ + } + else + { + /* Step 2: send more 50 packets then start Continuous Tx Mode. */ + /* Abort Tx, RX DMA. */ + RtmpDmaEnable(pAd, 0); + + /* Cont. TX set BBP R22 bit7=1 */ + ATE_BBP_START_CTS_TX_MODE(pAd, BBP_R22, &BbpData); + + pATEInfo->TxCount = 50; +#ifdef RTMP_MAC_PCI + { + RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QID_AC_BE * 0x10, &pTxRing->TxDmaIdx); + pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx; + pTxRing->TxCpuIdx = pTxRing->TxDmaIdx; + RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * 0x10, pTxRing->TxCpuIdx); + } +#endif /* RTMP_MAC_PCI */ + + pATEInfo->TxDoneCount = 0; + SetJapanFilter(pAd); + +#ifdef RTMP_MAC_PCI + for (ring_index = 0; (ring_index < TX_RING_SIZE-1) && (ring_index < pATEInfo->TxCount); ring_index++) + { + PNDIS_PACKET pPacket; + UINT32 TxIdx = pTxRing->TxCpuIdx; + +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; +#else + pDestTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif /* !RT_BIG_ENDIAN */ + /* clear current cell */ + pPacket = pTxRing->Cell[TxIdx].pNdisPacket; + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + + /* Always assign pNdisPacket as NULL after clear. */ + pTxRing->Cell[TxIdx].pNdisPacket = NULL; + + pPacket = pTxRing->Cell[TxIdx].pNextNdisPacket; + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + + /* Always assign pNextNdisPacket as NULL after clear. */ + pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif /* RT_BIG_ENDIAN */ + + if (ATESetUpFrame(pAd, TxIdx) != 0) + return NDIS_STATUS_FAILURE; + + INC_RING_INDEX(pTxRing->TxCpuIdx, TX_RING_SIZE); + } + + ATESetUpFrame(pAd, pTxRing->TxCpuIdx); +#endif /* RTMP_MAC_PCI */ + + + /* Enable Tx */ + ATE_MAC_TX_ENABLE(pAd, MAC_SYS_CTRL, &MacData); + + /* Disable Rx */ + ATE_MAC_RX_DISABLE(pAd, MAC_SYS_CTRL, &MacData); + + /* Start Tx, Rx DMA. */ + RtmpDmaEnable(pAd, 1); + +#ifdef RALINK_QA + if (pATEInfo->bQATxStart == TRUE) + { + pATEInfo->TxStatus = 1; + } +#endif /* RALINK_QA */ + +#ifdef RTMP_MAC_PCI + /* kick Tx Ring */ + RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * RINGREG_DIFF, pAd->TxRing[QID_AC_BE].TxCpuIdx); +#endif /* RTMP_MAC_PCI */ + + RTMPusecDelay(500); + + /* enable continuous tx production test */ + ATE_MAC_TX_CTS_ENABLE(pAd, MAC_SYS_CTRL, &MacData); + } + + DBGPRINT(RT_DEBUG_TRACE, ("ATE : <=== %s\n", __FUNCTION__)); + return Status; +} + + +static NDIS_STATUS TXCARS( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 MacData=0; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + UCHAR BbpData = 0; + PATE_CHIP_STRUCT pChipStruct = pATEInfo->pChipStruct; + + DBGPRINT(RT_DEBUG_TRACE, ("ATE : ===> %s\n", __FUNCTION__)); + + pATEInfo->Mode = ATE_TXCARRSUPP; + + if (pChipStruct->bBBPStoreTXCARRSUPP == TRUE) + { + UINT32 bbp_index=0; + + /* Zero All BBP Value */ + for (bbp_index=0;bbp_indexbQATxStart == FALSE) + { +#if !defined(RT3883) && !defined(RT3593) + if (!IS_RT3883(pAd) && !IS_RT3593(pAd)) + { + /* RT3883 and RT3593 do not need BbpSoftReset() */ + /* Soft reset BBP. */ + BbpSoftReset(pAd); + } +#endif /* !defined(RT3883) && !defined(RT3593) */ + + if (pATEInfo->TxMethod == TX_METHOD_1) + { + if (!IS_RT5592(pAd)) + { + /* store the original value of TX_PIN_CFG */ + RTMP_IO_READ32(pAd, TX_PIN_CFG, &(pATEInfo->Default_TX_PIN_CFG)); + + /* give TX_PIN_CFG(0x1328) a proper value. */ + if (pATEInfo->Channel <= 14) + { + /* G band */ + MacData = TXCONT_TX_PIN_CFG_G; + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, MacData); + } + else + { + /* A band */ + MacData = TXCONT_TX_PIN_CFG_A; + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, MacData); + } + } + +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + /* Carrier Suppression set BBP R21 bit4=1 (Enable Continuous Tx Mode) */ + BbpData = 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BbpData); + BbpData = 0x00; + } +#endif /* RT6352 */ + + /* Carrier Suppression set BBP R22 bit7=1 (Enable Continuous Tx Mode) */ + ATE_BBP_START_CTS_TX_MODE(pAd, BBP_R22, &BbpData); + + /* Carrier Suppression set BBP R24 bit0=1 (TX continuously send out 5.5MHZ sin save) */ + ATE_BBP_CTS_TX_SIN_WAVE_ENABLE(pAd, BBP_R24, &BbpData); + } + else + { + /* Carrier Suppression set BBP R22 bit7=1 (Enable Continuous Tx Mode) */ + ATE_BBP_START_CTS_TX_MODE(pAd, BBP_R22, &BbpData); + + /* Carrier Suppression set BBP R24 bit0=1 (TX continuously send out 5.5MHZ sin save) */ + ATE_BBP_CTS_TX_SIN_WAVE_ENABLE(pAd, BBP_R24, &BbpData); + + /* Set MAC_SYS_CTRL(0x1004) Continuous Tx Production Test (bit4) = 1. */ + ATE_MAC_TX_CTS_ENABLE(pAd, MAC_SYS_CTRL, &MacData); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("ATE : <=== %s\n", __FUNCTION__)); + return Status; +} + + +static NDIS_STATUS TXFRAME( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 MacData=0; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; +#ifdef RTMP_MAC_PCI + UINT32 ring_index=0; + PRTMP_TX_RING pTxRing = &pAd->TxRing[QID_AC_BE]; + PTXD_STRUC pTxD = NULL; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD = NULL; + TXD_STRUC TxD; +#endif /* RT_BIG_ENDIAN */ +#endif /* RTMP_MAC_PCI */ + UCHAR BbpData = 0; + STRING IPGStr[8] = {0}; +#ifdef RTMP_INTERNAL_TX_ALC +#if defined(RT3350) || defined(RT3352) + UCHAR RFValue, BBP49Value; + CHAR ChannelPower = pATEInfo->TxPower0; + CHAR *TssiRefPerChannel = pATEInfo->TssiRefPerChannel; + UCHAR CurrentChannel = pATEInfo->Channel; +#endif /* defined(RT3350) || defined(RT3352) */ +#endif /* RTMP_INTERNAL_TX_ALC */ +#ifdef RTMP_TEMPERATURE_COMPENSATION +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + +#ifdef RTMP_INTERNAL_TX_ALC +#if defined(RT3350) || defined(RT3352) + if (pATEInfo->bTSSICalbrEnableG == TRUE) + { + if ((!IS_RT3350(pAd)) && (!IS_RT3352(pAd))) + { + DBGPRINT_ERR(("Not support TSSI calibration since not 3350/3352 chip!!!\n")); + Status = NDIS_STATUS_FAILURE; + + return Status; + } + + /* Internal TSSI 0 */ + RFValue = (0x3 | 0x0 << 2 | 0x3 << 4); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R27, RFValue); + + RFValue = (0x3 | 0x0 << 2); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R28, RFValue); + + /* set BBP R49[7] = 1 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpData); + BBP49Value = BbpData; + BbpData |= 0x80; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R49, BbpData); + } +#endif /* defined(RT3350) || defined(RT3352) */ +#endif /* RTMP_INTERNAL_TX_ALC */ + +#ifdef RTMP_TEMPERATURE_COMPENSATION +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + + DBGPRINT(RT_DEBUG_TRACE, ("ATE : ===> %s(Count=%u)\n", __FUNCTION__, pATEInfo->TxCount)); + pATEInfo->Mode |= ATE_TXFRAME; + + if (pATEInfo->bQATxStart == FALSE) + { + + /* set IPG to sync tx power with QA tools */ + /* default value of IPG is 200 */ + snprintf(IPGStr, sizeof(IPGStr), "%u", pATEInfo->IPG); + DBGPRINT(RT_DEBUG_TRACE, ("IPGstr=%s\n", IPGStr)); + Set_ATE_IPG_Proc(pAd, IPGStr); + } + +#ifdef RTMP_MAC_PCI + /* Default value in BBP R22 is 0x0. */ + ATE_BBP_RESET_TX_MODE(pAd, BBP_R22, &BbpData); + + + if (!(IS_RT3883(pAd) || IS_RT3352(pAd) || IS_RT5350(pAd) || IS_RT3593(pAd) || IS_RT6352(pAd))) + { + /* Soft reset BBP. */ + BbpSoftReset(pAd); + } + + /* clear bit4 to stop continuous Tx production test */ + ATE_MAC_TX_CTS_DISABLE(pAd, MAC_SYS_CTRL, &MacData); + + /* Abort Tx, Rx DMA. */ + RtmpDmaEnable(pAd, 0); + + { + RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QID_AC_BE * RINGREG_DIFF, &pTxRing->TxDmaIdx); + pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx; + pTxRing->TxCpuIdx = pTxRing->TxDmaIdx; + RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * RINGREG_DIFF, pTxRing->TxCpuIdx); + } + + pATEInfo->TxDoneCount = 0; + + SetJapanFilter(pAd); + + for (ring_index = 0; (ring_index < TX_RING_SIZE-1) && (ring_index < pATEInfo->TxCount); ring_index++) + { + PNDIS_PACKET pPacket; + UINT32 TxIdx = pTxRing->TxCpuIdx; + +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; +#else + pDestTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif /* !RT_BIG_ENDIAN */ + /* Clear current cell. */ + pPacket = pTxRing->Cell[TxIdx].pNdisPacket; + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + + /* Always assign pNdisPacket as NULL after clear */ + pTxRing->Cell[TxIdx].pNdisPacket = NULL; + + pPacket = pTxRing->Cell[TxIdx].pNextNdisPacket; + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + + /* Always assign pNextNdisPacket as NULL after clear */ + pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif /* RT_BIG_ENDIAN */ + + if (ATESetUpFrame(pAd, TxIdx) != 0) + return NDIS_STATUS_FAILURE; + + INC_RING_INDEX(pTxRing->TxCpuIdx, TX_RING_SIZE); + + } + + ATESetUpFrame(pAd, pTxRing->TxCpuIdx); + + /* Start Tx, Rx DMA. */ + RtmpDmaEnable(pAd, 1); + + /* Enable Tx */ + ATE_MAC_TX_ENABLE(pAd, MAC_SYS_CTRL, &MacData); +#endif /* RTMP_MAC_PCI */ + + +#ifdef RALINK_QA + /* add this for LoopBack mode */ + if (pATEInfo->bQARxStart == FALSE) + { +#ifdef TXBF_SUPPORT + /* Enable Rx if Sending Sounding. Otherwise Disable */ + if (pATEInfo->txSoundingMode != 0) + { + ATE_MAC_RX_ENABLE(pAd, MAC_SYS_CTRL, &MacData); + } + else +#endif /* TXBF_SUPPORT */ + { + /* Disable Rx */ + ATE_MAC_RX_DISABLE(pAd, MAC_SYS_CTRL, &MacData); + } + } + + if (pATEInfo->bQATxStart == TRUE) + { + pATEInfo->TxStatus = 1; + } +#else +#ifdef TXBF_SUPPORT + /* Enable Rx if Sending Sounding. Otherwise Disable */ + if (pATEInfo->txSoundingMode != 0) + { + ATE_MAC_RX_ENABLE(pAd, MAC_SYS_CTRL, &MacData); + } + else +#endif /* TXBF_SUPPORT */ + { + /* Disable Rx */ + ATE_MAC_RX_DISABLE(pAd, MAC_SYS_CTRL, &MacData); + } +#endif /* RALINK_QA */ + +#ifdef RTMP_MAC_PCI + RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QID_AC_BE * RINGREG_DIFF, &pAd->TxRing[QID_AC_BE].TxDmaIdx); + /* kick Tx Ring */ + RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * RINGREG_DIFF, pAd->TxRing[QID_AC_BE].TxCpuIdx); + + pAd->RalinkCounters.KickTxCount++; +#endif /* RTMP_MAC_PCI */ + + +#ifdef RTMP_INTERNAL_TX_ALC +#if defined(RT3350) || defined(RT3352) + if (pATEInfo->bTSSICalbrEnableG == TRUE) + { + if ((IS_RT3350(pAd)) || (IS_RT3352(pAd))) + { + if ((pATEInfo->TxWI.MCS == 7) + && (pATEInfo->TxWI.BW == BW_20) && (pATEInfo->TxAntennaSel == 1)) + { + if (pATEInfo->Channel == 7) + { + /* step 1: get calibrated channel 7 TSSI reading as reference */ + RtmpOsMsDelay(500); + DBGPRINT(RT_DEBUG_TRACE, ("Channel %d, Calibrated Tx.Power0= 0x%04x\n", CurrentChannel, ChannelPower)); + + /* read BBP R49[4:0] and write to EEPROM 0x6E */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpData); + DBGPRINT(RT_DEBUG_TRACE, ("BBP R49 = 0x%02x\n", BbpData)); + BbpData &= 0x1f; + TssiRefPerChannel[CurrentChannel-1] = BbpData; + DBGPRINT(RT_DEBUG_TRACE, ("TSSI = 0x%02x\n", TssiRefPerChannel[CurrentChannel-1])); + } + + /* step 2: calibrate channel 1 and 13 TSSI delta values */ + else if (pATEInfo->Channel == 1) + { + /* Channel 1 */ + RtmpOsMsDelay(500); + DBGPRINT(RT_DEBUG_TRACE, ("Channel %d, Calibrated Tx.Power0= 0x%04x\n", CurrentChannel, ChannelPower)); + + /* read BBP R49[4:0] */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpData); + DBGPRINT(RT_DEBUG_TRACE, ("BBP R49 = 0x%02x\n", BbpData)); + BbpData &= 0x1f; + TssiRefPerChannel[CurrentChannel-1] = BbpData; + DBGPRINT(RT_DEBUG_TRACE, ("TSSI = 0x%02x\n", TssiRefPerChannel[CurrentChannel-1])); + } + else if (pATEInfo->Channel == 13) + { + /* Channel 13 */ + RtmpOsMsDelay(500); + DBGPRINT(RT_DEBUG_TRACE, ("Channel %d, Calibrated Tx.Power0= 0x%04x\n", CurrentChannel, ChannelPower)); + + /* read BBP R49[4:0] */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpData); + DBGPRINT(RT_DEBUG_TRACE, ("BBP R49 = 0x%02x\n", BbpData)); + BbpData &= 0x1f; + TssiRefPerChannel[CurrentChannel-1] = BbpData; + DBGPRINT(RT_DEBUG_TRACE, ("TSSI = 0x%02x\n", TssiRefPerChannel[CurrentChannel-1])); + } + else + { + DBGPRINT(RT_DEBUG_OFF, ("Channel %d, Calibrated Tx.Power0= 0x%04x\n", CurrentChannel, ChannelPower)); + } + } + } + } +#endif /* defined(RT3350) || defined(RT3352) */ +#endif /* RTMP_INTERNAL_TX_ALC */ + +#ifdef RTMP_TEMPERATURE_COMPENSATION +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + + DBGPRINT(RT_DEBUG_TRACE, ("ATE : <=== %s\n", __FUNCTION__)); + return Status; +} + + +static NDIS_STATUS RXFRAME( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 MacData=0; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + UCHAR BbpData = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("ATE : ===> %s\n", __FUNCTION__)); + + /* Disable Rx of MAC block */ + ATE_MAC_RX_DISABLE(pAd, MAC_SYS_CTRL, &MacData); + + /* Default value in BBP R22 is 0x0. */ + ATE_BBP_RESET_TX_MODE(pAd, BBP_R22, &BbpData); + +#if defined (RT3883) || defined (RT3352) || defined (RT5350) + if (IS_RT3883(pAd) || IS_RT3352(pAd) || IS_RT5350(pAd)) + { + if (pATEInfo->TxWI.BW == BW_20) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R103, 0xC0); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R103, 0x00); + } + } +#endif /* defined (RT3883) || defined (RT3352) || defined (RT5350) */ + + /* Clear bit4 to stop continuous Tx production test. */ + ATE_MAC_TX_CTS_DISABLE(pAd, MAC_SYS_CTRL, &MacData); + + pATEInfo->Mode |= ATE_RXFRAME; + + + /* Disable Tx of MAC block. */ + ATE_MAC_TX_DISABLE(pAd, MAC_SYS_CTRL, &MacData); + + + /* Enable Rx of MAC block. */ + ATE_MAC_RX_ENABLE(pAd, MAC_SYS_CTRL, &MacData); + + + + if (pATEInfo->bQAEnabled == FALSE) + { + if (IS_RT6352(pAd) && (pAd->CommonCfg.Chip_VerID > 1) && (pAd->CommonCfg.Chip_E_Number == 2)) + { + UCHAR RFValue; + + if (pATEInfo->RxAntennaSel != 0) /* 1R */ + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R31, 0x08); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R31, 0x48); + } + + RT635xReadRFRegister(pAd, RF_BANK0, RF_R28, &RFValue); + if ((pATEInfo->Channel == 11) && (pATEInfo->TxWI.BW == BW_40)) + RFValue |= 0x4; + else + RFValue &= (~0x4); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R28, RFValue); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("ATE : <=== %s\n", __FUNCTION__)); + return Status; +} + + +/* +========================================================================== + Description: + Set ATE operation mode to + 0. ATESTART = Start/Reset ATE Mode + 1. ATESTOP = Stop ATE Mode + 2. TXCARR = Transmit Carrier + 3. TXCONT = Continuous Transmit + 4. TXFRAME = Transmit Frames + 5. RXFRAME = Receive Frames +#ifdef RALINK_QA + 6. TXSTOP = Stop Any Type of Transmition + 7. RXSTOP = Stop Receiving Frames +#endif + + Return: + NDIS_STATUS_SUCCESS if all parameters are OK. +========================================================================== +*/ +static NDIS_STATUS ATECmdHandler( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s\n", __FUNCTION__)); + +#ifdef CONFIG_RT2880_ATE_CMD_NEW + if (!strcmp(arg, "ATESTART")) + { + /* Enter/Reset ATE mode and set Tx/Rx Idle */ + Status = ATESTART(pAd); + } + else if (!strcmp(arg, "ATESTOP")) + { + /* Leave ATE mode */ + Status = ATESTOP(pAd); + } +#else + if (!strcmp(arg, "APSTOP")) + { + Status = ATESTART(pAd); + } + else if (!strcmp(arg, "APSTART")) + { + Status = ATESTOP(pAd); + } +#endif + else if (!strcmp(arg, "TXCARR")) + { +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + /* Set ATE Mode in advance for RT6352ATEAsicSetTxRxPath() */ + pAd->ate.Mode &= ATE_RXSTOP; + pAd->ate.Mode |= ATE_TXCARR; + } +#endif /* RT6352 */ + ATEAsicSwitchChannel(pAd); + /* AsicLockChannel() is empty function so far in fact */ + AsicLockChannel(pAd, pATEInfo->Channel); + RtmpOsMsDelay(5); + + Status = TXCARR(pAd); + } + else if (!strcmp(arg, "TXCARS")) + { +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + /* Set ATE Mode in advance for RT6352ATEAsicSetTxRxPath() */ + pAd->ate.Mode &= ATE_RXSTOP; + pAd->ate.Mode |= ATE_TXCARRSUPP; + } +#endif /* RT6352 */ + ATEAsicSwitchChannel(pAd); + /* AsicLockChannel() is empty function so far in fact */ + AsicLockChannel(pAd, pATEInfo->Channel); + RtmpOsMsDelay(5); + + Status = TXCARS(pAd); + } + else if (!strcmp(arg, "TXCONT")) + { +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + /* Set ATE Mode in advance for RT6352ATEAsicSetTxRxPath() */ + pAd->ate.Mode &= ATE_RXSTOP; + pAd->ate.Mode |= ATE_TXCONT; + } +#endif /* RT6352 */ + ATEAsicSwitchChannel(pAd); + /* AsicLockChannel() is empty function so far in fact */ + AsicLockChannel(pAd, pATEInfo->Channel); + RtmpOsMsDelay(5); + + Status = TXCONT(pAd); + } + else if (!strcmp(arg, "TXFRAME")) + { +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + /* Set ATE Mode in advance for RT6352ATEAsicSetTxRxPath() */ + pAd->ate.Mode &= ATE_RXSTOP; + pAd->ate.Mode |= ATE_TXFRAME; + } +#endif /* RT6352 */ + ATEAsicSwitchChannel(pAd); + /* AsicLockChannel() is empty function so far in fact */ + AsicLockChannel(pAd, pATEInfo->Channel); + RtmpOsMsDelay(5); + + Status = TXFRAME(pAd); + } +#ifdef RT6352 + else if (!strcmp(arg, "TXAPPLY")) + { + if (IS_RT6352(pAd)) + { + /* Set ATE Mode in advance for RT6352ATEAsicSetTxRxPath() */ + pAd->ate.Mode &= ATE_RXSTOP; + pAd->ate.Mode |= ATE_TXFRAME; + } + ATEAsicSwitchChannel(pAd); + /* AsicLockChannel() is empty function so far in fact */ + AsicLockChannel(pAd, pATEInfo->Channel); + RtmpOsMsDelay(5); + } + else if (!strcmp(arg, "RXAPPLY")) + { + if (IS_RT6352(pAd)) + { + /* Set ATE Mode in advance for RT6352ATEAsicSetTxRxPath() */ + pAd->ate.Mode &= ATE_TXSTOP; + pAd->ate.Mode |= ATE_RXFRAME; + } + ATEAsicSwitchChannel(pAd); + /* AsicLockChannel() is empty function so far in fact */ + AsicLockChannel(pAd, pATEInfo->Channel); + RTMPusecDelay(5); + } +#endif /* RT6352 */ + else if (!strcmp(arg, "RXFRAME")) + { +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + /* Set ATE Mode in advance for RT6352ATEAsicSetTxRxPath() */ + pAd->ate.Mode &= ATE_TXSTOP; + pAd->ate.Mode |= ATE_RXFRAME; + } +#endif /* RT6352 */ + ATEAsicSwitchChannel(pAd); + /* AsicLockChannel() is empty function so far in fact */ + AsicLockChannel(pAd, pATEInfo->Channel); + RTMPusecDelay(5); + + Status = RXFRAME(pAd); + } +#ifdef RALINK_QA + /* Enter ATE mode and set Tx/Rx Idle */ + else if (!strcmp(arg, "TXSTOP")) + { + Status = TXSTOP(pAd); + } + else if (!strcmp(arg, "RXSTOP")) + { + Status = RXSTOP(pAd); + } +#endif /* RALINK_QA */ + else + { + DBGPRINT_ERR(("ATE : Invalid arg in %s!\n", __FUNCTION__)); + Status = NDIS_STATUS_INVALID_DATA; + } + RtmpOsMsDelay(5); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s\n", __FUNCTION__)); + return Status; +} + + +INT Set_ATE_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + /* Handle ATEACTIVE and ATEPASSIVE commands as a special case */ + if (!strcmp(arg, "ATEACTIVE")) + { + pATEInfo->PassiveMode = FALSE; + return TRUE; + } + + if (!strcmp(arg, "ATEPASSIVE")) + { + pATEInfo->PassiveMode = TRUE; + return TRUE; + } + + /* Disallow all other ATE commands in passive mode */ + if (pATEInfo->PassiveMode) + return TRUE; + + if (ATECmdHandler(pAd, arg) == NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_Proc Success\n")); + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + return TRUE; + } + else + { + DBGPRINT_ERR(("Set_ATE_Proc Failed\n")); + return FALSE; + } +} + + +/* +========================================================================== + Description: + Set ATE ADDR1=DA for TxFrame(AP : To DS = 0 ; From DS = 1) + or + Set ATE ADDR3=DA for TxFrame(STA : To DS = 1 ; From DS = 0) + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_DA_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + PSTRING value; + INT octet; + + /* Mac address acceptable format 01:02:03:04:05:06 length 17 */ + if (strlen(arg) != 17) + return FALSE; + + for (octet = 0, value = rstrtok(arg, ":"); value; value = rstrtok(NULL, ":")) + { + /* sanity check */ + if ((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1)))) + { + return FALSE; + } +#ifdef CONFIG_AP_SUPPORT + AtoH(value, &pATEInfo->Addr1[octet++], 1); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + AtoH(value, &pATEInfo->Addr3[octet++], 1); +#endif /* CONFIG_STA_SUPPORT */ + } + + /* sanity check */ + if (octet != MAC_ADDR_LEN) + { + return FALSE; + } +#ifdef CONFIG_AP_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_DA_Proc (DA = %02x:%02x:%02x:%02x:%02x:%02x)\n", + pATEInfo->Addr1[0], pATEInfo->Addr1[1], pATEInfo->Addr1[2], pATEInfo->Addr1[3], + pATEInfo->Addr1[4], pATEInfo->Addr1[5])); + +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_DA_Proc (DA = %02x:%02x:%02x:%02x:%02x:%02x)\n", + pATEInfo->Addr3[0], pATEInfo->Addr3[1], pATEInfo->Addr3[2], pATEInfo->Addr3[3], + pATEInfo->Addr3[4], pATEInfo->Addr3[5])); +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_DA_Proc Success\n")); + + return TRUE; +} + + +/* +========================================================================== + Description: + Set ATE ADDR3=SA for TxFrame(AP : To DS = 0 ; From DS = 1) + or + Set ATE ADDR2=SA for TxFrame(STA : To DS = 1 ; From DS = 0) + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_SA_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + PSTRING value; + INT octet; + + /* Mac address acceptable format 01:02:03:04:05:06 length 17 */ + if (strlen(arg) != 17) + return FALSE; + + for (octet=0, value = rstrtok(arg, ":"); value; value = rstrtok(NULL, ":")) + { + /* sanity check */ + if ((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1)))) + { + return FALSE; + } +#ifdef CONFIG_AP_SUPPORT + AtoH(value, &pATEInfo->Addr3[octet++], 1); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + AtoH(value, &pATEInfo->Addr2[octet++], 1); +#endif /* CONFIG_STA_SUPPORT */ + } + + /* sanity check */ + if (octet != MAC_ADDR_LEN) + { + return FALSE; + } +#ifdef CONFIG_AP_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_SA_Proc (SA = %02x:%02x:%02x:%02x:%02x:%02x)\n", + pATEInfo->Addr3[0], pATEInfo->Addr3[1], pATEInfo->Addr3[2], pATEInfo->Addr3[3], + pATEInfo->Addr3[4], pATEInfo->Addr3[5])); +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_SA_Proc (SA = %02x:%02x:%02x:%02x:%02x:%02x)\n", + pATEInfo->Addr2[0], pATEInfo->Addr2[1], pATEInfo->Addr2[2], pATEInfo->Addr2[3], + pATEInfo->Addr2[4], pATEInfo->Addr2[5])); +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_SA_Proc Success\n")); + + return TRUE; +} + + +/* +========================================================================== + Description: + Set ATE ADDR2=BSSID for TxFrame(AP : To DS = 0 ; From DS = 1) + or + Set ATE ADDR1=BSSID for TxFrame(STA : To DS = 1 ; From DS = 0) + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_BSSID_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + PSTRING value; + INT octet; + + /* Mac address acceptable format 01:02:03:04:05:06 length 17 */ + if (strlen(arg) != 17) + return FALSE; + + for (octet=0, value = rstrtok(arg, ":"); value; value = rstrtok(NULL, ":")) + { + /* sanity check */ + if ((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1)))) + { + return FALSE; + } +#ifdef CONFIG_AP_SUPPORT + AtoH(value, &pATEInfo->Addr2[octet++], 1); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + AtoH(value, &pATEInfo->Addr1[octet++], 1); +#endif /* CONFIG_STA_SUPPORT */ + } + + /* sanity check */ + if (octet != MAC_ADDR_LEN) + { + return FALSE; + } +#ifdef CONFIG_AP_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_BSSID_Proc (BSSID = %02x:%02x:%02x:%02x:%02x:%02x)\n", + pATEInfo->Addr2[0], pATEInfo->Addr2[1], pATEInfo->Addr2[2], pATEInfo->Addr2[3], + pATEInfo->Addr2[4], pATEInfo->Addr2[5])); + +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_BSSID_Proc (BSSID = %02x:%02x:%02x:%02x:%02x:%02x)\n", + pATEInfo->Addr1[0], pATEInfo->Addr1[1], pATEInfo->Addr1[2], pATEInfo->Addr1[3], + pATEInfo->Addr1[4], pATEInfo->Addr1[5])); +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_BSSID_Proc Success\n")); + + return TRUE; +} + + + + +/* +========================================================================== + Description: + Set ATE Tx Channel + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_CHANNEL_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR channel; + + + channel = simple_strtol(arg, 0, 10); + + /* to allow A band channel : ((channel < 1) || (channel > 14)) */ + if ((channel < 1) || (channel > 216)) + { + DBGPRINT_ERR(("Set_ATE_CHANNEL_Proc::Out of range, it should be in range of 1~14.\n")); + return FALSE; + } + + pATEInfo->Channel = channel; + + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_CHANNEL_Proc (ATE Channel = %d)\n", pATEInfo->Channel)); + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_CHANNEL_Proc Success\n")); + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +/* +========================================================================== + Description: + Initialize the channel - set the power and switch to selected channel + 0 => use current value + else set channel to specified channel + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_INIT_CHAN_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + int index; + int value; + + /* Get channel parameter */ + value = simple_strtol(arg, 0, 10); + + if (value<0 || value>216) + { + DBGPRINT_ERR(("Set_ATE_INIT_CHAN_Proc::Channel out of range\n")); + return FALSE; + } + + if (value != 0) + pATEInfo->Channel = value; + + for (index=0; indexChannel == pAd->TxPower[index].Channel) + { + pATEInfo->TxPower0 = pAd->TxPower[index].Power; + pATEInfo->TxPower1 = pAd->TxPower[index].Power2; +#ifdef DOT11N_SS3_SUPPORT + if (IS_RT2883(pAd) || IS_RT3593(pAd) || IS_RT3883(pAd)) + pATEInfo->TxPower2 = pAd->TxPower[index].Power3; +#endif /* DOT11N_SS3_SUPPORT */ + break; + } + } + + if (index == MAX_NUM_OF_CHANNELS) + { + DBGPRINT_ERR(("Set_ATE_INIT_CHAN_Proc::Channel not found\n")); + return FALSE; + } + + /* Force non-QATool mode */ + pATEInfo->bQATxStart = pATEInfo->bQARxStart = FALSE; + + ATETxPwrHandler(pAd, 0); + ATETxPwrHandler(pAd, 1); +#ifdef DOT11N_SS3_SUPPORT + ATETxPwrHandler(pAd, 2); +#endif /* DOT11N_SS3_SUPPORT */ + +#if defined(RT2883) || defined(RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + { + ATEAsicSwitchChannel(pAd); + } +#endif /* defined(RT2883) || defined(RT3883) */ + + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_INIT_CHAN_Proc Success\n")); + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +/* +========================================================================== + Description: + Set ATE Tx Power + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +static INT ATESetAntennaTxPower( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg, + IN INT Antenna) + +{ + PATE_INFO pATEInfo = &(pAd->ate); + CHAR TxPower; + INT index, maximun_index; + + pATEInfo = &(pAd->ate); + TxPower = simple_strtol(arg, 0, 10); + index = Antenna; + maximun_index = pAd->Antenna.field.TxPath - 1; + + if ((index < 0) || (index > maximun_index)) + { + DBGPRINT_ERR(("No such antenna! The range is 0~%d.\n", maximun_index)); + return FALSE; + } + + if (pATEInfo->Channel <= 14) /* 2.4 GHz */ + { +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + if ((TxPower > 47 /* 0x2F */) || (TxPower < 0)) + { + DBGPRINT_ERR(("Set_ATE_TX_POWER%d_Proc::Out of range! (Value=%d)\n", index, TxPower)); + DBGPRINT_ERR(("TxPower range is 0~47 in G band.\n")); + return FALSE; + } + } + else +#endif /* RT6352 */ + if (!IS_RT3390(pAd)) + { + if ((TxPower > 31) || (TxPower < 0)) + { + DBGPRINT_ERR(("Set_ATE_TX_POWER%d_Proc::Out of range! (Value=%d)\n", index, TxPower)); + DBGPRINT_ERR(("TxPower range is 0~31 in G band.\n")); + return FALSE; + } + } + } + else /* 5.5 GHz */ + { + if ((TxPower > (pATEInfo->MaxTxPowerBandA)) || (TxPower < (pATEInfo->MinTxPowerBandA))) + { + DBGPRINT_ERR(("Set_ATE_TX_POWER%d_Proc::Out of range! (Value=%d)\n", index, TxPower)); + DBGPRINT_ERR(("TxPower range is %d~%d in A band.\n", pATEInfo->MinTxPowerBandA, pATEInfo->MaxTxPowerBandA)); + return FALSE; + } + } + + switch (index) + { + case 0: + pATEInfo->TxPower0 = TxPower; + break; + case 1: + pATEInfo->TxPower1 = TxPower; + break; +#ifdef DOT11N_SS3_SUPPORT + case 2: + pATEInfo->TxPower2 = TxPower; + break; +#endif /* DOT11N_SS3_SUPPORT */ + default: + return FALSE; + } + + ATETxPwrHandler(pAd, index); + +#if defined(RT2883) || defined(RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + { + ATEAsicSwitchChannel(pAd); + } +#endif /* defined(RT2883) || defined(RT3883) */ + + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_POWER%d_Proc Success\n", index)); + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +/* +========================================================================== + Description: + Set ATE Tx Power0 + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_TX_POWER0_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT ret; + + ret = ATESetAntennaTxPower(pAd, arg, 0); + return ret; +} + + +/* +========================================================================== + Description: + Set ATE Tx Power1 + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_TX_POWER1_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT ret; + + ret = ATESetAntennaTxPower(pAd, arg, 1); + return ret; +} + + +#ifdef DOT11N_SS3_SUPPORT +/* +========================================================================== + Description: + Set ATE Tx Power2 + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_TX_POWER2_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT ret; + + ret = ATESetAntennaTxPower(pAd, arg, 2); + return ret; +} +#endif /* DOT11N_SS3_SUPPORT */ + + +/* +========================================================================== + Description: + Set ATE Tx Antenna + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_TX_Antenna_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + CHAR value; + INT maximun_index = pAd->Antenna.field.TxPath; + + value = simple_strtol(arg, 0, 10); + + if ((value > maximun_index) || (value < 0)) + { + DBGPRINT_ERR(("Set_ATE_TX_Antenna_Proc::Out of range (Value=%d)\n", value)); + DBGPRINT_ERR(("Set_ATE_TX_Antenna_Proc::The range is 0~%d\n", maximun_index)); + + return FALSE; + } + + pATEInfo->TxAntennaSel = value; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_Antenna_Proc (Antenna = %d)\n", pATEInfo->TxAntennaSel)); + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_Antenna_Proc Success\n")); + + /* calibration power unbalance issues */ + ATEAsicSwitchChannel(pAd); + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +/* +========================================================================== + Description: + Set ATE Rx Antenna + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_RX_Antenna_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + CHAR value; + INT maximun_index = pAd->Antenna.field.RxPath; + + value = simple_strtol(arg, 0, 10); + + if ((value > maximun_index) || (value < 0)) + { + DBGPRINT_ERR(("Set_ATE_RX_Antenna_Proc::Out of range (Value=%d)\n", value)); + DBGPRINT_ERR(("Set_ATE_RX_Antenna_Proc::The range is 0~%d\n", maximun_index)); + + return FALSE; + } + + pATEInfo->RxAntennaSel = value; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_RX_Antenna_Proc (Antenna = %d)\n", pATEInfo->RxAntennaSel)); + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_RX_Antenna_Proc Success\n")); + + /* calibration power unbalance issues */ + ATEAsicSwitchChannel(pAd); + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +VOID DefaultATEAsicExtraPowerOverMAC( + 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); + + if (IS_RT5392(pAd)) + { + /* 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_TRACE, ("Offset =0x13D8, TxPwr = 0x%08X, ", (UINT)ExtraPwrOverTxPwrCfg8)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("Offset = 0x13D4, TxPwr = 0x%08X, Offset = 0x13DC, TxPwr = 0x%08X\n", + (UINT)ExtraPwrOverTxPwrCfg7, + (UINT)ExtraPwrOverTxPwrCfg9)); +} + + +VOID ATEAsicExtraPowerOverMAC( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + if (pATEInfo->pChipStruct->AsicExtraPowerOverMAC!= NULL) + pATEInfo->pChipStruct->AsicExtraPowerOverMAC(pAd); + + return; +} + + +#ifdef RT3350 +/* +========================================================================== + Description: + Set ATE PA bias to improve EVM + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_PA_Bias_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR PABias = 0; + UCHAR RFValue; + + PABias = simple_strtol(arg, 0, 10); + + if (PABias >= 16) + { + DBGPRINT_ERR(("Set_ATE_PA_Bias_Proc::Out of range, it should be in range of 0~15.\n")); + return FALSE; + } + + pATEInfo->PABias = PABias; + +#ifdef RT6352 +// TODO: +/* ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R19, (PUCHAR)&RFValue); */ +#else + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R19, (PUCHAR)&RFValue); +#endif + RFValue = (((RFValue & 0x0F) | (pATEInfo->PABias << 4))); +#ifdef RT6352 +// TODO: +/* ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R19, (UCHAR)RFValue); */ +#else + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R19, (UCHAR)RFValue); +#endif + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_PA_Bias_Proc (PABias = %d)\n", pATEInfo->PABias)); + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_PA_Bias_Proc Success\n")); + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} +#endif /* RT3350 */ + + +/* +========================================================================== + Description: + Set ATE RF BW(default) + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Default_Set_ATE_TX_FREQ_OFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR RFFreqOffset = 0; +#ifdef RTMP_RF_RW_SUPPORT +#ifndef RF_BANK + UCHAR RFValue = 0; +#endif /* !RF_BANK */ +#endif /* RTMP_RF_RW_SUPPORT */ + + + RFFreqOffset = simple_strtol(arg, 0, 10); + +#ifdef RTMP_RF_RW_SUPPORT + /* 2008/08/06: KH modified the limit of offset value from 64 to 96(0x5F + 0x01) */ +#ifdef RT6352 + if (!IS_RT6352(pAd)) +#endif /* RT6352 */ + { + if (RFFreqOffset >= 96) + { + DBGPRINT_ERR(("Set_ATE_TX_FREQ_OFFSET_Proc::Out of range(0 ~ 95).\n")); + return FALSE; + } + } +#else + if (RFFreqOffset >= 64) + { + DBGPRINT_ERR(("Set_ATE_TX_FREQ_OFFSET_Proc::Out of range(0 ~ 63).\n")); + return FALSE; + } +#endif /* RTMP_RF_RW_SUPPORT */ + + pATEInfo->RFFreqOffset = RFFreqOffset; + +#ifdef RTMP_RF_RW_SUPPORT +#ifndef RF_BANK + if (IS_RT30xx(pAd)) + { + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R23, (PUCHAR)&RFValue); + RFValue = ((RFValue & 0x80) | pATEInfo->RFFreqOffset); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R23, (UCHAR)RFValue); + } +#endif /* !RF_BANK */ + if (IS_RT3593(pAd)) + { + ATEAsicSwitchChannel(pAd); + } + +#endif /* RTMP_RF_RW_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_FREQOFFSET_Proc (RFFreqOffset = %d)\n", pATEInfo->RFFreqOffset)); + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_FREQOFFSET_Proc Success\n")); + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +/* +========================================================================== + Description: + Set ATE RF frequence offset + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_TX_FREQ_OFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + INT ret = FALSE; + + if (pATEInfo->pChipStruct->Set_FREQ_OFFSET_Proc != NULL) + { + ret = pATEInfo->pChipStruct->Set_FREQ_OFFSET_Proc(pAd, arg); + } + + if (ret == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_FREQ_OFFSET_Proc (RFFreqOffset = %d)\n", pATEInfo->RFFreqOffset)); + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_FREQ_OFFSET_Proc Success\n")); + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + } + + return ret; +} + + +/* +========================================================================== + Description: + Set ATE RF BW(default) + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Default_Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + INT powerIndex; + UCHAR value = 0; + UCHAR BBPCurrentBW; + + BBPCurrentBW = simple_strtol(arg, 0, 10); + + if ((BBPCurrentBW == 0) + ) + { + pATEInfo->TxWI.BW = BW_20; + } + else + { + pATEInfo->TxWI.BW = BW_40; + } + + if ((pATEInfo->TxWI.PHYMODE == MODE_CCK) && (pATEInfo->TxWI.BW == BW_40)) + { + DBGPRINT_ERR(("Set_ATE_TX_BW_Proc!! Warning!! CCK only supports 20MHZ!!\n")); + DBGPRINT_ERR(("Bandwidth switch to 20!!\n")); + pATEInfo->TxWI.BW = BW_20; + } + + if (pATEInfo->TxWI.BW == BW_20) + { + if (pATEInfo->Channel <= 14) + { + /* BW=20;G band */ + for (powerIndex=0; powerIndexTx20MPwrCfgGBand[powerIndex] == 0xffffffff) + continue; + + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx20MPwrCfgGBand[powerIndex]); + RtmpOsMsDelay(5); + } + } + else + { + /* BW=20;A band */ + for (powerIndex=0; powerIndexTx20MPwrCfgABand[powerIndex] == 0xffffffff) + continue; + + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx20MPwrCfgABand[powerIndex]); + RtmpOsMsDelay(5); + } + } + + /* set BW = 20 MHz */ + /* Set BBP R4 bit[4:3]=0:0 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value &= (~0x18); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + /* Set BBP R66=0x3C */ + value = 0x3C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value); + + /* set BW = 20 MHz */ + { + pAd->LatchRfRegs.R4 &= ~0x00200000; + RtmpRfIoWrite(pAd); + } + + /* BW = 20 MHz */ + /* Set BBP R68=0x0B to improve Rx sensitivity. */ + value = 0x0B; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + /* Set BBP R69=0x16 */ + value = 0x16; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + /* Set BBP R70=0x08 */ + value = 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + /* Set BBP R73=0x11 */ + if ( IS_RT5390(pAd) || IS_RT5392(pAd)) + value = 0x13; + else + value = 0x11; + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + + + if (pATEInfo->Channel == 14) + { + INT TxMode = pATEInfo->TxWI.PHYMODE; + + if (TxMode == MODE_CCK) + { + /* when Channel==14 && Mode==CCK && BandWidth==20M, BBP R4 bit5=1 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value |= 0x20; /* set bit5=1 */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + } + } + } + /* If bandwidth = 40M, set RF Reg4 bit 21 = 0. */ + else if (pATEInfo->TxWI.BW == BW_40) + { + if (pATEInfo->Channel <= 14) + { + /* BW=40;G band */ + for (powerIndex=0; powerIndexTx40MPwrCfgGBand[powerIndex] == 0xffffffff) + continue; + + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx40MPwrCfgGBand[powerIndex]); + RtmpOsMsDelay(5); + } + } + else + { + /* BW=40;A band */ + for (powerIndex=0; powerIndexTx40MPwrCfgABand[powerIndex] == 0xffffffff) + continue; + + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + powerIndex*4, pAd->Tx40MPwrCfgABand[powerIndex]); + RtmpOsMsDelay(5); + } + + if ((pATEInfo->TxWI.PHYMODE >= 2) && (pATEInfo->TxWI.MCS == 7)) + { + value = 0x28; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R67, value); + } + } + + /* Set BBP R4 bit[4:3]=1:0 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value &= (~0x18); + value |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + /* Set BBP R66=0x3C */ + value = 0x3C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value); + + + /* Set BBP R68=0x0C to improve Rx sensitivity. */ + value = 0x0C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + /* Set BBP R69=0x1A */ + value = 0x1A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + /* Set BBP R70=0x0A */ + value = 0x0A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + /* Set BBP R73=0x16 */ + if (IS_RT5390(pAd) || IS_RT5392(pAd)) + value = 0x13; + else + value = 0x16; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_BW_Proc (BBPCurrentBW = %d)\n", pATEInfo->TxWI.BW)); + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_BW_Proc Success\n")); + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +/* +========================================================================== + Description: + Set ATE RF BW + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + if (pATEInfo->pChipStruct->Set_BW_Proc != NULL) + pATEInfo->pChipStruct->Set_BW_Proc(pAd, arg); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_BW_Proc (BBPCurrentBW = %d)\n", pATEInfo->TxWI.BW)); + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_BW_Proc Success\n")); + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +/* +========================================================================== + Description: + Set ATE Tx frame length + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_TX_LENGTH_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + pATEInfo->TxLength = simple_strtol(arg, 0, 10); + + if ((pATEInfo->TxLength < 24) || (pATEInfo->TxLength > (MAX_FRAME_SIZE - 34/* == 2312 */))) + { + pATEInfo->TxLength = (MAX_FRAME_SIZE - 34/* == 2312 */); + DBGPRINT_ERR(("Set_ATE_TX_LENGTH_Proc::Out of range, it should be in range of 24~%d.\n", (MAX_FRAME_SIZE - 34/* == 2312 */))); + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_LENGTH_Proc (TxLength = %d)\n", pATEInfo->TxLength)); + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_LENGTH_Proc Success\n")); + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +/* +========================================================================== + Description: + Set ATE Tx frame count + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_TX_COUNT_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + pATEInfo->TxCount = simple_strtol(arg, 0, 10); + +#ifdef RTMP_MAC_PCI + if (pATEInfo->TxCount == 0) + { + pATEInfo->TxCount = 0xFFFFFFFF; + } +#endif /* RTMP_MAC_PCI */ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_COUNT_Proc (TxCount = %d)\n", pATEInfo->TxCount)); + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_COUNT_Proc Success\n")); + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +/* +========================================================================== + Description: + Set ATE Tx frame MCS + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_TX_MCS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR MCS; + INT result; + + MCS = simple_strtol(arg, 0, 10); + result = CheckMCSValid(pAd, pATEInfo->TxWI.PHYMODE, MCS); + + if (result != -1) + { + pATEInfo->TxWI.MCS = (UCHAR)MCS; + } + else + { + DBGPRINT_ERR(("Set_ATE_TX_MCS_Proc::Out of range, refer to rate table.\n")); + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_MCS_Proc (MCS = %d)\n", pATEInfo->TxWI.MCS)); + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_MCS_Proc Success\n")); + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +/* +========================================================================== + Description: + Set ATE Tx frame STBC + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_TX_STBC_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + pATEInfo->TxWI.STBC = simple_strtol(arg, 0, 10); + + if (pATEInfo->TxWI.STBC > 1) + { + pATEInfo->TxWI.STBC = 0; + DBGPRINT_ERR(("Set_ATE_TX_STBC_Proc::Out of range\n")); + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_STBC_Proc (GI = %d)\n", pATEInfo->TxWI.STBC)); + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_STBC_Proc Success\n")); + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +/* +========================================================================== + Description: + Set ATE Tx frame Mode + 0: MODE_CCK + 1: MODE_OFDM + 2: MODE_HTMIX + 3: MODE_HTGREENFIELD + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_TX_MODE_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR BbpData = 0; + + pATEInfo->TxWI.PHYMODE = simple_strtol(arg, 0, 10); + + if (pATEInfo->TxWI.PHYMODE > 3) + { + pATEInfo->TxWI.PHYMODE = 0; + DBGPRINT_ERR(("Set_ATE_TX_MODE_Proc::Out of range.\nIt should be in range of 0~3\n")); + DBGPRINT(RT_DEBUG_OFF, ("0: CCK, 1: OFDM, 2: HT_MIX, 3: HT_GREEN_FIELD.\n")); + return FALSE; + } + + /* Turn on BBP 20MHz mode by request here. */ + if (pATEInfo->TxWI.PHYMODE == MODE_CCK) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BbpData); + BbpData &= (~0x18); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BbpData); + pATEInfo->TxWI.BW = BW_20; + } + +#ifdef RT3350 + if (IS_RT3350(pAd)) + { + if (pATEInfo->TxWI.PHYMODE == MODE_CCK) + { + USHORT value; + UCHAR rf_offset; + UCHAR rf_value; + + RT28xx_EEPROM_READ16(pAd, 0x126, value); + rf_value = value & 0x00FF; + rf_offset = (value & 0xFF00) >> 8; + + if(rf_offset == 0xff) + rf_offset = RF_R21; + if(rf_value == 0xff) + rf_value = 0x4F; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, rf_offset, (UCHAR)rf_value); + + RT28xx_EEPROM_READ16(pAd, 0x12a, value); + rf_value = value & 0x00FF; + rf_offset = (value & 0xFF00) >> 8; + + if(rf_offset == 0xff) + rf_offset = RF_R29; + if(rf_value == 0xff) + rf_value = 0x07; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, rf_offset, (UCHAR)rf_value); + + + /* set RF_R24 */ + if (pATEInfo->TxWI.BW == BW_40) + { + value = 0x3F; + } + else + { + value = 0x1F; + } + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R24, (UCHAR)value); + } + else + { + USHORT value; + UCHAR rf_offset; + UCHAR rf_value; + + RT28xx_EEPROM_READ16(pAd, 0x124, value); + rf_value = value & 0x00FF; + rf_offset = (value & 0xFF00) >> 8; + + if(rf_offset == 0xff) + rf_offset = RF_R21; + if(rf_value == 0xff) + rf_value = 0x6F; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, rf_offset, (UCHAR)rf_value); + + RT28xx_EEPROM_READ16(pAd, 0x128, value); + rf_value = value & 0x00FF; + rf_offset = (value & 0xFF00) >> 8; + + if(rf_offset == 0xff) + rf_offset = RF_R29; + if(rf_value == 0xff) + rf_value = 0x07; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, rf_offset, (UCHAR)rf_value); + + /* set RF_R24 */ + if (pATEInfo->TxWI.BW == BW_40) + { + value = 0x28; + } + else + { + value = 0x18; + } + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R24, (UCHAR)value); + } + } +#endif /* RT3350 */ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_MODE_Proc (TxMode = %d)\n", pATEInfo->TxWI.PHYMODE)); + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_MODE_Proc Success\n")); + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +/* +========================================================================== + Description: + Set ATE Tx frame GI + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_TX_GI_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + pATEInfo->TxWI.ShortGI = simple_strtol(arg, 0, 10); + + if (pATEInfo->TxWI.ShortGI > 1) + { + pATEInfo->TxWI.ShortGI = 0; + DBGPRINT_ERR(("Set_ATE_TX_GI_Proc::Out of range\n")); + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_GI_Proc (GI = %d)\n", pATEInfo->TxWI.ShortGI)); + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_GI_Proc Success\n")); + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +INT Set_ATE_RX_FER_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + pATEInfo->bRxFER = simple_strtol(arg, 0, 10); + + if (pATEInfo->bRxFER == 1) + { + pATEInfo->RxCntPerSec = 0; + pATEInfo->RxTotalCnt = 0; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_RX_FER_Proc (bRxFER = %d)\n", pATEInfo->bRxFER)); + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_RX_FER_Proc Success\n")); + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +INT Set_ATE_Read_RF_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ +#ifdef RTMP_RF_RW_SUPPORT +#ifndef RF_BANK + UCHAR RFValue; + INT index=0; + + if (IS_RT30xx(pAd) || IS_RT3572(pAd)) + { + for (index = 0; index < 32; index++) + { + ATE_RF_IO_READ8_BY_REG_ID(pAd, index, (PUCHAR)&RFValue); + DBGPRINT(RT_DEBUG_OFF, ("R%d=%d\n",index,RFValue)); + } + } + else +#ifdef RT305x + if (IS_RT305x(pAd)) + { + for (index = 0; index < 32; index++) + { + ATE_RF_IO_READ8_BY_REG_ID(pAd, index, (PUCHAR)&RFValue); + DBGPRINT(RT_DEBUG_OFF, ("R%d=%d\n",index,RFValue)); + } + } + else +#endif /* RT305x */ +#endif /* !RF_BANK */ +#endif /* RTMP_RF_RW_SUPPORT */ + { + DBGPRINT(RT_DEBUG_OFF, ("R1 = %x\n", pAd->LatchRfRegs.R1)); + DBGPRINT(RT_DEBUG_OFF, ("R2 = %x\n", pAd->LatchRfRegs.R2)); + DBGPRINT(RT_DEBUG_OFF, ("R3 = %x\n", pAd->LatchRfRegs.R3)); + DBGPRINT(RT_DEBUG_OFF, ("R4 = %x\n", pAd->LatchRfRegs.R4)); + } + return TRUE; +} + + +#ifndef RTMP_RF_RW_SUPPORT +INT Set_ATE_Write_RF1_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT32 value = (UINT32) simple_strtol(arg, 0, 16); + + pAd->LatchRfRegs.R1 = value; + RtmpRfIoWrite(pAd); + + return TRUE; +} + + +INT Set_ATE_Write_RF2_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT32 value = (UINT32) simple_strtol(arg, 0, 16); + + pAd->LatchRfRegs.R2 = value; + RtmpRfIoWrite(pAd); + + return TRUE; +} + + +INT Set_ATE_Write_RF3_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT32 value = (UINT32) simple_strtol(arg, 0, 16); + + pAd->LatchRfRegs.R3 = value; + RtmpRfIoWrite(pAd); + + return TRUE; +} + + +INT Set_ATE_Write_RF4_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT32 value = (UINT32) simple_strtol(arg, 0, 16); + + pAd->LatchRfRegs.R4 = value; + RtmpRfIoWrite(pAd); + + return TRUE; +} +#endif /* !RTMP_RF_RW_SUPPORT */ + + +/* +========================================================================== + Description: + Load and Write EEPROM from a binary file prepared in advance. + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_Load_E2P_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + BOOLEAN ret = FALSE; +#ifdef RTMP_RBUS_SUPPORT + PSTRING src = EEPROM_DEFAULT_FILE_PATH; +#else + PSTRING src = EEPROM_BIN_FILE_NAME; +#endif /* RTMP_RBUS_SUPPORT */ + RTMP_OS_FD srcf; + INT32 retval; + USHORT WriteEEPROM[(EEPROM_SIZE >> 1)]; + INT FileLength = 0; + UINT32 value = (UINT32) simple_strtol(arg, 0, 10); + RTMP_OS_FS_INFO osFSInfo; + + DBGPRINT(RT_DEBUG_OFF, ("===> %s (value=%d)\n\n", __FUNCTION__, value)); + + if (value > 0) + { + /* zero the e2p buffer */ + NdisZeroMemory((PUCHAR)WriteEEPROM, EEPROM_SIZE); + + RtmpOSFSInfoChange(&osFSInfo, TRUE); + + do + { + /* open the bin file */ + srcf = RtmpOSFileOpen(src, O_RDONLY, 0); + + if (IS_FILE_OPEN_ERR(srcf)) + { + DBGPRINT_ERR(("%s - Error opening file %s\n", __FUNCTION__, src)); + break; + } + + /* read the firmware from the file *.bin */ + FileLength = RtmpOSFileRead(srcf, (PSTRING)WriteEEPROM, EEPROM_SIZE); + + if (FileLength != EEPROM_SIZE) + { + DBGPRINT_ERR(("%s : error file length (=%d) in e2p.bin\n", + __FUNCTION__, FileLength)); + break; + } + else + { + /* write the content of .bin file to EEPROM */ +#if defined(RTMP_MAC_PCI) && defined(RTMP_PCI_SUPPORT) + { + USHORT index=0; + USHORT value=0; + INT32 e2p_size=512;/* == 0x200 for PCI interface */ + USHORT tempData=0; + + for (index = 0 ; index < (e2p_size >> 1); ) + { + /* "value" is especially for some compilers... */ + tempData = le2cpu16(WriteEEPROM[index]); + value = tempData; + RT28xx_EEPROM_WRITE16(pAd, (index << 1), value); + index ++; + } + } +#else + rt_ee_write_all(pAd, WriteEEPROM); +#endif /* defined(RTMP_MAC_PCI) && defined(RTMP_PCI_SUPPORT) */ + ret = TRUE; + } + break; + } while(TRUE); + + /* close firmware file */ + if (IS_FILE_OPEN_ERR(srcf)) + { + ; + } + else + { + retval = RtmpOSFileClose(srcf); + + if (retval) + { + DBGPRINT_ERR(("--> Error %d closing %s\n", -retval, src)); + + } + } + + /* restore */ + RtmpOSFSInfoChange(&osFSInfo, FALSE); + } + + DBGPRINT(RT_DEBUG_OFF, ("<=== %s (ret=%d)\n", __FUNCTION__, ret)); + + return ret; +} + + +INT Set_ATE_Read_E2P_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + USHORT buffer[EEPROM_SIZE >> 1]; + USHORT *p; + int i; + + rt_ee_read_all(pAd, (USHORT *)buffer); + p = buffer; + for (i = 0; i < (EEPROM_SIZE >> 1); i++) + { + DBGPRINT(RT_DEBUG_OFF, ("%4.4x ", *p)); + if (((i+1) % 16) == 0) + DBGPRINT(RT_DEBUG_OFF, ("\n")); + p++; + } + return TRUE; +} + + +#ifdef LED_CONTROL_SUPPORT +#endif /* LED_CONTROL_SUPPORT */ + +/* +========================================================================== + Description: + Enable ATE auto Tx alc (Tx auto level control). + According to the chip temperature, auto adjust the transmit power. + + 0: disable + 1: enable + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_AUTO_ALC_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 value = simple_strtol(arg, 0, 10); + UINT32 MacValue; + + if (value > 0) + { +#ifdef RTMP_INTERNAL_TX_ALC +#ifdef RT6352 + if (IS_RT6352(pAd)) + { +#ifdef RT6352_EP_SUPPORT + if (pAd->bExtPA == FALSE) + { +#endif /* RT6352_EP_SUPPORT */ + OS_SEM_LOCK(&(pATEInfo->TssiSemLock)); + RT635xTssiDcCalibration(pAd); + OS_SEM_UNLOCK(&(pATEInfo->TssiSemLock)); +#ifdef RT6352_EP_SUPPORT + } +#endif /* RT6352_EP_SUPPORT */ + } +#endif /* RT6352 */ +#endif /* RTMP_INTERNAL_TX_ALC */ + pATEInfo->bAutoTxAlc = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("ATEAUTOALC = TRUE , auto alc enabled!\n")); + } + else + { + pATEInfo->bAutoTxAlc = FALSE; + + if (IS_RT6352(pAd)) + { + /* clean up MAC 0x13B4 */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &MacValue); + MacValue = MacValue & (~0x3f); + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_1, MacValue); + } + DBGPRINT(RT_DEBUG_TRACE, ("ATEAUTOALC = FALSE , auto alc disabled!\n")); + } + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +/* +========================================================================== + Description: + Enable Tx temperature sensor. + + 0: disable + 1: enable + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_TEMP_SENSOR_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + BOOLEAN value = simple_strtol(arg, 0, 10); + UINT32 MacValue; + + if (value > 0) + { + pATEInfo->bLowTemperature = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("ATETEMPSENSOR = TRUE , temperature sensor enabled!\n")); + } + else + { + pATEInfo->bLowTemperature = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("ATETEMPSENSOR = FALSE , temperature sensor disabled!\n")); + } + +#ifdef CONFIG_AP_SUPPORT +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +#ifdef TXBF_SUPPORT +/* +========================================================================== + Description: + Set ATE Tx Beamforming mode + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_TXBF_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + CHAR value; + + value = simple_strtol(arg, 0, 10); + + switch (value) + { + case 0: + /* no BF */ + pATEInfo->TxWI.iTxBF = pATEInfo->TxWI.eTxBF = 0; + break; + case 1: + /* ETxBF */ + pATEInfo->TxWI.eTxBF = 1; + break; + case 2: + /* ITxBF */ + pATEInfo->TxWI.iTxBF = 1; + break; + case 3: + /* Enable TXBF support */ + pATEInfo->bTxBF = TRUE; + break; + case 4: + /* Disable TXBF support */ + pATEInfo->bTxBF = FALSE; + break; + default: + DBGPRINT_ERR(("Set_ATE_TXBF_Proc: Invalid parameter %d\n", value)); + break; + } + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; + } + + +/* +========================================================================== + Description: + Set ATE Sounding type + 0 => no sounding + 1 => Data sounding + 2 => 2 stream NDP sounding + 3 => 3 stream NDP Sounding + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_TXSOUNDING_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + CHAR value; + + value = simple_strtol(arg, 0, 10); + + if (value<0 || value>3) + { + DBGPRINT_ERR(("Set_ATE_TXSOUNDING_Proc: Invalid parameter %d\n", value)); + return FALSE; + } + + pATEInfo->txSoundingMode = value; + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +/* +========================================================================== + Description: + Do a Divider Calibration on calibration channels and save in EEPROM + 0 => do G and A band + 1 => G band only + 2 => A band only + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_TXBF_DIVCAL_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + int value; + ITXBF_DIV_PARAMS divParams; + CHAR initChanArg[] = "0"; + + value = simple_strtol(arg, 0, 10); + + if (value<0 || value>2) + return FALSE; + + /* G band */ + if (value==0 || value==1) + { + pATEInfo->Channel = 1; + Set_ATE_INIT_CHAN_Proc(pAd, initChanArg); + ITxBFDividerCalibration(pAd, 1, 0, NULL); + + pATEInfo->Channel = 14; + Set_ATE_INIT_CHAN_Proc(pAd, initChanArg); + ITxBFDividerCalibration(pAd, 1, 0, NULL); + + /* Display delta phase information */ + ITxBFGetEEPROM(pAd, NULL, NULL, &divParams); + + DBGPRINT(RT_DEBUG_WARN, ("Divider Cal Done:\n" + "ch1-ch14 = [%2d, %2d] degrees\n" + "ant0-ant2 = [%2d, %2d] degrees\n", + (UCHAR)(divParams.gBeg[0]-divParams.gEnd[0])*360/256, + (UCHAR)(divParams.gBeg[1]-divParams.gEnd[1])*360/256, + (UCHAR)(divParams.gBeg[0]-divParams.gBeg[1])*360/256, + (UCHAR)(divParams.gEnd[0]-divParams.gEnd[1])*360/256) ); + } + + /* A Band */ + if (value==0 || value==2) + { + pATEInfo->Channel = 36; + Set_ATE_INIT_CHAN_Proc(pAd, initChanArg); + ITxBFDividerCalibration(pAd, 1, 0, NULL); + + pATEInfo->Channel = 120; + Set_ATE_INIT_CHAN_Proc(pAd, initChanArg); + ITxBFDividerCalibration(pAd, 1, 0, NULL); + + pATEInfo->Channel = 165; + Set_ATE_INIT_CHAN_Proc(pAd, initChanArg); + ITxBFDividerCalibration(pAd, 1, 0, NULL); + } + + return TRUE; +} + + +/* +========================================================================== + Description: + Do a LNA Calibration on calibration channels and save in EEPROM + 0 => do G and A band + 1 => G band only + 2 => A band only + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_TXBF_LNACAL_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + int value; + int i; + CHAR initChanArg[] = "0"; + + value = simple_strtol(arg, 0, 10); + + if (value<0 || value>2) + return FALSE; + + /* G Band */ + if (value==0 || value==1) + { + pATEInfo->Channel = 1; + Set_ATE_INIT_CHAN_Proc(pAd, initChanArg); + ITxBFLNACalibration(pAd, 1, 0, TRUE); + + pATEInfo->Channel = 14; + Set_ATE_INIT_CHAN_Proc(pAd, initChanArg); + ITxBFLNACalibration(pAd, 1, 0, TRUE); + } + + /* A Band */ + if (value==0 || value==2) + { + static UCHAR channels[6] = {36, 64, 100, 128, 132, 165}; + for (i=0; i<6; i++) + { + pATEInfo->Channel = channels[i]; + Set_ATE_INIT_CHAN_Proc(pAd, initChanArg); + ITxBFLNACalibration(pAd, 1, 0, FALSE); + } + } + + return TRUE; +} + + +/* +========================================================================== + Description: + Sanity check for the channel of Implicit TxBF calibration. + + Return: + TRUE if all parameters are OK, FALSE otherwise + + Note: + 1. This sanity check function only work for Implicit TxBF calibration. + 2. Currently supported channels are: + 1, 14, 36, 64, 128, 132, 165 +========================================================================== +*/ +static BOOLEAN rtmp_ate_txbf_cal_valid_ch( + IN RTMP_ADAPTER *pAd, + IN UCHAR channel) +{ + BOOLEAN bValidCh; + + /* TODO: shall we check the capability of the chipset here ?? */ + switch (channel) + { + case 1: + case 14: +#ifdef A_BAND_SUPPORT + case 36: + case 64: + case 100: + case 128: + case 132: + case 165: +#endif /* A_BAND_SUPPORT */ + bValidCh = TRUE; + break; + default: + bValidCh = FALSE; + break; + } + + return bValidCh; +} + + +/* +========================================================================== + Description: + Set to start the initialization procedures of iTxBf calibration in DUT side + 0 => do nothing + 1 => do following initializations + + Return: + TRUE if all parameters are OK, FALSE otherwise + + Note: + This cmd shall only used in DUT side for calibration +========================================================================== +*/ +INT Set_ATE_TXBF_INIT_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + int val; + USHORT eepromVal; + UCHAR cmdStr[32]; + + val = simple_strtol(arg, 0, 10); + if (val != 1) + return FALSE; + + /* Do ATESTART */ +#ifdef CONFIG_RT2880_ATE_CMD_NEW + Set_ATE_Proc(pAd, "ATESTART"); +#else + Set_ATE_Proc(pAd, "APSTOP"); +#endif /* CONFIG_RT2880_ATE_CMD_NEW */ + + /* set ATETXBF=3 */ + Set_ATE_TXBF_Proc(pAd, "3"); + + + /* Set self mac address as 22:22:22:22:22:22 */ + RTMP_IO_WRITE32(pAd, 0x1008, 0x22222222); + RTMP_IO_WRITE32(pAd, 0x100c, 0x00002222); + + /* set ATEDA=11:11:11:11:11:11 */ + /* set ATESA=22:22:22:22:22:22 */ + /* set ATEBSSID=22:22:22:22:22:22 */ + for (val = 0; val < MAC_ADDR_LEN; val++) + { + pATEInfo->Addr1[val] = 0x11; /* the RA */ + pATEInfo->Addr2[val] = 0x22; /* the TA */ + pATEInfo->Addr3[val] = 0x22; /* the BSSID */ + } + + /* set ATETXMODE=2 */ + Set_ATE_TX_MODE_Proc(pAd, "2"); + + /* set ATETXMCS=16 */ + Set_ATE_TX_MCS_Proc(pAd, "16"); + + /* set ATETXBW=0 */ + Set_ATE_TX_BW_Proc(pAd, "0"); + + /* set ATETXGI=0 */ + Set_ATE_TX_GI_Proc(pAd, "0"); + + /* set ATETXANT=0 */ + Set_ATE_TX_Antenna_Proc(pAd, "0"); + + /* set ATERXANT=0 */ + Set_ATE_RX_Antenna_Proc(pAd, "0"); + + /* set ATETXFREQOFFSET=eeprom */ + /* read EEPROM Frequency offset from EEPROM and set it to BBP */ + RT28xx_EEPROM_READ16(pAd, 0x44, eepromVal); + snprintf(cmdStr, sizeof(cmdStr), "%d\n", (eepromVal & 0xff)); + Set_ATE_TX_FREQ_OFFSET_Proc(pAd, cmdStr); + + /* bbp 65=29 */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R65, 0x29); + + /* bbp 163=bd */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R163, 0xbd); + + /* bbp 173=28 */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R173, 0x28); + + return TRUE; +} + + +/* +========================================================================== + Description: + Set to do iTxBF calibration procedures for specific channel, following show us the supported channels. + 1, 14, 36, 64, 128, 132, 165 + + Return: + TRUE if all parameters are OK, FALSE otherwise + + Note: + This cmd shall only used in DUT side for calibration +========================================================================== +*/ +INT Set_ATE_TXBF_CAL_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR ch; + UCHAR cmdStr[32]; + + ch = simple_strtol(arg, 0, 10); + if (rtmp_ate_txbf_cal_valid_ch(pAd, ch) == FALSE) + return FALSE; + + /* iwpriv ra0 set ATECHANNEL=Channel */ + snprintf(cmdStr, sizeof(cmdStr), "%d\n", ch); + if (Set_ATE_CHANNEL_Proc(pAd, cmdStr) == FALSE) + return FALSE; + + /* iwpriv ra0 set ATEINITCHAN =0 */ + if (Set_ATE_INIT_CHAN_Proc(pAd, "0") == FALSE) + return FALSE; + + /* iwpriv ra0 set ATETXSOUNDING=3 */ + if (Set_ATE_TXSOUNDING_Proc(pAd, "3") == FALSE) + return FALSE; + + /* iwpriv ra0 set ETxBfNoncompress=0 */ + if (Set_ETxBfNoncompress_Proc(pAd, "0") == FALSE) + return FALSE; + + /* iwpriv ra0 set ATETXMCS=0 */ + if (Set_ATE_TX_MCS_Proc(pAd, "0") == FALSE) + return FALSE; + + /* iwpriv ra0 set ATETXCNT=1 */ + if (Set_ATE_TX_COUNT_Proc(pAd, "1") == FALSE) + return FALSE; + + /* iwpriv ra0 set ATETXLEN=258 */ + if (Set_ATE_TX_LENGTH_Proc(pAd, "258") == FALSE) + return FALSE; + + /* iwpriv ra0 set InvTxBfTag=0 */ + if (Set_InvTxBfTag_Proc(pAd, "0") == FALSE) + return FALSE; + + /* iwpriv ra0 set ATE=TXFRAME */ + if (Set_ATE_Proc(pAd, "TXFRAME") == FALSE) + return FALSE; + + /* iwpriv ra0 set ITxBfCal=1 */ + return Set_ITxBfCal_Proc(pAd, "1"); + +} + + +/* +========================================================================== + Description: + Set to start the initialization procedures of iTxBf calibration in Golden side at specified channel + arg => valid values are "1, 14, 36, 64, 128, 132, 165" + + Return: + TRUE if all parameters are OK, FALSE otherwise + + Note: + This cmd shall only used in GOLDEN side for calibration feedback +========================================================================== +*/ +INT Set_ATE_TXBF_GOLDEN_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR ch; + UCHAR cmdStr[32]; + USHORT eepromVal; + + ch = simple_strtol(arg, 0, 10); + if (rtmp_ate_txbf_cal_valid_ch(pAd, ch) == FALSE) + return FALSE; + + /* iwpriv ra0 set ATE=ATESTART */ +#ifdef CONFIG_RT2880_ATE_CMD_NEW + Set_ATE_Proc(pAd, "ATESTART"); +#else + Set_ATE_Proc(pAd, "APSTOP"); +#endif // CONFIG_RT2880_ATE_CMD_NEW // + + /* set the ate channel and read txpower from EEPROM and set to bbp */ + /* iwpriv ra0 set ATECHANNEL=Channel */ + /* iwpriv ra0 set ATETXPOWER=0 */ + snprintf(cmdStr, sizeof(cmdStr), "%d\n", ch); + Set_ATE_INIT_CHAN_Proc(pAd, cmdStr); + + + /* Set self mac address as 11:11:11:11:11:11 */ + /* iwpriv ra0 set ATESA=11:11:11:11:11:11 */ + RTMP_IO_WRITE32(pAd, 0x1008, 0x11111111); + RTMP_IO_WRITE32(pAd, 0x100c, 0x00001111); + + /* iwpriv ra0 set ATETXMODE=2 */ + Set_ATE_TX_MODE_Proc(pAd, "2"); + + /* iwpriv ra0 set ATETXBW=0 */ + Set_ATE_TX_BW_Proc(pAd, "0"); + + /* iwpriv ra0 set ATETXGI=0 */ + Set_ATE_TX_GI_Proc(pAd, "0"); + + /* iwpriv ra0 set ATETXANT=1 */ + Set_ATE_TX_Antenna_Proc(pAd, "1"); + + /* iwpriv ra0 set ATERXANT=1 */ + Set_ATE_RX_Antenna_Proc(pAd, "1"); + + /* iwpriv ra0 set ATETXFREQOFFSET=ValueOfEEPROM */ + RT28xx_EEPROM_READ16(pAd, 0x44, eepromVal); + snprintf(cmdStr, sizeof(cmdStr), "%d\n", (eepromVal & 0xff)); + Set_ATE_TX_FREQ_OFFSET_Proc(pAd, cmdStr); + + /* iwpriv ra0 bbp 65=29 */ + /* iwpriv ra0 bbp 163=9d */ + /* iwpriv ra0 bbp 173=00 */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R65, 0x29); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R163, 0x9d); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R173, 0x00); + + /* iwpriv ra0 set ATE=RXFRAME */ + Set_ATE_Proc(pAd, "RXFRAME"); + + /* reset the BBP_R173 as 0 to eliminate the compensation */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R173, 0x00); + + return TRUE; + +} + + +/* +========================================================================== + Description: + Set to do iTxBF calibration verification procedures at sepcified channel, following show us the supported channels. + args=> valid values are "1, 14, 36, 64, 128, 132, 165" + + Return: + TRUE if all parameters are OK, FALSE otherwise + + Note: + This cmd shall only used in GOLDEN side for calibration verification +========================================================================== +*/ +INT Set_ATE_TXBF_VERIFY_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR ch; + UCHAR cmdStr[32]; + + ch = simple_strtol(arg, 0, 10); + if (rtmp_ate_txbf_cal_valid_ch(pAd, ch) == FALSE) + return FALSE; + + /* iwpriv ra0 set ATECHANNEL=Channel */ + snprintf(cmdStr, sizeof(cmdStr), "%d\n", ch); + if (Set_ATE_CHANNEL_Proc(pAd, cmdStr) == FALSE) + return FALSE; + + /* iwpriv ra0 set ATETXSOUNDING=3 */ + if (Set_ATE_TXSOUNDING_Proc(pAd, "3") == FALSE) + return FALSE; + + /* iwpriv ra0 set ETxBfNoncompress=0 */ + if (Set_ETxBfNoncompress_Proc(pAd, "0") == FALSE) + return FALSE; + + /* iwpriv ra0 set ATETXMCS=0 */ + if (Set_ATE_TX_MCS_Proc(pAd, "0") == FALSE) + return FALSE; + + /* iwpriv ra0 set ATETXCNT=1 */ + if (Set_ATE_TX_COUNT_Proc(pAd, "1") == FALSE) + return FALSE; + + /* iwpriv ra0 set ATETXLEN=258 */ + if (Set_ATE_TX_LENGTH_Proc(pAd, "258") == FALSE) + return FALSE; + + /* iwpriv ra0 set InvTxBfTag=0 */ + if (Set_InvTxBfTag_Proc(pAd, "0") == FALSE) + return FALSE; + + /* iwpriv ra0 set ATE=TXFRAME */ + if (Set_ATE_Proc(pAd, "TXFRAME") == FALSE) + return FALSE; + + /* iwpriv ra0 set ITxBfCal=0 */ + return Set_ITxBfCal_Proc(pAd, "0"); +} + + +INT Set_ATE_ForceBBP_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR bbpReg; + + bbpReg = simple_strtol(arg, 0, 10); + + /* + 0: no any restriction for BBP writing + 1~255: force to not allow to change this specific BBP register. + + Note: + BBP_R0 is not write-able, so use 0 as the rest operation shall be safe enough + */ + pATEInfo->forceBBPReg = bbpReg; + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_ForceBBP_Proc:(forceBBPReg value=%d)\n", pATEInfo->forceBBPReg)); + + return TRUE; +} + + +/* +========================================================================== + Description: + Set to do iTxBF calibration verification without R173 compensation procedures at sepcified channel, following show us the supported channels. + args=> valid values are "1, 14, 36, 64, 128, 132, 165" + + Return: + TRUE if all parameters are OK, FALSE otherwise + + Note: + This cmd shall only used in GOLDEN side for calibration verification +========================================================================== +*/ +INT Set_ATE_TXBF_VERIFY_NoComp_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR ch; + UCHAR cmdStr[32]; + UCHAR bbpR173 = 0; + int retval; + + ch = simple_strtol(arg, 0, 10); + if (rtmp_ate_txbf_cal_valid_ch(pAd, ch) == FALSE) + return FALSE; + + /* iwpriv ra0 set ATECHANNEL=Channel */ + snprintf(cmdStr, sizeof(cmdStr), "%d\n", ch); + if (Set_ATE_CHANNEL_Proc(pAd, cmdStr) == FALSE) + return FALSE; + + /* iwpriv ra0 set ATETXSOUNDING=3 */ + if (Set_ATE_TXSOUNDING_Proc(pAd, "3") == FALSE) + return FALSE; + + /* iwpriv ra0 set ETxBfNoncompress=0 */ + if (Set_ETxBfNoncompress_Proc(pAd, "0") == FALSE) + return FALSE; + + /* iwpriv ra0 set ATETXMCS=0 */ + if (Set_ATE_TX_MCS_Proc(pAd, "0") == FALSE) + return FALSE; + + /* iwpriv ra0 set ATETXCNT=1 */ + if (Set_ATE_TX_COUNT_Proc(pAd, "1") == FALSE) + return FALSE; + + /* iwpriv ra0 set ATETXLEN=258 */ + if (Set_ATE_TX_LENGTH_Proc(pAd, "258") == FALSE) + return FALSE; + + /* iwpriv ra0 set InvTxBfTag=0 */ + if (Set_InvTxBfTag_Proc(pAd, "0") == FALSE) + return FALSE; + + /* save current BBP_R173 value and reset it as 0 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R173, &bbpR173); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R173, 0); + + /* force BBP_R173 value when do following procedures. */ + Set_ATE_ForceBBP_Proc(pAd, "173"); + + /* iwpriv ra0 set ATE=TXFRAME */ + if (Set_ATE_Proc(pAd, "TXFRAME") == FALSE) + { + Set_ATE_ForceBBP_Proc(pAd, "0"); + return FALSE; + } + + /* enable the update of BBP_R173 */ + Set_ATE_ForceBBP_Proc(pAd, "0"); + + /* iwpriv ra0 set ITxBfCal=0 */ + retval = Set_ITxBfCal_Proc(pAd, "0"); + + /* recovery the BBP_173 to original value */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R173, bbpR173); + + /* done and return */ + return retval; + +} +#endif /* TXBF_SUPPORT */ + + +/* +========================================================================== + Description: + Set ATE Tx frame IPG + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_IPG_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 data, value; + + pATEInfo->IPG = simple_strtol(arg, 0, 10); + value = pATEInfo->IPG; + + RTMP_IO_READ32(pAd, XIFS_TIME_CFG, &data); + + if (value <= 0) + { + DBGPRINT(RT_DEBUG_OFF, ("Set_ATE_IPG_Proc::IPG is disabled(IPG == 0).\n")); + return TRUE; + } + + ASSERT(value > 0); + + if ((value > 0) && (value < 256)) + { + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &data); + data &= 0x0; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, data); + + RTMP_IO_READ32(pAd, EDCA_AC1_CFG, &data); + data &= 0x0; + RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, data); + + RTMP_IO_READ32(pAd, EDCA_AC2_CFG, &data); + data &= 0x0; + RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, data); + + RTMP_IO_READ32(pAd, EDCA_AC3_CFG, &data); + data &= 0x0; + RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, data); + } + else + { + UINT32 aifsn, slottime; + + RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &slottime); + slottime &= 0x000000FF; + + aifsn = value / slottime; + value = value % slottime; + + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &data); + data &= 0x0; + data |= (aifsn << 8); + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, data); + + RTMP_IO_READ32(pAd, EDCA_AC1_CFG, &data); + data &= 0x0; + data |= (aifsn << 8); + RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, data); + + RTMP_IO_READ32(pAd, EDCA_AC2_CFG, &data); + data &= 0x0; + data |= (aifsn << 8); + RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, data); + + RTMP_IO_READ32(pAd, EDCA_AC3_CFG, &data); + data &= 0x0; + data |= (aifsn << 8); + RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, data); + } + + data = (value & 0xFFFF0000) | value | (value << 8); + RTMP_IO_WRITE32(pAd, XIFS_TIME_CFG, data); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_IPG_Proc (IPG = %u)\n", pATEInfo->IPG)); + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_IPG_Proc Success\n")); + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +/* +========================================================================== + Description: + Set ATE payload pattern for TxFrame + + Return: + TRUE if all parameters are OK, FALSE otherwise +========================================================================== +*/ +INT Set_ATE_Payload_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + PSTRING value; + + value = arg; + + /* only one octet acceptable */ + if (strlen(value) != 2) + return FALSE; + + AtoH(value, &(pATEInfo->Payload), 1); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_Payload_Proc (repeated pattern = 0x%2x)\n", pATEInfo->Payload)); + DBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_Payload_Proc Success\n")); + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + + + +INT Set_ATE_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + PSTRING Mode_String = NULL; + PSTRING TxMode_String = NULL; + + switch (pATEInfo->Mode) + { +#ifdef CONFIG_RT2880_ATE_CMD_NEW + case (fATE_IDLE): + Mode_String = "ATESTART"; + break; + case (fATE_EXIT): + Mode_String = "ATESTOP"; + break; +#else + case (fATE_IDLE): + Mode_String = "APSTOP"; + break; + case (fATE_EXIT): + Mode_String = "APSTART"; + break; +#endif /* CONFIG_RT2880_ATE_CMD_NEW */ + case ((fATE_TX_ENABLE)|(fATE_TXCONT_ENABLE)): + Mode_String = "TXCONT"; + break; + case ((fATE_TX_ENABLE)|(fATE_TXCARR_ENABLE)): + Mode_String = "TXCARR"; + break; + case ((fATE_TX_ENABLE)|(fATE_TXCARRSUPP_ENABLE)): + Mode_String = "TXCARS"; + break; + case (fATE_TX_ENABLE): + Mode_String = "TXFRAME"; + break; + case (fATE_RX_ENABLE): + Mode_String = "RXFRAME"; + break; + default: + { + Mode_String = "Unknown ATE mode"; + DBGPRINT(RT_DEBUG_OFF, ("ERROR! Unknown ATE mode!\n")); + break; + } + } + DBGPRINT(RT_DEBUG_OFF, ("ATE Mode=%s\n", Mode_String)); +#ifdef RT3350 + if (IS_RT3350(pAd)) + DBGPRINT(RT_DEBUG_OFF, ("PABias=%u\n", pATEInfo->PABias)); +#endif /* RT3350 */ + DBGPRINT(RT_DEBUG_OFF, ("TxPower0=%d\n", pATEInfo->TxPower0)); + DBGPRINT(RT_DEBUG_OFF, ("TxPower1=%d\n", pATEInfo->TxPower1)); +#ifdef DOT11N_SS3_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("TxPower2=%d\n", pATEInfo->TxPower2)); +#endif /* DOT11N_SS3_SUPPORT */ + DBGPRINT(RT_DEBUG_OFF, ("TxAntennaSel=%d\n", pATEInfo->TxAntennaSel)); + DBGPRINT(RT_DEBUG_OFF, ("RxAntennaSel=%d\n", pATEInfo->RxAntennaSel)); + DBGPRINT(RT_DEBUG_OFF, ("BBPCurrentBW=%u\n", pATEInfo->TxWI.BW)); + DBGPRINT(RT_DEBUG_OFF, ("GI=%u\n", pATEInfo->TxWI.ShortGI)); + DBGPRINT(RT_DEBUG_OFF, ("MCS=%u\n", pATEInfo->TxWI.MCS)); + + switch (pATEInfo->TxWI.PHYMODE) + { + case 0: + TxMode_String = "CCK"; + break; + case 1: + TxMode_String = "OFDM"; + break; + case 2: + TxMode_String = "HT-Mix"; + break; + case 3: + TxMode_String = "GreenField"; + break; + default: + { + TxMode_String = "Unknown TxMode"; + DBGPRINT(RT_DEBUG_OFF, ("ERROR! Unknown TxMode!\n")); + break; + } + } + + DBGPRINT(RT_DEBUG_OFF, ("TxMode=%s\n", TxMode_String)); + DBGPRINT(RT_DEBUG_OFF, ("Addr1=%02x:%02x:%02x:%02x:%02x:%02x\n", + pATEInfo->Addr1[0], pATEInfo->Addr1[1], pATEInfo->Addr1[2], pATEInfo->Addr1[3], pATEInfo->Addr1[4], pATEInfo->Addr1[5])); + DBGPRINT(RT_DEBUG_OFF, ("Addr2=%02x:%02x:%02x:%02x:%02x:%02x\n", + pATEInfo->Addr2[0], pATEInfo->Addr2[1], pATEInfo->Addr2[2], pATEInfo->Addr2[3], pATEInfo->Addr2[4], pATEInfo->Addr2[5])); + DBGPRINT(RT_DEBUG_OFF, ("Addr3=%02x:%02x:%02x:%02x:%02x:%02x\n", + pATEInfo->Addr3[0], pATEInfo->Addr3[1], pATEInfo->Addr3[2], pATEInfo->Addr3[3], pATEInfo->Addr3[4], pATEInfo->Addr3[5])); + DBGPRINT(RT_DEBUG_OFF, ("Channel=%u\n", pATEInfo->Channel)); + DBGPRINT(RT_DEBUG_OFF, ("TxLength=%u\n", pATEInfo->TxLength)); + DBGPRINT(RT_DEBUG_OFF, ("TxCount=%u\n", pATEInfo->TxCount)); + DBGPRINT(RT_DEBUG_OFF, ("RFFreqOffset=%u\n", pATEInfo->RFFreqOffset)); + DBGPRINT(RT_DEBUG_OFF, ("bAutoTxAlc=%d\n", pATEInfo->bAutoTxAlc)); + DBGPRINT(RT_DEBUG_OFF, ("IPG=%u\n", pATEInfo->IPG)); + DBGPRINT(RT_DEBUG_OFF, ("Payload=0x%02x\n", pATEInfo->Payload)); +#ifdef TXBF_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("bTxBF=%d\n", pATEInfo->bTxBF)); + DBGPRINT(RT_DEBUG_OFF, ("txSoundingMode=%d\n", pATEInfo->txSoundingMode)); +#endif /* TXBF_SUPPORT */ + DBGPRINT(RT_DEBUG_OFF, ("Set_ATE_Show_Proc Success\n")); +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + return TRUE; +} + + +INT Set_ATE_Help_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ +#ifdef CONFIG_RT2880_ATE_CMD_NEW + DBGPRINT(RT_DEBUG_OFF, ("ATE=ATESTART, ATESTOP, TXCONT, TXCARR, TXCARS, TXFRAME, RXFRAME\n")); +#else + DBGPRINT(RT_DEBUG_OFF, ("ATE=APSTOP, APSTART, TXCONT, TXCARR, TXCARS, TXFRAME, RXFRAME\n")); +#endif /* CONFIG_RT2880_ATE_CMD_NEW */ + DBGPRINT(RT_DEBUG_OFF, ("ATEDA\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATESA\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATEBSSID\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATECHANNEL, range:0~14(unless A band !)\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATETXPOW0, set power level of antenna 1.\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATETXPOW1, set power level of antenna 2.\n")); +#ifdef DOT11N_SS3_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("ATETXPOW2, set power level of antenna 3.\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATETXANT, set TX antenna. 0:all, 1:antenna one, 2:antenna two, 3:antenna three.\n")); +#else + DBGPRINT(RT_DEBUG_OFF, ("ATETXANT, set TX antenna. 0:all, 1:antenna one, 2:antenna two.\n")); +#endif /* DOT11N_SS3_SUPPORT */ + DBGPRINT(RT_DEBUG_OFF, ("ATERXANT, set RX antenna.0:all, 1:antenna one, 2:antenna two, 3:antenna three.\n")); +#ifdef RT3350 + if (IS_RT3350(pAd)) + DBGPRINT(RT_DEBUG_OFF, ("ATEPABIAS, set power amplifier bias for EVM, range 0~15\n")); +#endif /* RT3350 */ +#ifdef RTMP_RF_RW_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("ATETXFREQOFFSET, set frequency offset, range 0~95\n")); +#else + DBGPRINT(RT_DEBUG_OFF, ("ATETXFREQOFFSET, set frequency offset, range 0~63\n")); +#endif /* RTMP_RF_RW_SUPPORT */ + DBGPRINT(RT_DEBUG_OFF, ("ATETXBW, set BandWidth, 0:20MHz, 1:40MHz.\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATETXLEN, set Frame length, range 24~%d\n", (MAX_FRAME_SIZE - 34/* == 2312 */))); + DBGPRINT(RT_DEBUG_OFF, ("ATETXCNT, set how many frame going to transmit.\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATETXMCS, set MCS, reference to rate table.\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATETXMODE, set Mode 0:CCK, 1:OFDM, 2:HT-Mix, 3:GreenField, reference to rate table.\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATETXGI, set GI interval, 0:Long, 1:Short\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATERXFER, 0:disable Rx Frame error rate. 1:enable Rx Frame error rate.\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATERRF, show all RF registers.\n")); +#ifndef RTMP_RF_RW_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("ATEWRF1, set RF1 register.\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATEWRF2, set RF2 register.\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATEWRF3, set RF3 register.\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATEWRF4, set RF4 register.\n")); +#endif /* !RTMP_RF_RW_SUPPORT */ + DBGPRINT(RT_DEBUG_OFF, ("ATELDE2P, load EEPROM from .bin file.\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATERE2P, display all EEPROM content.\n")); +#ifdef LED_CONTROL_SUPPORT +#endif /* LED_CONTROL_SUPPORT */ + DBGPRINT(RT_DEBUG_OFF, ("ATEAUTOALC, enable ATE auto Tx alc (Tx auto level control).\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATEIPG, set ATE Tx frame IPG.\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATEPAYLOAD, set ATE payload pattern for TxFrame.\n")); +#ifdef TXBF_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("ATETXBF, enable ATE Tx beam forming.\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATETXSOUNDING, Sounding mode 0:none, 1:Data sounding, 2:2 stream NDP, 3:3 stream NDP.\n")); +#endif /* TXBF_SUPPORT */ +#ifdef RTMP_INTERNAL_TX_ALC + DBGPRINT(RT_DEBUG_OFF, ("ATETSSICBA, start internal TSSI calibration.\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATETSSICBAEX, start extended internal TSSI calibration.\n")); +#endif /* RTMP_INTERNAL_TX_ALC */ +#ifdef RTMP_TEMPERATURE_COMPENSATION + DBGPRINT(RT_DEBUG_OFF, ("ATEREADEXTSSI, start advanced temperature TSSI calibration.\n")); +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + DBGPRINT(RT_DEBUG_OFF, ("ATESHOW, display all parameters of ATE.\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATEHELP, online help.\n")); + + return TRUE; +} + + +#ifdef RT6352 +#ifdef RTMP_TEMPERATURE_CALIBRATION +INT RT6352_ATETempCalibration( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + //PATE_INFO pATEInfo = &(pAd->ate); + INT32 ref25 = 0, curr_reading = 0, curr_temperature = 0; + INT ret = TRUE; + UINT16 e2p_data = 0; + + curr_temperature = (INT32)simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("curr_temperature = 0x%x\n", curr_temperature)); + + /* to get bbp r49 */ + RT6352_Temperature_Init(pAd); + curr_reading = pAd->CurrTemperature; + DBGPRINT(RT_DEBUG_TRACE, ("curr_reading = 0x%x\n", curr_reading)); + + ref25 = curr_reading + ((25 - curr_temperature)*10)/19; + /* write calibration result */ + RT28xx_EEPROM_READ16(pAd, 0xD0, e2p_data); + e2p_data &= ~(0xFF00); + e2p_data |= (((ref25 & 0xFF) << 8) & 0xFF00); + RT28xx_EEPROM_WRITE16(pAd, 0xD0, e2p_data); + + return ret; +} +#endif /* RTMP_TEMPERATURE_CALIBRATION */ +#endif /* RT6352 */ + + +#ifdef RTMP_TEMPERATURE_CALIBRATION +INT Set_ATE_TEMP_CAL_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT ret = TRUE; + +#ifdef RT6352 + if (IS_RT6352(pAd)) + ret = RT6352_ATETempCalibration(pAd, arg); +#endif /* RT6352 */ + + return ret; +} + + +INT Set_ATE_SHOW_TSSI_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT ret = TRUE; +#ifdef RT6352 + UCHAR wait, BBPValue, RFValue, RFB0R2Value; + CHAR BbpR49 = 0; +#endif /* RT6352 */ + +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + /* 1. set BBP R47[4]=1 to enable TSSI for next reading */ + /* enable RF before reading temperature sensor */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_BANK0, RF_R02, &RFValue); + RFB0R2Value = RFValue; /* keep it for recovery later */ + RFValue |= 0x10; + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R02, RFValue); + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + + if (!(BBPValue & (1<<4))) + { + BBPValue |= (1<<4); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + } + + /* 2. polling BBP_R47 until BBP R47[4]==0 */ + for (wait=0; wait<200; wait++) + { + RTMPusecDelay(100); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + + if (!(BBPValue & (1<<4))) + { + break; + } + } + + if ((BBPValue & 0x10) != 0) + { + ret = FALSE; + printk("Read TSSI failed !\n"); + return ret; + } + + /* 3. set BBP R47[3:0]=4 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= ~(0x0F); + BBPValue |= (0x04); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + /* 4. fetch temperature reading */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); + + /* 5. recover RF after reading temperature sensor */ + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_BANK0, RF_R02, RFB0R2Value); + + printk("BBP R49: 0x%02X\n", BbpR49); + } +#endif /* RT6352 */ + + return ret; +} +#endif /* RTMP_TEMPERATURE_CALIBRATION */ + + +#ifdef RTMP_INTERNAL_TX_ALC + + +INT Set_ATE_TSSI_CALIBRATION_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + if (pATEInfo->pChipStruct->TssiCalibration != NULL) + { + pATEInfo->pChipStruct->TssiCalibration(pAd, arg); + } + else + { + RTMP_CHIP_ATE_TSSI_CALIBRATION(pAd, arg); + } + + return TRUE; +} + + +INT Set_ATE_TSSI_CALIBRATION_EX_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + if (pATEInfo->pChipStruct->ExtendedTssiCalibration != NULL) + { + pATEInfo->pChipStruct->ExtendedTssiCalibration(pAd, arg); + } + else + { + RTMP_CHIP_ATE_TSSI_CALIBRATION_EXTEND(pAd, arg); + } + + return TRUE; +} + + +#if defined(RT3350) || defined(RT3352) +INT RT335x2_Set_ATE_TSSI_CALIBRATION_ENABLE_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + BOOLEAN bTSSICalbrEnableG = FALSE; + + if (pAd->TxPowerCtrl.bInternalTxALC == FALSE) + { + DBGPRINT_ERR(("Please set e2p 0x36 as 0x2024!!!\n")); + return FALSE; + } + + if ((!IS_RT3350(pAd)) && (!IS_RT3352(pAd))) + { + DBGPRINT_ERR(("Not support TSSI calibration since not 3350/3352 chip!!!\n")); + return FALSE; + } + + if (strcmp(arg, "0") == 0) + { + bTSSICalbrEnableG = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("TSSI calibration disabled!\n")); + } + else if (strcmp(arg, "1") == 0) + { + bTSSICalbrEnableG = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("TSSI calibration enabled!\n")); + } + else + { + return FALSE; + } + + pAd->ate.bTSSICalbrEnableG = bTSSICalbrEnableG; + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +CHAR InsertTssi(UCHAR InChannel, UCHAR Channel0, UCHAR Channel1,CHAR Tssi0, CHAR Tssi1) +{ + CHAR InTssi; + CHAR ChannelDelta, InChannelDelta; + CHAR TssiDelta; + + ChannelDelta = Channel1 - Channel0; + InChannelDelta = InChannel - Channel0; + TssiDelta = Tssi1 - Tssi0; + + InTssi = Tssi0 + ((InChannelDelta * TssiDelta) / ChannelDelta); + + return InTssi; +} + + +INT RT335xATETssiCalibrationExtend( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + CHAR TssiRefPerChannel[CFG80211_NUM_OF_CHAN_2GHZ], TssiDeltaPerChannel[CFG80211_NUM_OF_CHAN_2GHZ]; + UCHAR CurrentChannel; + UCHAR BbpData = 0; + USHORT EEPData; + + if (pAd->ate.bTSSICalbrEnableG == FALSE) + { + DBGPRINT_ERR(("No TSSI readings obtained !!!\n")); + DBGPRINT_ERR(("TSSI calibration failed !!!\n")); + + return FALSE; + } + else + { + pAd->ate.bTSSICalbrEnableG = FALSE; + } + + NdisCopyMemory(TssiRefPerChannel, pAd->ate.TssiRefPerChannel, CFG80211_NUM_OF_CHAN_2GHZ); + NdisCopyMemory(TssiDeltaPerChannel, pAd->ate.TssiDeltaPerChannel, CFG80211_NUM_OF_CHAN_2GHZ); + + /* step 1: write TSSI_ref to EEPROM 0x6E */ + CurrentChannel = 7; + BbpData = TssiRefPerChannel[CurrentChannel-1]; + DBGPRINT(RT_DEBUG_TRACE, ("TSSI_ref = 0x%02x\n", TssiRefPerChannel[CurrentChannel-1])); + RT28xx_EEPROM_READ16(pAd, EEPROM_TSSI_OVER_OFDM_54, EEPData); + EEPData &= 0xff00; + EEPData |= BbpData; + DBGPRINT(RT_DEBUG_TRACE, ("Write E2P 0x6e: 0x%04x\n", EEPData)); +#ifdef RTMP_EFUSE_SUPPORT + if(pAd->bUseEfuse) + { + if(pAd->bFroceEEPROMBuffer) + NdisMoveMemory(&(pAd->EEPROMImage[EEPROM_TSSI_OVER_OFDM_54]), (PUCHAR) (&EEPData) ,2); + else + eFuseWrite(pAd, EEPROM_TSSI_OVER_OFDM_54, (PUCHAR) (&EEPData), 2); + } + else +#endif /* RTMP_EFUSE_SUPPORT */ + { + RT28xx_EEPROM_WRITE16(pAd, EEPROM_TSSI_OVER_OFDM_54, EEPData); + RTMPusecDelay(10); + } + + /* step 2: insert the TSSI table */ + /* insert channel 2 to 6 TSSI values */ + for (CurrentChannel = 2; CurrentChannel < 7; CurrentChannel++) + TssiRefPerChannel[CurrentChannel-1] = InsertTssi(CurrentChannel, 1, 7, TssiRefPerChannel[0], TssiRefPerChannel[6]); + + /* insert channel 8 to 12 TSSI values */ + for (CurrentChannel = 8; CurrentChannel < 13; CurrentChannel++) + TssiRefPerChannel[CurrentChannel-1] = InsertTssi(CurrentChannel, 7, 13, TssiRefPerChannel[6], TssiRefPerChannel[12]); + + /* channel 14 TSSI equals channel 13 TSSI */ + TssiRefPerChannel[13] = TssiRefPerChannel[12]; + + for (CurrentChannel = 1; CurrentChannel <= 14; CurrentChannel++) + { + TssiDeltaPerChannel[CurrentChannel-1] = TssiRefPerChannel[CurrentChannel-1] - TssiRefPerChannel[6]; + + /* boundary check */ + if(TssiDeltaPerChannel[CurrentChannel-1] > 7 ) + TssiDeltaPerChannel[CurrentChannel-1] = 7; + if(TssiDeltaPerChannel[CurrentChannel-1] < -8 ) + TssiDeltaPerChannel[CurrentChannel-1] = -8; + + /* eeprom only use 4 bit for TSSI delta */ + TssiDeltaPerChannel[CurrentChannel-1] &= 0x0f; + DBGPRINT(RT_DEBUG_TRACE, ("Channel %d, TSSI= 0x%x, TssiDelta=0x%x\n", + CurrentChannel, TssiRefPerChannel[CurrentChannel-1], TssiDeltaPerChannel[CurrentChannel-1])); + } + + /* step 3: store TSSI delta values to EEPROM */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TX_POWER_OFFSET_OVER_CH_1-1, EEPData); + EEPData &= 0x00ff; + EEPData |= (TssiDeltaPerChannel[0] << 8) | (TssiDeltaPerChannel[1] << 12); + +#ifdef RTMP_EFUSE_SUPPORT + if (pAd->bUseEfuse) + { + if (pAd->bFroceEEPROMBuffer) + NdisMoveMemory(&(pAd->EEPROMImage[EEPROM_TX_POWER_OFFSET_OVER_CH_1-1]), (PUCHAR)(&EEPData), 2); + else + eFuseWrite(pAd, EEPROM_TX_POWER_OFFSET_OVER_CH_1-1, (PUCHAR) (&EEPData), 2); + } + else +#endif /* RTMP_EFUSE_SUPPORT */ + { + RT28xx_EEPROM_WRITE16(pAd, EEPROM_TX_POWER_OFFSET_OVER_CH_1-1, EEPData); + RTMPusecDelay(10); + } + + for (CurrentChannel = 3; CurrentChannel <= 14; CurrentChannel += 4) + { + EEPData = (TssiDeltaPerChannel[CurrentChannel+2] << 12) |(TssiDeltaPerChannel[CurrentChannel+1] << 8) + | (TssiDeltaPerChannel[CurrentChannel] << 4) | TssiDeltaPerChannel[CurrentChannel-1]; +#ifdef RTMP_EFUSE_SUPPORT + if (pAd->bUseEfuse) + { + if (pAd->bFroceEEPROMBuffer) + NdisMoveMemory(&(pAd->EEPROMImage[(EEPROM_TX_POWER_OFFSET_OVER_CH_3 +((CurrentChannel-3)/2))]), (PUCHAR)(&EEPData), 2); + else + eFuseWrite(pAd, (EEPROM_TX_POWER_OFFSET_OVER_CH_3 +((CurrentChannel-3)/2)), (PUCHAR) (&EEPData), 2); + } + else +#endif /* RTMP_EFUSE_SUPPORT */ + { + RT28xx_EEPROM_WRITE16(pAd, (EEPROM_TX_POWER_OFFSET_OVER_CH_3 +((CurrentChannel-3)/2)), EEPData); + RTMPusecDelay(10); + } + } + + /* step 4: disable legacy ALC and set TSSI enabled and TSSI extend mode to EEPROM */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TSSI_ENABLE, EEPData); + /* disable legacy ALC */ + EEPData &= ~(1 << 1); + /* enable TSSI */ + EEPData |= (1 << 13); +#ifdef RTMP_EFUSE_SUPPORT + if (pAd->bUseEfuse) + { + if (pAd->bFroceEEPROMBuffer) + NdisMoveMemory(&(pAd->EEPROMImage[EEPROM_TSSI_ENABLE]), (PUCHAR)(&EEPData), 2); + else + eFuseWrite(pAd, EEPROM_TSSI_ENABLE, (PUCHAR)(&EEPData), 2); + } + else +#endif /* RTMP_EFUSE_SUPPORT */ + { + RT28xx_EEPROM_WRITE16(pAd, EEPROM_TSSI_ENABLE, EEPData); + RTMPusecDelay(10); + } + + RT28xx_EEPROM_READ16(pAd, EEPROM_TSSI_MODE_EXTEND, EEPData); + /* set extended TSSI mode */ + EEPData |= (1 << 15); +#ifdef RTMP_EFUSE_SUPPORT + if (pAd->bUseEfuse) + { + if (pAd->bFroceEEPROMBuffer) + NdisMoveMemory(&(pAd->EEPROMImage[EEPROM_TSSI_MODE_EXTEND]), (PUCHAR)(&EEPData), 2); + else + eFuseWrite(pAd, EEPROM_TSSI_MODE_EXTEND, (PUCHAR)(&EEPData), 2); + } + else +#endif /* RTMP_EFUSE_SUPPORT */ + { + RT28xx_EEPROM_WRITE16(pAd, EEPROM_TSSI_MODE_EXTEND, EEPData); + RTMPusecDelay(10); + } + + /* step 5: synchronize ATE private data structure with the values written to EEPROM */ + NdisCopyMemory(pAd->ate.TssiRefPerChannel, TssiRefPerChannel, CFG80211_NUM_OF_CHAN_2GHZ); + NdisCopyMemory(pAd->ate.TssiDeltaPerChannel, TssiDeltaPerChannel, CFG80211_NUM_OF_CHAN_2GHZ); + + return TRUE; +} + +#endif /* defined(RT3350) || defined(RT3352) */ +#endif /* RTMP_INTERNAL_TX_ALC */ + + +#ifdef RTMP_TEMPERATURE_COMPENSATION + + +INT Set_ATE_READ_EXTERNAL_TSSI_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + + RTMP_CHIP_ATE_READ_EXTERNAL_TSSI(pAd, arg); + return TRUE; +} +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + + + + +struct _ATE_CHIP_STRUCT RALINKDefault = +{ + /* functions */ + .ChannelSwitch = DefaultATEAsicSwitchChannel, + .TxPwrHandler = DefaultATETxPwrHandler, + .TssiCalibration = NULL, + .ExtendedTssiCalibration = NULL, + .RxVGAInit = NULL, + .AsicSetTxRxPath = DefaultATEAsicSetTxRxPath, + .AdjustTxPower = DefaultATEAsicAdjustTxPower, + .AsicExtraPowerOverMAC = NULL, + + /* command handlers */ + .Set_BW_Proc = Default_Set_ATE_TX_BW_Proc, + .Set_FREQ_OFFSET_Proc = Default_Set_ATE_TX_FREQ_OFFSET_Proc, + + /* variables */ + .maxTxPwrCnt = 5, + .bBBPStoreTXCARR = TRUE, + .bBBPStoreTXCARRSUPP = TRUE, + .bBBPStoreTXCONT = FALSE, + .bBBPLoadATESTOP = TRUE, +}; + +#ifdef RT28xx +#ifdef RTMP_MAC_PCI +extern ATE_CHIP_STRUCT RALINK2860; +extern ATE_CHIP_STRUCT RALINK2880; +#endif /* RTMP_MAC_PCI */ +#endif /* RT28xx */ + + +#ifdef RT2883 +extern ATE_CHIP_STRUCT RALINK2883; +#endif /* RT2883 */ + +#ifdef RT3883 +extern ATE_CHIP_STRUCT RALINK3883; +#endif /* RT3883 */ + +#ifdef RT305x +#ifdef RT3050 +extern ATE_CHIP_STRUCT RALINK3050; +#endif /* RT3050 */ + +#ifdef RT3052 +extern ATE_CHIP_STRUCT RALINK3052; +#endif /* RT3052 */ + +#ifdef RT3350 +extern ATE_CHIP_STRUCT RALINK3350; +#endif /* RT3350 */ + +#ifdef RT3352 +extern ATE_CHIP_STRUCT RALINK3352; +#endif /* RT3352 */ + +#ifdef RT5350 +extern ATE_CHIP_STRUCT RALINK5350; +#endif /* RT5350 */ +#endif /* RT305x */ + + + + + + +#ifdef RT6352 +extern ATE_CHIP_STRUCT RALINK6352; +#endif /* RT6352 */ + + +/* +========================================================================== + Description: + Assign chip structure when initialization. + This routine is specific for ATE. + +========================================================================== +*/ +NDIS_STATUS ChipStructAssign( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + + pATEInfo->pChipStruct = &RALINKDefault; + +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + /* + Notice: IS_RT6352(_pAd) is currently defined + as (((_pAd)->MACVersion & 0xFFFF0000) == 0x53900000) + */ + pATEInfo->pChipStruct = &RALINK6352; + return NDIS_STATUS_SUCCESS; + } +#endif /* IS_RT6352 */ + + +#ifdef RT2883 + if (IS_RT2883(pAd)) + { + pATEInfo->pChipStruct = &RALINK2883; + return NDIS_STATUS_SUCCESS; + } +#endif /* RT2883 */ + +#ifdef RT3883 + if (IS_RT3883(pAd)) + { + pATEInfo->pChipStruct = &RALINK3883; + return NDIS_STATUS_SUCCESS; + } +#endif /* RT3883 */ + + +#ifdef RT305x +#ifdef RT3050 + if (IS_RT3050(pAd)) + { + pATEInfo->pChipStruct = &RALINK3050; + return NDIS_STATUS_SUCCESS; + } +#endif /* RT3050 */ + +#ifdef RT3052 + if (IS_RT3052(pAd)) + { + pATEInfo->pChipStruct = &RALINK3052; + return NDIS_STATUS_SUCCESS; + } +#endif /* RT3052 */ + +#ifdef RT3350 + if (IS_RT3350(pAd)) + { + pATEInfo->pChipStruct = &RALINK3350; + return NDIS_STATUS_SUCCESS; + } +#endif /* RT3350 */ + +#ifdef RT3352 + if (IS_RT3352(pAd)) + { + pATEInfo->pChipStruct = &RALINK3352; + return NDIS_STATUS_SUCCESS; + } +#endif /* RT3352 */ + +#ifdef RT5350 + if (IS_RT5350(pAd)) + { + pATEInfo->pChipStruct = &RALINK5350; + return NDIS_STATUS_SUCCESS; + } +#endif /* RT5350 */ +#endif /* RT305x */ + + +#ifdef RT28xx +#ifdef A_BAND_SUPPORT + if (IS_PCI_ONLY_INF(pAd) || IS_USB_INF(pAd) || IS_RBUS_INF(pAd)) + { +#ifdef RT2860 + if (IS_PCI_ONLY_INF(pAd)) + { + pATEInfo->pChipStruct = &RALINK2860; + return NDIS_STATUS_SUCCESS; + } +#endif /* RT2860 */ + + +#ifdef RT2880 + if (IS_RBUS_INF(pAd)) + { + pATEInfo->pChipStruct = &RALINK2880; + return NDIS_STATUS_SUCCESS; + } +#endif /* RT2880 */ + } +#endif /* A_BAND_SUPPORT */ +#endif /* RT28xx */ + + + + + /* sanity check */ + if (pATEInfo->pChipStruct == &RALINKDefault) + { + /* Unknown chipset ! */ + DBGPRINT_ERR(("Warning - Unknown chipset !!!\n")); + DBGPRINT_ERR(("MAC Version is %u\n", ((pAd->MACVersion & 0xFFFF0000) >> 16))); + DBGPRINT_ERR(("Interface type is %d\n", pAd->infType)); + + return NDIS_STATUS_FAILURE; + } + + return NDIS_STATUS_SUCCESS; +} + + +/* +========================================================================== + Description: + Initialize ATE_INFO structure. + This routine is specific for ATE. + +========================================================================== +*/ +NDIS_STATUS ATEInit( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + NdisZeroMemory(pATEInfo, sizeof(ATE_INFO)); + + if (ChipStructAssign(pAd) != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("%s failed !\n", __FUNCTION__)); + return NDIS_STATUS_FAILURE; + } + + OS_NdisAllocateSpinLock(&(pATEInfo->TssiSemLock)); + + pATEInfo->Mode = ATE_STOP; +#ifdef RT3350 + pATEInfo->PABias = 0; +#endif /* RT3350 */ + pATEInfo->TxCount = 0xFFFFFFFF; /* to sync with QA and to exceed TX_RING_SIZE ... */ + pATEInfo->TxDoneCount = 0; + pATEInfo->RFFreqOffset = 0; +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + pATEInfo->Payload = 0xAA; /* new chip: sync with QA */ + pATEInfo->bDPDEnable = FALSE; + } + else +#endif /* RT6352 */ + pATEInfo->Payload = 0xA5;/* to be backward compatible */ + pATEInfo->IPG = 200;/* 200 : sync with QA */ + pATEInfo->TxLength = 1058;/* 1058 : sync with QA */ + pATEInfo->TxWI.ShortGI = 0;/* LONG GI : 800 ns*/ + pATEInfo->TxWI.PHYMODE = MODE_CCK; + pATEInfo->TxWI.MCS = 3; + pATEInfo->TxWI.BW = BW_20; + /* please do not change these default values */ + pATEInfo->Channel = 1; + pATEInfo->TxAntennaSel = 1; + pATEInfo->RxAntennaSel = 0; + + +#ifdef RTMP_MAC_PCI +#endif /* RTMP_MAC_PCI */ + pATEInfo->QID = QID_AC_BE; + +#ifdef DOT11N_SS3_SUPPORT + /* For 3T/3R ++ */ + /* use broadcast address as default value */ + pATEInfo->Addr1[0] = 0xFF; + pATEInfo->Addr1[1] = 0xFF; + pATEInfo->Addr1[2] = 0xFF; + pATEInfo->Addr1[3] = 0xFF; + pATEInfo->Addr1[4] = 0xFF; + pATEInfo->Addr1[5] = 0xFF; + + pATEInfo->Addr2[0] = 0x00; + pATEInfo->Addr2[1] = 0x11; + pATEInfo->Addr2[2] = 0x22; + pATEInfo->Addr2[3] = 0xAA; + pATEInfo->Addr2[4] = 0xBB; + pATEInfo->Addr2[5] = 0xCC; + + NdisMoveMemory(pATEInfo->Addr3, pATEInfo->Addr2, ETH_LENGTH_OF_ADDRESS); + + { + UINT32 data; + + data = 0xFFFFFFFF; + RTMP_IO_WRITE32(pAd, 0x1044, data); + RTMP_IO_READ32(pAd, 0x1048, &data); + + data = data | 0x0000FFFF; + RTMP_IO_WRITE32(pAd, 0x1048, data); + } + /* For stream mode in 3T/3R -- */ +#else + pATEInfo->Addr1[0] = 0x00; + pATEInfo->Addr1[1] = 0x11; + pATEInfo->Addr1[2] = 0x22; + pATEInfo->Addr1[3] = 0xAA; + pATEInfo->Addr1[4] = 0xBB; + pATEInfo->Addr1[5] = 0xCC; + + NdisMoveMemory(pATEInfo->Addr2, pATEInfo->Addr1, ETH_LENGTH_OF_ADDRESS); + NdisMoveMemory(pATEInfo->Addr3, pATEInfo->Addr1, ETH_LENGTH_OF_ADDRESS); +#endif /* DOT11N_SS3_SUPPORT */ + + pATEInfo->bRxFER = 0; + pATEInfo->bQAEnabled = FALSE; + pATEInfo->bQATxStart = FALSE; + pATEInfo->bQARxStart = FALSE; + pATEInfo->bAutoTxAlc = FALSE; + pATEInfo->bLowTemperature = FALSE; +#ifdef RTMP_INTERNAL_TX_ALC +#if defined(RT3350) || defined(RT3352) + pATEInfo->bTSSICalbrEnableG = FALSE; + NdisZeroMemory((PUCHAR)&(pATEInfo->TssiRefPerChannel), CFG80211_NUM_OF_CHAN_2GHZ); + NdisZeroMemory((PUCHAR)&(pATEInfo->TssiDeltaPerChannel), CFG80211_NUM_OF_CHAN_2GHZ); +#endif /* defined(RT3350) || defined(RT3352) */ +#endif /* RTMP_INTERNAL_TX_ALC */ + /* Default TXCONT/TXCARR/TXCARS mechanism is TX_METHOD_1 */ + pATEInfo->TxMethod = TX_METHOD_1; + if ((IS_RT2070(pAd) || IS_RT2860(pAd) || IS_RT2872(pAd) || IS_RT2883(pAd))) + { + /* Early chipsets must be applied original TXCONT/TXCARR/TXCARS mechanism. */ + pATEInfo->TxMethod = TX_METHOD_0; + } + + /* Power range is 0~31 in A band. */ + pATEInfo->MinTxPowerBandA = 0; + pATEInfo->MaxTxPowerBandA = 31; + if ((IS_RT2860(pAd)) || (IS_RT2872(pAd)) || (IS_RT2883(pAd))) + { + /* Power range of early chipsets is -7~15 in A band. */ + pATEInfo->MinTxPowerBandA = -7; + pATEInfo->MaxTxPowerBandA = 15; + } + +#ifdef TXBF_SUPPORT + pATEInfo->bTxBF = FALSE; +#endif /* TXBF_SUPPORT */ +#ifdef RTMP_MAC_PCI + pATEInfo->bFWLoading = FALSE; +#endif /* RTMP_MAC_PCI */ + + + +#ifdef RALINK_QA + pATEInfo->TxStatus = 0; + RtmpOsTaskPidInit(&(pATEInfo->AtePid)); +/* pATEInfo->AtePid = THREAD_PID_INIT_VALUE; */ +#endif /* RALINK_QA */ + pATEInfo->OneSecPeriodicRound = 0; + pATEInfo->PeriodicRound = 0; + + return NDIS_STATUS_SUCCESS; +} + + +#ifdef RALINK_QA +/* +========================================================================== + Description: + This routine is specific for ATE. + When we start tx from QA GUI, it will modify BBP registers without + notify ATE driver what the tx subtype is. + + Return: + VOID +========================================================================== +*/ +VOID ReadQATxTypeFromBBP( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR Bbp22Value = 0, Bbp24Value = 0; + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &Bbp22Value); + + switch (Bbp22Value) + { + case BBP22_TXFRAME: + { +#ifdef RTMP_MAC_PCI + if (pATEInfo->TxCount == 0) + { + pATEInfo->TxCount = 0xFFFFFFFF; + } +#endif /* RTMP_MAC_PCI */ + DBGPRINT(RT_DEBUG_TRACE,("START TXFRAME\n")); + pATEInfo->bQATxStart = TRUE; + Set_ATE_Proc(pAd, "TXFRAME"); + } + break; + + case BBP22_TXCONT_OR_CARRSUPP: + { + DBGPRINT(RT_DEBUG_TRACE,("BBP22_TXCONT_OR_CARRSUPP\n")); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R24, &Bbp24Value); + + switch (Bbp24Value) + { + case BBP24_TXCONT: + { + DBGPRINT(RT_DEBUG_TRACE,("START TXCONT\n")); + pATEInfo->bQATxStart = TRUE; + + if (pATEInfo->TxMethod == TX_METHOD_0) + { + Set_ATE_Proc(pAd, "TXCONT"); + } + } + break; + + case BBP24_CARRSUPP: + { + DBGPRINT(RT_DEBUG_TRACE,("START TXCARRSUPP\n")); + pATEInfo->bQATxStart = TRUE; + + if (pATEInfo->TxMethod == TX_METHOD_0) + { + Set_ATE_Proc(pAd, "TXCARS"); + } + } + break; + + default: + { + DBGPRINT_ERR(("Unknown TX subtype !\n")); + } + break; + } + } + break; + + case BBP22_TXCARR: + { + DBGPRINT(RT_DEBUG_TRACE,("START TXCARR\n")); + pATEInfo->bQATxStart = TRUE; + + if (pATEInfo->TxMethod == TX_METHOD_0) + { + Set_ATE_Proc(pAd, "TXCARR"); + } + } + break; + + default: + { + DBGPRINT_ERR(("Unknown Start TX subtype !\n")); + } + break; + } + + return; +} +#endif /* RALINK_QA */ + + +NDIS_STATUS ATEBBPWriteWithRxChain( + 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) < 0x28830000) || + (pAd->Antenna.field.RxPath == 1)) + { + ATE_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) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R27, &val); + val = (val & (~0x60)/* clear bit5 and bit6 */) | (idx << 5); + +#ifdef RTMP_MAC_PCI + if (IS_PCI_INF(pAd) || IS_RBUS_INF(pAd)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, val); + ATE_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; +} + + +#define SMM_BASEADDR 0x4000 +#define PKT_BASEADDR 0x8000 + + +INT Set_ADCDump_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR BBP_R21_Ori=0,BBP_R60_Ori=0,BBP_R142_ORI=0,BBP_R143_ORI=0; + UINT32 MACValue=0,PBF_SYS_CTRL_ORI=0,PBF_CAP_CTRL_ORI=0; + UINT32 CaptureModeOffset=0,CaptureStartAddr=0; + UINT32 SMM_Addr; + UINT32 PKT_Addr; + int i = 0; + PSTRING src = "ADCDump.txt"; + RTMP_OS_FD srcf; + RTMP_OS_FS_INFO osFSInfo; + UCHAR msg[128]; + UCHAR msg1[128]; + CAPTURE_MODE_SHARE_MEMORY SMMValued; + CAPTURE_MODE_PACKET_BUFFER PKTValue1d; + CAPTURE_MODE_PACKET_BUFFER PKTValue2d; + UCHAR retval=0; + UCHAR DataSourceADC6=simple_strtol(arg, 0, 10); + + pAd->ate.Mode = ATE_START; + + /* Disable Tx/Rx */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x00); + BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &BBP_R21_Ori); + + /* Disable BBP power saving */ + + /* disable all Tx/Rx Queue */ + RTMP_IO_WRITE32(pAd, PBF_CFG, 0x00000000); + + /* capture mode */ + RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &MACValue); + PBF_SYS_CTRL_ORI=MACValue; + MACValue |= 0x00004000; /* bit[14]=1 */ + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, MACValue); + + /* capture setting */ + if (DataSourceADC6 == 1) + { + BBP_IO_READ8_BY_REG_ID(pAd, BBP_R60, &BBP_R60_Ori); + BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R60, 0x80); + BBP_IO_READ8_BY_REG_ID(pAd, BBP_R142, &BBP_R142_ORI); + BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R142, 0x10); + BBP_IO_READ8_BY_REG_ID(pAd, BBP_R143, &BBP_R143_ORI); + BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R143, 0x05); + + RTMP_IO_READ32(pAd, PBF_CAP_CTRL, &MACValue); + PBF_CAP_CTRL_ORI=MACValue; + MACValue |= 0x00008000; /* set bit[15]=1 for ADC 6 */ + MACValue &= ~0x80000000; /* set bit[31]=0 */ + RTMP_IO_WRITE32(pAd, PBF_CAP_CTRL, MACValue); + } + else + { + RTMP_IO_READ32(pAd, PBF_CAP_CTRL, &MACValue); + PBF_CAP_CTRL_ORI=MACValue; + MACValue &= ~0x80008000; /* set bit[31]=0, bit[15]=0 for ADC 8 */ + RTMP_IO_WRITE32(pAd, PBF_CAP_CTRL, MACValue); + } + + /* trigger offset */ + RTMP_IO_READ32(pAd, PBF_CAP_CTRL, &MACValue); + MACValue &= ~(0x1FFF0000); + RTMP_IO_WRITE32(pAd, PBF_CAP_CTRL, MACValue); + + if ((CaptureModeOffset > 0) && (CaptureModeOffset <= 0x1FFF)) + { + RTMP_IO_READ32(pAd, PBF_CAP_CTRL, &MACValue); + MACValue |= CaptureModeOffset << 16; + RTMP_IO_WRITE32(pAd, PBF_CAP_CTRL, MACValue); + } + + /* start capture */ + RTMP_IO_READ32(pAd, PBF_CAP_CTRL, &MACValue); + MACValue = MACValue | 0x40000000; /* set bit[30]=1 */ + RTMP_IO_WRITE32(pAd, PBF_CAP_CTRL, MACValue); + + if (0) + { + /* start TX */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4); + } + else + { + /* start RX */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x8); + } + + /* Wait until [0x440] bit30=0 */ + do + { + i++; + RTMPusecDelay(10); + RTMP_IO_READ32(pAd, PBF_CAP_CTRL, &MACValue); + MACValue = MACValue & 0x40000000; /* bit[30] */ + + if (MACValue == 0) + { + break; + } + + if (i == 1000) /* 3 sec */ + { + printk("Error, over 3s\n"); + break; + } + } while (MACValue != 0); + + if (DataSourceADC6 == 1) + { + /* restore BBP R60 */ + BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R60, BBP_R60_Ori); + } + + /* Stop TX/RX */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); + + /* Read [0x440] bit[12:0] */ + RTMP_IO_READ32(pAd, PBF_CAP_CTRL, &CaptureStartAddr); + CaptureStartAddr = CaptureStartAddr & 0x00001FFF; + + /* Dump data from MAC memory */ + RtmpOSFSInfoChange(&osFSInfo, TRUE); + + SMM_Addr=SMM_BASEADDR+CaptureStartAddr*2; + PKT_Addr=PKT_BASEADDR+CaptureStartAddr*4; + + /* SMM Address must be four byte alignment*/ + SMM_Addr=(SMM_Addr/4)*4; + + /* open file */ + if (src && *src) + { + srcf = RtmpOSFileOpen(src, O_WRONLY|O_CREAT, 0); + + if (IS_FILE_OPEN_ERR(srcf)) + { + DBGPRINT(RT_DEBUG_ERROR, ("--> Error opening %s\n", src)); + return FALSE; + } + else + { + memset(msg, 0x00, 128); + memset(msg1, 0x00, 128); + + for (i=0;i<0x1000;i++) + { + RTMP_IO_READ32(pAd,SMM_Addr, &SMMValued.Value); + SMM_Addr += 4; + + if(SMM_Addr >= 0x8000) + SMM_Addr = SMM_Addr - SMM_BASEADDR; + + RTMP_IO_READ32(pAd,PKT_Addr, &PKTValue1d.Value); + PKT_Addr += 4; + + if(PKT_Addr >= 0x10000) + PKT_Addr = PKT_Addr - PKT_BASEADDR; + + RTMP_IO_READ32(pAd,PKT_Addr, &PKTValue2d.Value); + PKT_Addr += 4; + + if(PKT_Addr >= 0x10000) + PKT_Addr = PKT_Addr - PKT_BASEADDR; + + sprintf(msg, "%d %d %d %d %d %d\n",SMMValued.field.LOW_BYTE1,SMMValued.field.LOW_BYTE0 + ,PKTValue1d.field.BYTE3,PKTValue1d.field.BYTE2 + ,PKTValue1d.field.BYTE1,PKTValue1d.field.BYTE0); + sprintf(msg1, "%d %d %d %d %d %d\n",SMMValued.field.LOW_BYTE1,SMMValued.field.LOW_BYTE0 + ,PKTValue2d.field.BYTE3,PKTValue2d.field.BYTE2 + ,PKTValue2d.field.BYTE1,PKTValue2d.field.BYTE0); + + retval=RtmpOSFileWrite(srcf, (PSTRING)msg, strlen(msg)); + retval=RtmpOSFileWrite(srcf, (PSTRING)msg1, strlen(msg1)); + } + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("--> Error src or srcf is null\n")); + return FALSE; + } + + retval=RtmpOSFileClose(srcf); + + if (retval) + { + DBGPRINT(RT_DEBUG_TRACE, ("--> Error %d closing %s\n", -retval, src)); + } + + RtmpOSFSInfoChange(&osFSInfo, FALSE); + + BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BBP_R21_Ori); + BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R60, BBP_R60_Ori); + + BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R142, BBP_R142_ORI); + BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R142, BBP_R142_ORI); + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, PBF_SYS_CTRL_ORI); + RTMP_IO_WRITE32(pAd, PBF_CAP_CTRL, PBF_CAP_CTRL_ORI); + + /* Finish */ + /* normal mode */ + RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &MACValue); + MACValue &= ~0x00004000; + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, MACValue); + + /* reset packet buffer */ + RTMP_IO_WRITE32(pAd, PBF_CTRL,0x00000020 ); + + /* enable Tx/Rx Queue */ + RTMP_IO_WRITE32(pAd, PBF_CFG, 0x00F40016); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0C); + pAd->ate.Mode = ATE_STOP; + + return TRUE; +} + + +/* 0.1-second periodic execution */ +VOID ATEPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext; + PATE_INFO pATEInfo = &(pAd->ate); + + if (ATE_ON(pAd)) + { + pATEInfo->PeriodicRound++; + +#ifdef RT6352 + if (IS_RT6352(pAd)) + { +#ifdef RTMP_TEMPERATURE_CALIBRATION + if ((pATEInfo->bAutoTxAlc == FALSE) && (pATEInfo->bQAEnabled == FALSE)) + { + if (pATEInfo->bLowTemperature == TRUE) + { + INT32 wait; + CHAR BbpR49; + UINT8 BBPValue; + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + + if (!(BBPValue & (1<<4))) + { + BBPValue |= (1<<4); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + } + + /* polling BBP_R47 until BBP R47[4]==0 */ + for (wait=0; wait<200; wait++) + { + RTMPusecDelay(200); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + + if (!(BBPValue & (1<<4))) + { + break; + } + } + + if ((BBPValue & 0x10) != 0) + return; + + /* set BBP R47[3:0]=4 */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue &= ~(0x0F); + BBPValue |= (0x04); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + /* fetch temperature reading */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); + pAd->CurrTemperature = (INT32)BbpR49; + DBGPRINT(RT_DEBUG_INFO, ("%s: Current Temperature from BBP_R49=0x%x\n", __FUNCTION__, pAd->CurrTemperature)); + } + } + else +#endif /* RTMP_TEMPERATURE_CALIBRATION */ + if ((pATEInfo->bAutoTxAlc == TRUE) && (pATEInfo->Mode == ATE_TXFRAME)) + { + OS_SEM_LOCK(&(pATEInfo->TssiSemLock)); + /* For MT7620, let QA come in for TSSI */ + ATEAsicAdjustTxPower(pAd); + OS_SEM_UNLOCK(&(pATEInfo->TssiSemLock)); + ATEAsicExtraPowerOverMAC(pAd); +#ifdef RT6352_EP_SUPPORT + if (pAd->bExtPA == FALSE) + { +#endif /* RT6352_EP_SUPPORT */ + if (pATEInfo->bDPDEnable == TRUE) + { + if (pATEInfo->TxAntennaSel == ANT_0) /* TX0 */ + Set_TestDPDCalibrationTX0_Proc(pAd, "9"); + else if (pATEInfo->TxAntennaSel == ANT_1) /* TX1 */ + Set_TestDPDCalibrationTX1_Proc(pAd, "9"); + else /* both TX */ + Set_TestDPDCalibration_Proc(pAd, "9"); /* both TX */ + } +#ifdef RT6352_EP_SUPPORT + } +#endif /* RT6352_EP_SUPPORT */ + } + +#ifdef RTMP_TEMPERATURE_CALIBRATION + if (pATEInfo->bQAEnabled == FALSE) + { + if (pATEInfo->bLowTemperature == TRUE) + { + RT6352_TemperatureCalibration(pAd); + } + } +#endif /* RTMP_TEMPERATURE_CALIBRATION */ + } +#endif /* RT6352 */ + + if ((pATEInfo->bQAEnabled == FALSE) && (!IS_RT6352(pAd))) + { + if ((pATEInfo->bAutoTxAlc == TRUE) && (pATEInfo->Mode == ATE_TXFRAME)) + { + ATEAsicAdjustTxPower(pAd); + } + } + + ATEAsicExtraPowerOverMAC(pAd); + + /* Normal 1 second ATE PeriodicExec.*/ + if (pATEInfo->PeriodicRound % (ATE_TASK_EXEC_MULTIPLE) == 0) + { + pATEInfo->OneSecPeriodicRound++; + + /* for performace enchanement */ + NdisZeroMemory(&pAd->RalinkCounters, + (UINT32)&pAd->RalinkCounters.OneSecEnd - + (UINT32)&pAd->RalinkCounters.OneSecStart); + NICUpdateRawCounters(pAd); + + if (pATEInfo->bRxFER == 1) + { + pATEInfo->RxTotalCnt += pATEInfo->RxCntPerSec; + ate_print(KERN_EMERG "ATEPeriodicExec: Rx packet cnt = %d/%d\n", + pATEInfo->RxCntPerSec, pATEInfo->RxTotalCnt); + pATEInfo->RxCntPerSec = 0; + + if (pATEInfo->RxAntennaSel == 0) + ate_print(KERN_EMERG "ATEPeriodicExec: Rx AvgRssi0=%d, AvgRssi1=%d, AvgRssi2=%d\n\n", + pATEInfo->AvgRssi0, pATEInfo->AvgRssi1, pATEInfo->AvgRssi2); + else + ate_print(KERN_EMERG "ATEPeriodicExec: Rx AvgRssi=%d\n\n", pATEInfo->AvgRssi0); + } + + MlmeResetRalinkCounters(pAd); + + /* In QA Mode, QA will handle all registers. */ + if (pATEInfo->bQAEnabled == TRUE) + { + return; + } + +#if (defined(RT3052) && !defined(RT3352)) || defined(RT3070) + /* request by Gary, if Rssi0 > -42, BBP 82 need to be changed from 0x62 to 0x42, , bbp 67 need to be changed from 0x20 to 0x18*/ + if ((!pAd->CommonCfg.HighPowerPatchDisabled) +#ifdef RT3052 + && (IS_RT3052B(pAd)) +#endif /* RT3052 */ + ) + { + { + if ((pATEInfo->AvgRssi0 != 0) && (pATEInfo->AvgRssi0 > (pAd->BbpRssiToDbmDelta - 35))) + { + RT30xxWriteRFRegister(pAd, RF_R27, 0x20); + } + else + { + RT30xxWriteRFRegister(pAd, RF_R27, 0x23); + } + } + +#ifdef RT3052 + if (pAd->Antenna.field.RxPath == 2) + { + if ((pATEInfo->AvgRssi0 != 0) && (pATEInfo->AvgRssi0 > (pAd->BbpRssiToDbmDelta - 42) )) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x42); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R67, 0x18); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R67, 0x20); + } + } +#endif /* RT3052 */ + } +#endif /* RT305x */ + } + } + else + { + DBGPRINT_ERR(("%s is NOT called in ATE mode.\n", __FUNCTION__)); + } + + return; +} + + diff --git a/mt7620/src/ate/common/rt_qa.c b/mt7620/src/ate/common/rt_qa.c new file mode 100644 index 0000000..e1156b4 --- /dev/null +++ b/mt7620/src/ate/common/rt_qa.c @@ -0,0 +1,3634 @@ +/* + *************************************************************************** + * 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_qa.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ +#include "rt_config.h" + +#ifdef RALINK_QA +NDIS_STATUS TXSTOP( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 MacData=0, atemode=0; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; +#ifdef RTMP_MAC_PCI + UINT32 ring_index=0; + PTXD_STRUC pTxD = NULL; + PRTMP_TX_RING pTxRing = &pAd->TxRing[QID_AC_BE]; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD = NULL; + TXD_STRUC TxD; +#endif /* RT_BIG_ENDIAN */ +#endif /* RTMP_MAC_PCI */ + UCHAR BbpData = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("ATE : ===> %s\n", __FUNCTION__)); + + atemode = pATEInfo->Mode; + pATEInfo->Mode &= ATE_TXSTOP; + pATEInfo->bQATxStart = FALSE; + + if (atemode == ATE_TXCARR) + { + if (pATEInfo->TxMethod == TX_METHOD_0) + { + /* No Carrier Test set BBP R22 bit7=0, bit6=0, bit[5~0]=0x0 */ + ATE_BBP_RESET_TX_MODE(pAd, BBP_R22, &BbpData); + } + } + else if (atemode == ATE_TXCARRSUPP) + { + if (pATEInfo->TxMethod == TX_METHOD_0) + { + /* No Cont. TX set BBP R22 bit7=0 */ + /* QA will do this in new TXCARRSUPP proposal */ + ATE_BBP_STOP_CTS_TX_MODE(pAd, BBP_R22, &BbpData); + + /* No Carrier Suppression set BBP R24 bit0=0 */ + ATE_BBP_CTS_TX_SIN_WAVE_DISABLE(pAd, BBP_R24, &BbpData); + } + } + + /* + We should free some resource which was allocated + when ATE_TXFRAME, ATE_STOP, and ATE_TXCONT. + */ + else if ((atemode & ATE_TXFRAME) || (atemode == ATE_STOP)) + { + if (atemode == ATE_TXCONT) + { + if (pATEInfo->TxMethod == TX_METHOD_0) + { + /* No Cont. TX set BBP R22 bit7=0 */ + /* QA will do this in new TXCONT proposal */ + ATE_BBP_STOP_CTS_TX_MODE(pAd, BBP_R22, &BbpData); + } + } + +#ifdef RTMP_MAC_PCI + /* Abort Tx, Rx DMA. */ + RtmpDmaEnable(pAd, 0); + + for (ring_index=0; ring_indexTxRing[QID_AC_BE].Cell[ring_index].AllocVa; +#else + pDestTxD = (PTXD_STRUC)pAd->TxRing[QID_AC_BE].Cell[ring_index].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif /* !RT_BIG_ENDIAN */ + pTxD->DMADONE = 0; + pPacket = pTxRing->Cell[ring_index].pNdisPacket; + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + + /* Always assign pNdisPacket as NULL after clear */ + pTxRing->Cell[ring_index].pNdisPacket = NULL; + + pPacket = pTxRing->Cell[ring_index].pNextNdisPacket; + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + + /* Always assign pNextNdisPacket as NULL after clear */ + pTxRing->Cell[ring_index].pNextNdisPacket = NULL; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif /* RT_BIG_ENDIAN */ + } + /* Enable Tx, Rx DMA */ + RtmpDmaEnable(pAd, 1); +#endif /* RTMP_MAC_PCI */ + + } + + /* task Tx status : 0 --> task is idle, 1 --> task is running */ + pATEInfo->TxStatus = 0; + + if (pATEInfo->TxMethod == TX_METHOD_0) + { + BbpSoftReset(pAd);/* Soft reset BBP. */ + } + + /* Disable Tx */ + ATE_MAC_TX_DISABLE(pAd, MAC_SYS_CTRL, &MacData); + + + DBGPRINT(RT_DEBUG_TRACE, ("ATE : <=== %s\n", __FUNCTION__)); + return Status; +} + + +NDIS_STATUS RXSTOP( + IN PRTMP_ADAPTER pAd) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 MacData=0; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + + DBGPRINT(RT_DEBUG_TRACE, ("ATE : ===> %s\n", __FUNCTION__)); + + /* Disable Rx */ + ATE_MAC_RX_DISABLE(pAd, MAC_SYS_CTRL, &MacData); + + pATEInfo->Mode &= ATE_RXSTOP; + pATEInfo->bQARxStart = FALSE; + + + if ((!IS_RT3883(pAd)) && (!IS_RT3352(pAd)) && (!IS_RT5350(pAd))) + BbpSoftReset(pAd);/* Soft reset BBP. */ + + DBGPRINT(RT_DEBUG_TRACE, ("ATE : <=== %s\n", __FUNCTION__)); + return Status; +} + + +static VOID memcpy_exl(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len) +{ + UINT32 i, Value = 0; + UCHAR *pDst = NULL, *pSrc = NULL; + + for (i = 0 ; i < (len >> 2); i++) + { + pDst = (dst + i*4); + pSrc = (src + i*4); + /* For alignment issue, we need a variable "Value". */ + memmove(&Value, pSrc, 4); + Value = OS_HTONL(Value); + memmove(pDst, &Value, 4); + pDst += 4; + pSrc += 4; + } + + if ((len % 4) != 0) + { + /* wish that it will never reach here */ + memmove(&Value, pSrc, (len % 4)); + Value = OS_HTONL(Value); + memmove(pDst, &Value, (len % 4)); + } +} + + +static VOID memcpy_exs(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len) +{ + ULONG i; +#if defined(RT2883) || defined(RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + { + UCHAR *pDst, *pSrc; + + pDst = dst; + pSrc = src; + + for (i = 0; i < (len >> 1); i++) + { + memmove(pDst, pSrc, 2); + *((USHORT *)pDst) = OS_HTONS(*((USHORT *)pDst)); + pDst+=2; + pSrc+=2; + } + + if ((len % 2) != 0) + { + memmove(pDst, pSrc, 1); + } + } + else +#endif /* defined(RT2883) || defined(RT3883) */ + { + USHORT *pDst, *pSrc; + + pDst = (USHORT *) dst; + pSrc = (USHORT *) src; + + for (i =0; i < (len >> 1); i++) + { + *pDst = OS_NTOHS(*pSrc); + pDst++; + pSrc++; + } + + if ((len % 2) != 0) + { + memcpy(pDst, pSrc, (len % 2)); + *pDst = OS_NTOHS(*pDst); + } + } + return; +} + + +static VOID RTMP_IO_READ_BULK(PRTMP_ADAPTER pAd, UCHAR *dst, UINT32 offset, UINT32 len) +{ + UINT32 index, Value = 0; + UCHAR *pDst; + + DBGPRINT(RT_DEBUG_WARN,("\n\n")); + for (index = 0 ; index < (len >> 2); index++) + { + pDst = (dst + (index << 2)); + RTMP_IO_READ32(pAd, offset, &Value); + DBGPRINT(RT_DEBUG_WARN,("mac r 0x%04X=0x%08X\n", offset, Value)); + + Value = OS_HTONL(Value); + memmove(pDst, &Value, 4); + offset += 4; + } + DBGPRINT(RT_DEBUG_WARN,("\n\n")); + + return; +} + + +VOID BubbleSort(INT32 size, INT32 array[]) +{ + INT32 outer, inner, temp; + + for (outer = size-1; outer>0; outer--) + { + for (inner = 0; inner array[inner+1]) + { + temp = array[inner]; + array[inner]=array[inner+1]; + array[inner+1]=temp; + } + } + } + return; +} + + +VOID CalNoiseLevel(PRTMP_ADAPTER pAd, UCHAR channel, INT32 RSSI[3][10]) +{ + PATE_INFO pATEInfo = &(pAd->ate); + INT32 RSSI0, RSSI1, RSSI2; + CHAR Rssi0Offset, Rssi1Offset, Rssi2Offset; + UCHAR BbpR50Rssi0 = 0, BbpR51Rssi1 = 0, BbpR52Rssi2 = 0; + UCHAR Org_BBP66value = 0, Org_BBP69value = 0, Org_BBP70value = 0, data = 0; +#if defined(RT2883) || defined(RT3883) || defined(RT3352) || defined(RT5350) + UCHAR byteValue = 0; +#endif /* defined(RT2883) || defined(RT3883) || defined(RT3352) || defined(RT5350) */ + USHORT LNA_Gain = 0; + INT32 column = 0; + UCHAR Org_Channel = pATEInfo->Channel; + USHORT GainValue = 0, OffsetValue = 0; + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &Org_BBP66value); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R69, &Org_BBP69value); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R70, &Org_BBP70value); + + /************************************************************************/ + /* Read the value of LNA gain and RSSI offset */ + /************************************************************************/ + RT28xx_EEPROM_READ16(pAd, EEPROM_LNA_OFFSET, GainValue); + + /* for Noise Level */ + if (channel <= 14) + { + LNA_Gain = GainValue & 0x00FF; + + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET, OffsetValue); + Rssi0Offset = OffsetValue & 0x00FF; + Rssi1Offset = (OffsetValue & 0xFF00) >> 8; + + RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_BG_OFFSET + 2)/* 0x48 */, OffsetValue); + Rssi2Offset = OffsetValue & 0x00FF; + } + else + { + LNA_Gain = (GainValue & 0xFF00) >> 8; + + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_A_OFFSET, OffsetValue); + Rssi0Offset = OffsetValue & 0x00FF; + Rssi1Offset = (OffsetValue & 0xFF00) >> 8; + + RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_A_OFFSET + 2)/* 0x4C */, OffsetValue); + Rssi2Offset = OffsetValue & 0x00FF; + } + /***********************************************************************/ + { + pATEInfo->Channel = channel; + ATEAsicSwitchChannel(pAd); + RtmpOsMsDelay(5); + + data = 0x10; +#if defined (RT2883) || defined (RT3883) || defined (RT3352) || defined (RT5350) + if (IS_RT2883(pAd) || IS_RT3883(pAd) || IS_RT3352(pAd) || IS_RT5350(pAd)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R27, &byteValue); + byteValue &= 0x9f; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, byteValue); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, data); + } +#ifdef RT3352 + if (IS_RT3352(pAd)) + { + if (pATEInfo->TxWI.BW == BW_20) + { + data = (GET_LNA_GAIN(pAd) << 1) + 0x1C; + } + else + { + data = (GET_LNA_GAIN(pAd) << 1) + 0x24; + } + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, (byteValue | (1 << 5))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, data); + } +#endif /* RT3352 */ +#if defined (RT2883) || defined (RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, (byteValue | (1 << 5))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, data); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, (byteValue | (1 << 6))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, data); + } +#endif /* defined (RT2883) || defined (RT3883) */ +#else + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, data); +#endif /* defined(RT2883) || defined(RT3883) || defined(RT3352) || defined (RT5350) */ + data = 0x40; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, data); + data = 0x40; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, data); + RtmpOsMsDelay(5); + + /* start Rx */ + pATEInfo->bQARxStart = TRUE; + Set_ATE_Proc(pAd, "RXFRAME"); + + RtmpOsMsDelay(5); + + for (column = 0; column < 10; column++) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R50, &BbpR50Rssi0); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R51, &BbpR51Rssi1); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R52, &BbpR52Rssi2); + + RtmpOsMsDelay(10); + + /* calculate RSSI 0 */ + if (BbpR50Rssi0 == 0) + { + RSSI0 = -100; + } + else + { + RSSI0 = (INT32)(-12 - BbpR50Rssi0 - LNA_Gain - Rssi0Offset); + } + RSSI[0][column] = RSSI0; + + if ( pAd->Antenna.field.RxPath >= 2 ) /* 2R */ + { + /* calculate RSSI 1 */ + if (BbpR51Rssi1 == 0) + { + RSSI1 = -100; + } + else + { + RSSI1 = (INT32)(-12 - BbpR51Rssi1 - LNA_Gain - Rssi1Offset); + } + RSSI[1][column] = RSSI1; + } + + if ( pAd->Antenna.field.RxPath >= 3 ) /* 3R */ + { + /* calculate RSSI 2 */ + if (BbpR52Rssi2 == 0) + RSSI2 = -100; + else + RSSI2 = (INT32)(-12 - BbpR52Rssi2 - LNA_Gain - Rssi2Offset); + + RSSI[2][column] = RSSI2; + } + } + + /* stop Rx */ + Set_ATE_Proc(pAd, "RXSTOP"); + + RtmpOsMsDelay(5); + + BubbleSort(10, RSSI[0]); /* 1R */ + + if ( pAd->Antenna.field.RxPath >= 2 ) /* 2R */ + { + BubbleSort(10, RSSI[1]); + } + + if ( pAd->Antenna.field.RxPath >= 3 ) /* 3R */ + { + BubbleSort(10, RSSI[2]); + } + } + + pATEInfo->Channel = Org_Channel; + ATEAsicSwitchChannel(pAd); + + /* restore original value */ +#if defined (RT2883) || defined (RT3883) || defined (RT3352) || defined (RT5350) + if (IS_RT2883(pAd) || IS_RT3883(pAd) || IS_RT3352(pAd) || IS_RT5350(pAd)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R27, &byteValue); + byteValue &= 0x9f; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, byteValue); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, Org_BBP66value); + } +#ifdef RT3352 + if (IS_RT3352(pAd)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, (byteValue | (1 << 5))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, Org_BBP66value); + } +#endif /* RT3352 */ +#if defined (RT2883) || defined (RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, (byteValue | (1 << 5))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, Org_BBP66value); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, (byteValue | (1 << 6))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, Org_BBP66value); + } +#endif /* defined (RT2883) || defined (RT3883) */ +#endif /* defined (RT2883) || defined (RT3883) || defined (RT3352) || defined (RT5350) */ + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, Org_BBP69value); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, Org_BBP70value); + + return; +} + + +static VOID ATE_BBPRead( + IN PRTMP_ADAPTER pAd, + IN UCHAR offset, + IN UCHAR *pValue) +{ + if (ATE_ON(pAd)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, offset, pValue); + } + else + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, offset, pValue); + } +} + + +static VOID ATE_BBPWrite( + IN PRTMP_ADAPTER pAd, + IN UCHAR offset, + IN UCHAR value) +{ + if (ATE_ON(pAd)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, offset, value); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, offset, value); + } +} + + +BOOLEAN SyncTxRxConfig(PRTMP_ADAPTER pAd, USHORT offset, UCHAR value) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR tmp = 0, bbp_data = 0; + + ATE_BBPRead(pAd, offset, &bbp_data); + + /* confirm again */ + ASSERT(bbp_data == value); + + switch (offset) + { + case BBP_R1: + /* Need to synchronize tx configuration with legacy ATE. */ + tmp = (bbp_data & ((1 << 4) | (1 << 3))/* 0x18 */) >> 3; + switch (tmp) + { + /* The BBP R1 bit[4:3] = 2 :: Both DACs will be used by QA. */ + case 2: + /* All */ + pATEInfo->TxAntennaSel = 0; + break; + /* The BBP R1 bit[4:3] = 0 :: DAC 0 will be used by QA. */ + case 0: + /* Antenna one */ + pATEInfo->TxAntennaSel = 1; + break; + /* The BBP R1 bit[4:3] = 1 :: DAC 1 will be used by QA. */ + case 1: + /* Antenna two */ + pATEInfo->TxAntennaSel = 2; + break; + default: + DBGPRINT_ERR(("%s -- Sth. wrong! : return FALSE; \n", __FUNCTION__)); + return FALSE; + } + break;/* case BBP_R1 */ + + case BBP_R3: + /* Need to synchronize rx configuration with legacy ATE. */ + tmp = (bbp_data & ((1 << 1) | (1 << 0))/* 0x03 */); + switch(tmp) + { + /* The BBP R3 bit[1:0] = 3 :: All ADCs will be used by QA. */ + case 3: + /* All */ + pATEInfo->RxAntennaSel = 0; + break; + /* + The BBP R3 bit[1:0] = 0 :: ADC 0 will be used by QA, + unless the BBP R3 bit[4:3] = 2 + */ + case 0: + /* Antenna one */ + pATEInfo->RxAntennaSel = 1; + tmp = ((bbp_data & ((1 << 4) | (1 << 3))/* 0x03 */) >> 3); + if (tmp == 2) /* 3R */ + { + /* Default : All ADCs will be used by QA */ + pATEInfo->RxAntennaSel = 0; + } + break; + /* The BBP R3 bit[1:0] = 1 :: ADC 1 will be used by QA. */ + case 1: + /* Antenna two */ + pATEInfo->RxAntennaSel = 2; + break; + /* The BBP R3 bit[1:0] = 2 :: ADC 2 will be used by QA. */ + case 2: + /* Antenna three */ + pATEInfo->RxAntennaSel = 3; + break; + default: + DBGPRINT_ERR(("%s -- Impossible! : return FALSE; \n", __FUNCTION__)); + return FALSE; + } + break;/* case BBP_R3 */ + + default: + DBGPRINT_ERR(("%s -- Sth. wrong! : return FALSE; \n", __FUNCTION__)); + return FALSE; + + } + return TRUE; +} + + +static INT ResponseToGUI( + IN struct ate_racfghdr *pRaCfg, + IN RTMP_IOCTL_INPUT_STRUCT *pwrq, + IN INT Length, + IN INT Status) +{ + (pRaCfg)->length = OS_HTONS((Length)); + (pRaCfg)->status = OS_HTONS((Status)); + (pwrq)->u.data.length = sizeof((pRaCfg)->magic_no) + sizeof((pRaCfg)->command_type) + + sizeof((pRaCfg)->command_id) + sizeof((pRaCfg)->length) + + sizeof((pRaCfg)->sequence) + OS_NTOHS((pRaCfg)->length); + + if (copy_to_user((pwrq)->u.data.pointer, (UCHAR *)(pRaCfg), (pwrq)->u.data.length)) + { + + DBGPRINT_ERR(("copy_to_user() fail in %s\n", __FUNCTION__)); + return (-EFAULT); + } + else + { + } + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_START( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START\n")); + + pATEInfo->bQAEnabled = TRUE; + DBGPRINT(RT_DEBUG_TRACE,("pATEInfo->bQAEnabled = %s\n", (pATEInfo->bQAEnabled)? "TRUE":"FALSE")); + + /* Prepare feedback as soon as we can to avoid QA timeout. */ + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + +#ifdef CONFIG_RT2880_ATE_CMD_NEW + Set_ATE_Proc(pAd, "ATESTART"); +#else + Set_ATE_Proc(pAd, "APSTOP"); +#endif /* CONFIG_RT2880_ATE_CMD_NEW */ + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_STOP( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_STOP\n")); + + pATEInfo->bQAEnabled = FALSE; + DBGPRINT(RT_DEBUG_TRACE,("pATEInfo->bQAEnabled = %s\n", (pATEInfo->bQAEnabled)? "TRUE":"FALSE")); + + /* + Distinguish this command came from QA(via ate agent) + or ate agent according to the existence of pid in payload. + + No need to prepare feedback if this cmd came directly from ate agent, + not from QA. + */ + pRaCfg->length = OS_NTOHS(pRaCfg->length); + + if (pRaCfg->length == sizeof(pATEInfo->AtePid)) + { + /* + This command came from QA. + Get the pid of ATE agent. + */ + memcpy((UCHAR *)&pATEInfo->AtePid, + (&pRaCfg->data[0]) - 2/* == sizeof(pRaCfg->status) */, + sizeof(pATEInfo->AtePid)); + + /* Prepare feedback as soon as we can to avoid QA timeout. */ + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + } + + + /* AP/STA may be already in ATE_STOP mode due to cmd from QA. */ + if (ATE_ON(pAd)) + { + /* Someone has killed ate agent while QA GUI is still open. */ + +#ifdef CONFIG_RT2880_ATE_CMD_NEW + Set_ATE_Proc(pAd, "ATESTOP"); +#else + Set_ATE_Proc(pAd, "APSTART"); +#endif + DBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_AP_START is done !\n")); + } + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_RF_WRITE_ALL( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + UINT32 R1, R2, R3, R4; + USHORT channel; + + memcpy(&R1, pRaCfg->data-2, 4); + memcpy(&R2, pRaCfg->data+2, 4); + memcpy(&R3, pRaCfg->data+6, 4); + memcpy(&R4, pRaCfg->data+10, 4); + memcpy(&channel, pRaCfg->data+14, 2); + + pAd->LatchRfRegs.R1 = OS_NTOHL(R1); + pAd->LatchRfRegs.R2 = OS_NTOHL(R2); + pAd->LatchRfRegs.R3 = OS_NTOHL(R3); + pAd->LatchRfRegs.R4 = OS_NTOHL(R4); + pAd->LatchRfRegs.Channel = OS_NTOHS(channel); + + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R3); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_E2PROM_READ16( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + UINT16 offset=0, value=0; + USHORT tmp=0; + + offset = OS_NTOHS(pRaCfg->status); + RT28xx_EEPROM_READ16(pAd, offset, tmp); + value = tmp; + DBGPRINT(RT_DEBUG_WARN,("e2p r %02Xh=0x%02X\n" + , (offset&0x00FF), (value&0x00FF))); + DBGPRINT(RT_DEBUG_WARN,("e2p r %02Xh=0x%02X\n" + , (offset&0x00FF)+1, (value&0xFF00)>>8)); + value = OS_HTONS(value); + + memcpy(pRaCfg->data, &value, 2); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status)+2, NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_E2PROM_WRITE16( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + USHORT offset, value; + + offset = OS_NTOHS(pRaCfg->status); + memcpy(&value, pRaCfg->data, 2); + value = OS_NTOHS(value); + RT28xx_EEPROM_WRITE16(pAd, offset, value); + DBGPRINT(RT_DEBUG_WARN,("e2p w 0x%04X=0x%04X\n", offset, value)); + DBGPRINT(RT_DEBUG_WARN,("e2p w %02Xh=0x%02X\n" + , (offset&0x00FF), (value&0x00FF))); + DBGPRINT(RT_DEBUG_WARN,("e2p w %02Xh=0x%02X\n" + , (offset&0x00FF)+1, (value&0xFF00)>>8)); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_E2PROM_READ_ALL( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + USHORT buffer[EEPROM_SIZE >> 1]; + + rt_ee_read_all(pAd,(USHORT *)buffer); + memcpy_exs(pAd, pRaCfg->data, (UCHAR *)buffer, EEPROM_SIZE); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status)+EEPROM_SIZE, NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_E2PROM_WRITE_ALL( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + USHORT buffer[EEPROM_SIZE >> 1]; + + NdisZeroMemory((UCHAR *)buffer, EEPROM_SIZE); + memcpy_exs(pAd, (UCHAR *)buffer, (UCHAR *)&pRaCfg->status, EEPROM_SIZE); + rt_ee_write_all(pAd,(USHORT *)buffer); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_IO_READ( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + UINT32 offset; + UINT32 value; +#ifdef RT6352 + RF_CSR_CFG_STRUC rfcsr = { { 0 } }; + UCHAR bank, regID, rfValue; +#endif /* RT6352 */ + + memcpy(&offset, &pRaCfg->status, 4); + offset = OS_NTOHL(offset); + +#ifdef RTMP_RBUS_SUPPORT + if ((offset & 0xFFFF0000) == 0x10000000) + { + RTMP_SYS_IO_READ32(offset | 0xa0000000, &value); + DBGPRINT(RT_DEBUG_WARN,("mac r 0x%08X=0x%08X\n", offset | 0xa0000000, value)); + } + else +#endif /* RTMP_RBUS_SUPPORT */ + { + /* + We do not need the base address. + So just extract the offset out. + */ + offset &= 0x0000FFFF; + RTMP_IO_READ32(pAd, offset, &value); + +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + if (offset == RF_CSR_CFG) + { + rfcsr = (RF_CSR_CFG_STRUC)value; + regID = (UCHAR)(rfcsr.field.TESTCSR_RFACC_REGNUM & 0x0000003F); + bank = (UCHAR)((rfcsr.field.TESTCSR_RFACC_REGNUM & 0x000003FF) >> 6); + rfValue = (UCHAR)(rfcsr.field.RF_CSR_DATA); + DBGPRINT(RT_DEBUG_WARN,("rf%u r R%u=0x%02X\n", bank, regID, rfValue)); + } + else + { + DBGPRINT(RT_DEBUG_WARN,("mac r 0x%04X=0x%08X\n", offset, value)); + } + } +#endif /* RT6352 */ +#ifndef RT6352 + DBGPRINT(RT_DEBUG_WARN,("mac r 0x%04X=0x%08X\n", offset, value)); +#endif /* !RT6352 */ + } + value = OS_HTONL(value); + memcpy(pRaCfg->data, &value, 4); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status)+4, NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_IO_WRITE( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + UINT32 offset, value; +#ifdef RT6352 + RF_CSR_CFG_STRUC rfcsr = { { 0 } }; + UCHAR bank, regID, rfValue; +#endif /* RT6352 */ + + memcpy(&offset, pRaCfg->data-2, 4); + memcpy(&value, pRaCfg->data+2, 4); + + offset = OS_NTOHL(offset); + + /* + We do not need the base address. + So just extract the offset out. + */ + offset &= 0x0000FFFF; + value = OS_NTOHL(value); + + RTMP_IO_WRITE32(pAd, offset, value); + +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + if (offset == RF_CSR_CFG) + { + rfcsr = (RF_CSR_CFG_STRUC)value; + regID = (UCHAR)(rfcsr.field.TESTCSR_RFACC_REGNUM & 0x0000003F); + bank = (UCHAR)((rfcsr.field.TESTCSR_RFACC_REGNUM & 0x000003FF) >> 6); + rfValue = (UCHAR)(rfcsr.field.RF_CSR_DATA); + DBGPRINT(RT_DEBUG_WARN,("rf%u w R%u=0x%02X\n", bank, regID, rfValue)); + } + else + { + DBGPRINT(RT_DEBUG_WARN,("mac w 0x%04X=0x%08X\n", offset, value)); + } + } +#endif /* RT6352 */ +#ifndef RT6352 + DBGPRINT(RT_DEBUG_WARN,("mac w 0x%04X=0x%08X\n", offset, value)); +#endif /* !RT6352 */ + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_IO_READ_BULK( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + UINT32 offset; + USHORT len; + + memcpy(&offset, &pRaCfg->status, 4); + offset = OS_NTOHL(offset); + + offset &= 0x0000FFFF; + memcpy(&len, pRaCfg->data+2, 2); + len = OS_NTOHS(len); + + if (len > 371) + { + DBGPRINT_ERR(("%s : length requested is too large, make it smaller\n", __FUNCTION__)); + pRaCfg->length = OS_HTONS(2); + pRaCfg->status = OS_HTONS(1); + + return -EFAULT; + } + + RTMP_IO_READ_BULK(pAd, pRaCfg->data, offset, (len << 2)); /* unit in four bytes*/ + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status)+(len << 2), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_BBP_READ8( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + USHORT offset; + UCHAR value; + + value = 0; + offset = OS_NTOHS(pRaCfg->status); + + ATE_BBPRead(pAd, offset, &value); + DBGPRINT(RT_DEBUG_WARN,("bbp r R%u=0x%02X\n", offset, value)); + pRaCfg->data[0] = value; + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status)+1, NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_BBP_WRITE8( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + USHORT offset; + UCHAR value; + + offset = OS_NTOHS(pRaCfg->status); + memcpy(&value, pRaCfg->data, 1); + ATE_BBPWrite(pAd, offset, value); + DBGPRINT(RT_DEBUG_WARN,("bbp w R%u=0x%02X\n", offset, value)); + + if ((offset == BBP_R1) || (offset == BBP_R3)) + { + SyncTxRxConfig(pAd, offset, value); + } + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_BBP_READ_ALL( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + USHORT bbp_reg_index; + + for (bbp_reg_index = 0; bbp_reg_index < pAd->chipCap.MaxNumOfBbpId+1; bbp_reg_index++) + { + pRaCfg->data[bbp_reg_index] = 0; + ATE_BBPRead(pAd, bbp_reg_index, &pRaCfg->data[bbp_reg_index]); + } + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status)+ pAd->chipCap.MaxNumOfBbpId+1, NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_GET_NOISE_LEVEL( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + UCHAR channel; + INT32 buffer[3][10];/* 3 : RxPath ; 10 : no. of per rssi samples */ + + channel = (OS_NTOHS(pRaCfg->status) & 0x00FF); + CalNoiseLevel(pAd, channel, buffer); + memcpy_exl(pAd, (UCHAR *)pRaCfg->data, (UCHAR *)&(buffer[0][0]), (sizeof(INT32)*3*10)); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status)+(sizeof(INT32)*3*10), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +#if defined(RT2883) || defined(RT3883) +#ifdef TXBF_SUPPORT +static INT DO_RACFG_CMD_QUERY_BF_RSP( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + USHORT value, value0, value1, value2, soundingRespSize; + int i; + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_QUERY_BF_RSP\n")); + + if ((pATEInfo->sounding == 2) && ((jiffies - pATEInfo->sounding_jiffies) < TIME_ONE_SECOND)) + { + value = OS_HTONS(1); + value0 = OS_HTONS(pATEInfo->soundingSNR[0]); + value1 = OS_HTONS(pATEInfo->soundingSNR[1]); + value2 = OS_HTONS(pATEInfo->soundingSNR[2]); + soundingRespSize = 0; /* 0=>sounding response is not returned */ + } + else + { + value = 0; + value0 = value1 = value2 = 0; + soundingRespSize = 0; + } + + /* prepare feedback */ + pRaCfg->length = OS_HTONS(4+6+2+soundingRespSize); + pRaCfg->status = OS_HTONS(0); + memcpy(pRaCfg->data, &value, 2); + memcpy(pRaCfg->data+2, &value0, 2); + memcpy(pRaCfg->data+4, &value1, 2); + memcpy(pRaCfg->data+6, &value2, 2); + value2 = OS_HTONS(soundingRespSize); + memcpy(pRaCfg->data+8, &value2, 2); + + for (i=0; isoundingResp) && idata)-10; i++) + pRaCfg->data[10+i] = pATEInfo->soundingResp[i]; + + ResponseToGUI(pRaCfg, wrq, 4+6+2+soundingRespSize, NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +#define DO_RACFG_CMD_QUERY_EBF_TAG DO_RACFG_CMD_QUERY_IBF_TAG +static INT DO_RACFG_CMD_QUERY_IBF_TAG( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + USHORT profileNum; + int byteIndex, di; + UCHAR byteVal; + BOOLEAN eProfile = OS_NTOHS(pRaCfg->command_id)==RACFG_CMD_QUERY_EBF_TAG; + + profileNum = OS_NTOHS(pRaCfg->status); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_QUERY_BF_TAG %d\n", profileNum)); + + /* Select Explicit/Implicit profile */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R179, eProfile? 0x04: 0x00); + + pRaCfg->length = OS_HTONS(2+18); + pRaCfg->status = OS_HTONS(0); + + /* Read the tagfield and write to data buffer */ + di = 0; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R181, 0x80); + + for (byteIndex=0; byteIndex<18; byteIndex++) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R180, (profileNum<<5) | byteIndex); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R182, &byteVal); + pRaCfg->data[di++] = byteVal; + } + + ResponseToGUI(pRaCfg, wrq, 2+18, NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +#define DO_RACFG_CMD_QUERY_EBF_PROFILE DO_RACFG_CMD_QUERY_IBF_PROFILE +static INT DO_RACFG_CMD_QUERY_IBF_PROFILE( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + USHORT profileNum, startCarrier; + USHORT bytesPerRow, numCarriers; + int byteIndex, carrierIndex, di; + UCHAR byteVal; + BOOLEAN eProfile = OS_NTOHS(pRaCfg->command_id)==RACFG_CMD_QUERY_EBF_PROFILE; +#ifdef LINUX + struct timeval tval1, tval2; +#endif /* LINUX */ + + profileNum = OS_NTOHS(pRaCfg->status); + memcpy(&startCarrier, pRaCfg->data, 2); + startCarrier = OS_NTOHS(startCarrier); + memcpy(&numCarriers, pRaCfg->data+2, 2); + numCarriers = OS_NTOHS(numCarriers); + + /* + Older version have no numCarriers field so length is 4. + If so, numCarriers=64. + */ + if (OS_NTOHS(pRaCfg->length)==4) + numCarriers = 64; + + if (startCarrier+numCarriers > 128) + numCarriers = 128 - startCarrier; + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_QUERY_BF_PROFILE\n")); + +#ifdef LINUX + do_gettimeofday(&tval1); +#endif /* LINUX */ + bytesPerRow = (eProfile? 18: 14); + + /* Select Explicit/Implicit profile */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R179, eProfile? 0x04: 0x00); + + pRaCfg->length = OS_HTONS(2+bytesPerRow*numCarriers); + pRaCfg->status = OS_HTONS(0); + + /* Read the data for each carrier and write to data buffer */ + di = 0; + for (carrierIndex=startCarrier; carrierIndexdata[di++] = byteVal; + } + } + +#ifdef LINUX + do_gettimeofday(&tval2); + DBGPRINT(RT_DEBUG_WARN, ("BF Read elasped = %ld usec\n", tval2.tv_usec - tval1.tv_usec)); +#endif /* LINUX */ + + ResponseToGUI(pRaCfg, wrq, 2+bytesPerRow*numCarriers, NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +#define DO_RACFG_CMD_WRITE_EBF_TAG DO_RACFG_CMD_WRITE_IBF_TAG +static INT DO_RACFG_CMD_WRITE_IBF_TAG( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + USHORT profileNum; + int byteIndex, di; + BOOLEAN eProfile = OS_NTOHS(pRaCfg->command_id)==RACFG_CMD_WRITE_EBF_TAG; + + profileNum = OS_NTOHS(pRaCfg->status); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_WRITE_EBF_TAG %d\n", profileNum)); + + /* Select Explicit/Implicit profile */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R179, eProfile? 0x04: 0x00); + + pRaCfg->length = OS_HTONS(2); + pRaCfg->status = OS_HTONS(0); + + /* Read the tagfield and write to data buffer */ + di = 0; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R181, 0x80); + + for (byteIndex=0; byteIndex<18; byteIndex++) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R180, (profileNum<<5) | byteIndex); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R182, pRaCfg->data[2+di]); + di++; + } + + ResponseToGUI(pRaCfg, wrq, 2, NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +#define DO_RACFG_CMD_WRITE_EBF_PROFILE DO_RACFG_CMD_WRITE_IBF_PROFILE +static INT DO_RACFG_CMD_WRITE_IBF_PROFILE( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + USHORT profileNum, startCarrier; + USHORT bytesPerRow, numCarriers; + int byteIndex, carrierIndex, di; + BOOLEAN eProfile = OS_NTOHS(pRaCfg->command_id)==RACFG_CMD_WRITE_EBF_PROFILE; +#ifdef LINUX + struct timeval tval1, tval2; +#endif /* LINUX */ + + bytesPerRow = (eProfile? 18: 14); + + profileNum = OS_NTOHS(pRaCfg->status); + memcpy(&startCarrier, pRaCfg->data, 2); + startCarrier = OS_NTOHS(startCarrier); + + /* Calculate number of carriers from length of data */ + numCarriers = (OS_NTOHS(pRaCfg->length)-4)/bytesPerRow; + + if (startCarrier+numCarriers > 128) + numCarriers = 128 - startCarrier; + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_WRITE_BF_PROFILE-%d %d\n", startCarrier, numCarriers)); + +#ifdef LINUX + do_gettimeofday(&tval1); +#endif /* LINUX */ + + /* Select Explicit/Implicit profile */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R179, eProfile? 0x04: 0x00); + + pRaCfg->length = OS_HTONS(2); + pRaCfg->status = OS_HTONS(0); + + /* Write the data for each carrier from data buffer */ + di = 0; + for (carrierIndex=startCarrier; carrierIndexdata[2+di]); + di++; + } + } + +#ifdef LINUX + do_gettimeofday(&tval2); + DBGPRINT(RT_DEBUG_WARN, ("BF Write elasped = %ld usec\n", tval2.tv_usec - tval1.tv_usec)); +#endif /* LINUX */ + + ResponseToGUI(pRaCfg, wrq, 2, NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CALIBRATION_CAPTURE( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + UINT32 capCtrl, macCtrl; + UINT8 r25Value, r27Value, r65Value, r66Value[3], r186Value; + UINT8 rf36Value, rf37Value; + int i, j; + SHORT txAnt, temp; + UINT8 r65Setting, r66Setting, r25Setting; + UINT16 r36r37Setting; + + UINT16 papdIQ[3] = {0,0,0}; + BOOLEAN usePapd = FALSE; +#ifdef LINUX + struct timeval tval0, tval1, tval2; +#endif /* LINUX */ + + /* Get Parameters */ + txAnt = OS_NTOHS(pRaCfg->status); + memcpy(&temp, &(pRaCfg->data[0]), 2); + r65Setting = OS_NTOHS(temp); + memcpy(&temp, &(pRaCfg->data[2]), 2); + r66Setting = OS_NTOHS(temp); + memcpy(&temp, &(pRaCfg->data[4]), 2); + r36r37Setting = OS_NTOHS(temp); + memcpy(&temp, &(pRaCfg->data[6]), 2); + r25Setting = OS_NTOHS(temp); + + /* + For backwards compatibility txAnt: + 0, 1, 2 = only enable Ant0/1/2 + -1 = if no papd parameters then don't use papd. + Otherwise read papd parameters + */ + if (txAnt==0 || txAnt==1 || txAnt==2) + { + papdIQ[txAnt] = 0x7F00; + usePapd = TRUE; + } + else if (OS_NTOHS(pRaCfg->length)>10) + { + /* papdIQ[3] containing I/Q values for PAPD table */ + memcpy(&temp, &(pRaCfg->data[8]), 2); + papdIQ[0] = OS_NTOHS(temp); + memcpy(&temp, &(pRaCfg->data[10]), 2); + papdIQ[1] = OS_NTOHS(temp); + memcpy(&temp, &(pRaCfg->data[12]), 2); + papdIQ[2] = OS_NTOHS(temp); + usePapd = TRUE; + } + + /* Read CAP CTRL, MAC CTRL and RF R25 */ + RTMP_IO_READ32(pAd, PBF_CAP_CTRL, &capCtrl); + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &macCtrl); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R25, &r25Value); + + /* Disable MAC Rx */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x00); + /* -> disable all Tx/Rx Queue */ + RTMP_IO_WRITE32(pAd, PBF_CFG, 0x00000000); + + /* Overwrite PAPD table and enable PAPD */ + if (usePapd) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R186, &r186Value); + + for (i=0; i<3; i++) + { + for (j=0; j<32; j++) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, (i<<6) | (j<<1)); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, (papdIQ[i]>>8) & 0xFF); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, (i<<6) | (j<<1) | 1); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, papdIQ[i] & 0xFF); + } + } + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x80); + } + + /* -> capture mode */ + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x00004E80); + + /* Enable Capture and RX */ + capCtrl &= ~0x80000000; /* set bit[31]=0 */ + capCtrl &= ~(0x1FFF0000); /* CaptureModeOffset = 0 */ + + /* Enable Capture and RX */ + RTMP_IO_WRITE32(pAd, PBF_CAP_CTRL, capCtrl | 0x40000000); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x08); + +#ifdef LINUX + do_gettimeofday(&tval0); +#endif /* LINUX */ + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R250, &r65Value); /* gaa */ + + /* Set BBP R65 - LNA */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R65, &r65Value); + if (r65Setting != 0xFF) + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R65, r65Setting); + + /* Set BBP R66 - VGA */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R27, &r27Value); + for (i=0; i<3; i++) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, (r27Value & ~0x60) | (i<<5)); + ATE_RF_IO_READ8_BY_REG_ID(pAd, BBP_R66, &r66Value[i]); + if (r66Setting != 0) + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, r66Setting); + } + + /* Enable RF Loopback */ + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R36, &rf36Value); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R36, rf36Value | (r36r37Setting & 0xFF)); + ATE_RF_IO_READ8_BY_REG_ID(pAd, RF_R37, &rf37Value); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R37, rf37Value | (r36r37Setting >> 8)); + + /* Start capture before RF loopback */ + RTMP_IO_WRITE32(pAd, PBF_CAP_CTRL, capCtrl | 0x20000000); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R25, r25Value | r25Setting); + +#ifdef LINUX + do_gettimeofday(&tval2); +#endif /* LINUX */ + + /* Wait for capture buffer to fill */ + i = 0; + do + { + RTMPusecDelay(75); + RTMP_IO_READ32(pAd, PBF_CAP_CTRL, &capCtrl); + } while ((capCtrl & 0x40000000)!=0 && ++i<12); + + /* Stop RX */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x00); + + /* Restore BBP R65, R66, R27, R186 and RF_R36/37 */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R65, r65Value); + + for (i=0; i<3; i++) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, (r27Value & ~0x60) | (i<<5)); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, r66Value[i]); + } + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, r27Value); + + if (usePapd) + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, r186Value); + + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R36, rf36Value); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, RF_R37, rf37Value); + +#ifdef LINUX + do_gettimeofday(&tval1); + DBGPRINT(RT_DEBUG_WARN, ("Cal Cap c=%x, t1=%ld t2=%ld\n", capCtrl, + tval1.tv_usec - tval0.tv_usec, tval2.tv_usec - tval0.tv_usec)); +#endif /* LINUX */ + + ResponseToGUI(pRaCfg, wrq, 2, NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} +#endif /* TXBF_SUPPORT */ +#endif /* defined(RT2883) || defined(RT3883) */ + + +static INT DO_RACFG_CMD_GET_COUNTER( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + memcpy_exl(pAd, &pRaCfg->data[0], (UCHAR *)&pATEInfo->U2M, 4); + memcpy_exl(pAd, &pRaCfg->data[4], (UCHAR *)&pATEInfo->OtherData, 4); + memcpy_exl(pAd, &pRaCfg->data[8], (UCHAR *)&pATEInfo->Beacon, 4); + memcpy_exl(pAd, &pRaCfg->data[12], (UCHAR *)&pATEInfo->OtherCount, 4); + memcpy_exl(pAd, &pRaCfg->data[16], (UCHAR *)&pATEInfo->TxAc0, 4); + memcpy_exl(pAd, &pRaCfg->data[20], (UCHAR *)&pATEInfo->TxAc1, 4); + memcpy_exl(pAd, &pRaCfg->data[24], (UCHAR *)&pATEInfo->TxAc2, 4); + memcpy_exl(pAd, &pRaCfg->data[28], (UCHAR *)&pATEInfo->TxAc3, 4); + memcpy_exl(pAd, &pRaCfg->data[32], (UCHAR *)&pATEInfo->TxHCCA, 4); + memcpy_exl(pAd, &pRaCfg->data[36], (UCHAR *)&pATEInfo->TxMgmt, 4); + memcpy_exl(pAd, &pRaCfg->data[40], (UCHAR *)&pATEInfo->RSSI0, 4); + memcpy_exl(pAd, &pRaCfg->data[44], (UCHAR *)&pATEInfo->RSSI1, 4); + memcpy_exl(pAd, &pRaCfg->data[48], (UCHAR *)&pATEInfo->RSSI2, 4); + memcpy_exl(pAd, &pRaCfg->data[52], (UCHAR *)&pATEInfo->SNR0, 4); + memcpy_exl(pAd, &pRaCfg->data[56], (UCHAR *)&pATEInfo->SNR1, 4); + +#if defined(RT2883) || defined(RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + { +#ifdef DOT11N_SS3_SUPPORT + memcpy_exl(pAd, &pRaCfg->data[60], (UCHAR *)&pATEInfo->SNR2, 4); +#endif /* DOT11N_SS3_SUPPORT */ +#ifdef TXBF_SUPPORT + memcpy_exl(pAd, &pRaCfg->data[64], (UCHAR *)&pATEInfo->LastRxRate, 4); +#endif /* TXBF_SUPPORT */ + memcpy_exl(pAd, &pRaCfg->data[68], (UCHAR *)&pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word, 4); + memcpy_exl(pAd, &pRaCfg->data[72], (UCHAR *)&pATEInfo->BF_SNR[0], 4); + memcpy_exl(pAd, &pRaCfg->data[76], (UCHAR *)&pATEInfo->BF_SNR[1], 4); + memcpy_exl(pAd, &pRaCfg->data[80], (UCHAR *)&pATEInfo->BF_SNR[2], 4); + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status)+84, NDIS_STATUS_SUCCESS); + } + else + { + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status)+60, NDIS_STATUS_SUCCESS); + } +#else + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status)+60, NDIS_STATUS_SUCCESS); +#endif /* defined(RT2883) || defined(RT3883) */ + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_CLEAR_COUNTER( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + pATEInfo->U2M = 0; + pATEInfo->OtherData = 0; + pATEInfo->Beacon = 0; + pATEInfo->OtherCount = 0; + pATEInfo->TxAc0 = 0; + pATEInfo->TxAc1 = 0; + pATEInfo->TxAc2 = 0; + pATEInfo->TxAc3 = 0; + pATEInfo->TxHCCA = 0; + pATEInfo->TxMgmt = 0; + pATEInfo->TxDoneCount = 0; + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_TX_START( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + USHORT *p; + USHORT err = 1; +#if defined(RT2883) || defined(RT3883) + HEADER_802_11 *pHeader_802_11 = NULL; + PHT_CONTROL pHTC; +#endif /* defined(RT2883) || defined(RT3883) */ + UINT8 TXWISize = pAd->chipCap.TXWISize; + UINT8 TxInfoSize = 4; + + if ((pATEInfo->TxStatus != 0) && (pATEInfo->Mode & ATE_TXFRAME)) + { + DBGPRINT_ERR(("%s : Ate Tx is already running," + "to run next Tx, you must stop it first\n", __FUNCTION__)); + err = 2; + goto tx_start_error; + } + else if ((pATEInfo->TxStatus != 0) && !(pATEInfo->Mode & ATE_TXFRAME)) + { + int slot = 0; + + while ((slot++ < 10) && (pATEInfo->TxStatus != 0)) + { + RtmpOsMsDelay(5); + } + + /* force it to stop */ + pATEInfo->TxStatus = 0; + pATEInfo->TxDoneCount = 0; + pATEInfo->bQATxStart = FALSE; + } + + /* + Reset ATE mode and set Tx/Rx idle + for new proposed TXCONT/TXCARR/TXCARRSUPP solution. + */ + if ((pATEInfo->Mode & ATE_TXFRAME) && (pATEInfo->TxMethod == TX_METHOD_1)) + { + TXSTOP(pAd); + } + + /* + If pRaCfg->length == 0, this "RACFG_CMD_TX_START" + is for Carrier test or Carrier Suppression test. + */ + if (OS_NTOHS(pRaCfg->length) != 0) + { + /* get frame info */ + + NdisMoveMemory(&pATEInfo->TxWI, pRaCfg->data + 2, TXWISize); +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, (PUCHAR)&pATEInfo->TxWI, TYPE_TXWI); +#endif /* RT_BIG_ENDIAN */ + + NdisMoveMemory(&pATEInfo->TxCount, pRaCfg->data + TXWISize + 2, 4); + pATEInfo->TxCount = OS_NTOHL(pATEInfo->TxCount); + +/* p = (USHORT *)(&pRaCfg->data[TXWISize + TxInfoSize + 2]); */ + + /* always use QID_AC_BE */ + pATEInfo->QID = 0; + + p = (USHORT *)(&pRaCfg->data[TXWISize + TxInfoSize + 2*2]); + pATEInfo->HLen = OS_NTOHS(*p); + + if (pATEInfo->HLen > 32) + { + DBGPRINT_ERR(("%s : pATEInfo->HLen > 32\n", __FUNCTION__)); + DBGPRINT_ERR(("pATEInfo->HLen = %d\n", pATEInfo->HLen)); + err = 3; + goto tx_start_error; + } + + NdisMoveMemory(&pATEInfo->Header, pRaCfg->data + (TXWISize + TxInfoSize + 2*3), pATEInfo->HLen); +#if defined(RT2883) || defined(RT3883) +#ifdef TXBF_SUPPORT + if (IS_RT2883(pAd) || IS_RT3883(pAd) ) + { + /* check Sounding frame */ + pATEInfo->sounding = 0; + pHeader_802_11 = (HEADER_802_11 *) pATEInfo->Header; + pHTC = (PHT_CONTROL) &pHeader_802_11->Octet[2]; + if ((pATEInfo->TxWI.Sounding== 1) + || ((pHeader_802_11->FC.SubType & 0x08) + && (pHeader_802_11->FC.Order == 1) && (pHTC->NDPAnnounce)) ) + { + DBGPRINT(RT_DEBUG_TRACE, ("Sending sounding frame\n")); + pATEInfo->sounding = 1; + pATEInfo->sounding_jiffies = jiffies; /* TIME_ONE_SECOND timeout */ + } + } +#endif /* TXBF_SUPPORT */ +#endif /* defined(RT2883) || defined(RT3883) */ + + pATEInfo->PLen = OS_NTOHS(pRaCfg->length) - (pATEInfo->HLen + (TXWISize + TxInfoSize + 2*4)); + + if (pATEInfo->PLen > 32) + { + DBGPRINT_ERR(("%s : pATEInfo->PLen > 32\n", __FUNCTION__)); + err = 4; + goto tx_start_error; + } + + NdisMoveMemory(&pATEInfo->Pattern, pRaCfg->data + (TXWISize + TxInfoSize + 2*3) + pATEInfo->HLen, pATEInfo->PLen); + pATEInfo->DLen = pATEInfo->TxWI.MPDUtotalByteCount - pATEInfo->HLen; + +#if defined(RT2883) || defined(RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd) ) + { + if ((pHeader_802_11->FC.SubType & 0x08) && (pHeader_802_11->FC.Order == 1)) + pATEInfo->DLen += 2; /* compensation for header padding */ + } +#endif /* defined(RT2883) || defined(RT3883) */ + + } + + ReadQATxTypeFromBBP(pAd); + + if (pATEInfo->bQATxStart == TRUE) + { + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + return NDIS_STATUS_SUCCESS; + } + +tx_start_error: + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), err); + + return err; +} + + +static INT DO_RACFG_CMD_GET_TX_STATUS( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + UINT32 count=0; + + count = OS_HTONL(pATEInfo->TxDoneCount); + NdisMoveMemory(pRaCfg->data, &count, 4); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status)+4, NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_TX_STOP( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_TX_STOP\n")); + + Set_ATE_Proc(pAd, "TXSTOP"); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_RX_START( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_RX_START\n")); + + pATEInfo->bQARxStart = TRUE; + Set_ATE_Proc(pAd, "RXFRAME"); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_RX_STOP( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_RX_STOP\n")); + + Set_ATE_Proc(pAd, "RXSTOP"); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_START_TX_CARRIER( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START_TX_CARRIER\n")); + + Set_ATE_Proc(pAd, "TXCARR"); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_START_TX_CONT( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START_TX_CONT\n")); + + Set_ATE_Proc(pAd, "TXCONT"); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_START_TX_FRAME( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START_TX_FRAME\n")); + + Set_ATE_Proc(pAd, "TXFRAME"); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_SET_BW( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + SHORT value = 0; + STRING str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_BW\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = OS_NTOHS(value); + snprintf((char *)str, sizeof(str), "%d", value); + + Set_ATE_TX_BW_Proc(pAd, str); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_SET_TX_POWER0( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + SHORT value = 0; + STRING str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_POWER0\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = OS_NTOHS(value); + snprintf((char *)str, sizeof(str), "%d", value); + Set_ATE_TX_POWER0_Proc(pAd, str); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_SET_TX_POWER1( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + SHORT value = 0; + STRING str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_POWER1\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = OS_NTOHS(value); + snprintf((char *)str, sizeof(str), "%d", value); + Set_ATE_TX_POWER1_Proc(pAd, str); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +#ifdef DOT11N_SS3_SUPPORT +static INT DO_RACFG_CMD_ATE_SET_TX_POWER2( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + SHORT value = 0; + STRING str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_POWER2\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = OS_NTOHS(value); + snprintf((char *)str, sizeof(str), "%d", value); + Set_ATE_TX_POWER2_Proc(pAd, str); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} +#endif /* DOT11N_SS3_SUPPORT */ + + +static INT DO_RACFG_CMD_ATE_SET_FREQ_OFFSET( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + SHORT value = 0; + STRING str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_FREQ_OFFSET\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = OS_NTOHS(value); + snprintf((char *)str, sizeof(str), "%d", value); + Set_ATE_TX_FREQ_OFFSET_Proc(pAd, str); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_GET_STATISTICS( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_GET_STATISTICS\n")); + + memcpy_exl(pAd, &pRaCfg->data[0], (UCHAR *)&pATEInfo->TxDoneCount, 4); + memcpy_exl(pAd, &pRaCfg->data[4], (UCHAR *)&pAd->WlanCounters.RetryCount.u.LowPart, 4); + memcpy_exl(pAd, &pRaCfg->data[8], (UCHAR *)&pAd->WlanCounters.FailedCount.u.LowPart, 4); + memcpy_exl(pAd, &pRaCfg->data[12], (UCHAR *)&pAd->WlanCounters.RTSSuccessCount.u.LowPart, 4); + memcpy_exl(pAd, &pRaCfg->data[16], (UCHAR *)&pAd->WlanCounters.RTSFailureCount.u.LowPart, 4); + memcpy_exl(pAd, &pRaCfg->data[20], (UCHAR *)&pAd->WlanCounters.ReceivedFragmentCount.QuadPart, 4); + memcpy_exl(pAd, &pRaCfg->data[24], (UCHAR *)&pAd->WlanCounters.FCSErrorCount.u.LowPart, 4); + memcpy_exl(pAd, &pRaCfg->data[28], (UCHAR *)&pAd->Counters8023.RxNoBuffer, 4); + memcpy_exl(pAd, &pRaCfg->data[32], (UCHAR *)&pAd->WlanCounters.FrameDuplicateCount.u.LowPart, 4); + memcpy_exl(pAd, &pRaCfg->data[36], (UCHAR *)&pAd->RalinkCounters.OneSecFalseCCACnt, 4); + + if (pATEInfo->RxAntennaSel == 0) + { + INT32 RSSI0 = 0; + INT32 RSSI1 = 0; + INT32 RSSI2 = 0; + + RSSI0 = (INT32)(pATEInfo->LastRssi0 - pAd->BbpRssiToDbmDelta); + RSSI1 = (INT32)(pATEInfo->LastRssi1 - pAd->BbpRssiToDbmDelta); + RSSI2 = (INT32)(pATEInfo->LastRssi2 - pAd->BbpRssiToDbmDelta); + memcpy_exl(pAd, &pRaCfg->data[40], (UCHAR *)&RSSI0, 4); + memcpy_exl(pAd, &pRaCfg->data[44], (UCHAR *)&RSSI1, 4); + memcpy_exl(pAd, &pRaCfg->data[48], (UCHAR *)&RSSI2, 4); + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status)+52, NDIS_STATUS_SUCCESS); + } + else + { + INT32 RSSI0 = 0; + + RSSI0 = (INT32)(pATEInfo->LastRssi0 - pAd->BbpRssiToDbmDelta); + memcpy_exl(pAd, &pRaCfg->data[40], (UCHAR *)&RSSI0, 4); + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status)+44, NDIS_STATUS_SUCCESS); + } + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_RESET_COUNTER( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + SHORT value = 1; + STRING str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_RESET_COUNTER\n")); + + snprintf((char *)str, sizeof(str), "%d", value); + Set_ResetStatCounter_Proc(pAd, str); + + pATEInfo->TxDoneCount = 0; + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_SEL_TX_ANTENNA( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + SHORT value = 0; + STRING str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SEL_TX_ANTENNA\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = OS_NTOHS(value); + snprintf((char *)str, sizeof(str), "%d", value); + Set_ATE_TX_Antenna_Proc(pAd, str); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_SEL_RX_ANTENNA( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + SHORT value = 0; + STRING str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SEL_RX_ANTENNA\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = OS_NTOHS(value); + snprintf((char *)str, sizeof(str), "%d", value); + Set_ATE_RX_Antenna_Proc(pAd, str); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_SET_PREAMBLE( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + SHORT value = 0; + STRING str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_PREAMBLE\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = OS_NTOHS(value); + snprintf((char *)str, sizeof(str), "%d", value); + Set_ATE_TX_MODE_Proc(pAd, str); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_SET_CHANNEL( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + SHORT value = 0; + STRING str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_CHANNEL\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = OS_NTOHS(value); + snprintf((char *)str, sizeof(str), "%d", value); + Set_ATE_CHANNEL_Proc(pAd, str); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_SET_ADDR1( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_ADDR1\n")); + memcpy(pATEInfo->Addr1, (PUCHAR)(pRaCfg->data - 2), MAC_ADDR_LEN); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_SET_ADDR2( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_ADDR2\n")); + memcpy(pATEInfo->Addr2, (PUCHAR)(pRaCfg->data - 2), MAC_ADDR_LEN); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_SET_ADDR3( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_ADDR3\n")); + memcpy(pATEInfo->Addr3, (PUCHAR)(pRaCfg->data - 2), MAC_ADDR_LEN); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_SET_RATE( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + SHORT value = 0; + STRING str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_RATE\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = OS_NTOHS(value); + snprintf((char *)str, sizeof(str), "%d", value); + Set_ATE_TX_MCS_Proc(pAd, str); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_SET_TX_FRAME_LEN( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + SHORT value = 0; + STRING str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_FRAME_LEN\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = OS_NTOHS(value); + snprintf((char *)str, sizeof(str), "%d", value); + Set_ATE_TX_LENGTH_Proc(pAd, str); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_SET_TX_FRAME_COUNT( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ +#ifdef RTMP_MAC_PCI + PATE_INFO pATEInfo = &(pAd->ate); +#endif /* RTMP_MAC_PCI */ + USHORT value = 0; + STRING str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_FRAME_COUNT\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = OS_NTOHS(value); + +#ifdef RTMP_MAC_PCI + /* TX_FRAME_COUNT == 0 means tx infinitely */ + if (value == 0) + { + /* Use TxCount = 0xFFFFFFFF to approximate the infinity. */ + pATEInfo->TxCount = 0xFFFFFFFF; + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_COUNT_Proc (TxCount = %d)\n", pATEInfo->TxCount)); + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#endif /* CONFIG_AP_SUPPORT */ + } + else +#endif /* RTMP_MAC_PCI */ + { + snprintf((char *)str, sizeof(str), "%d", value); + Set_ATE_TX_COUNT_Proc(pAd, str); + } + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_START_RX_FRAME( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_RX_START\n")); + + Set_ATE_Proc(pAd, "RXFRAME"); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_E2PROM_READ_BULK( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + USHORT offset; + USHORT len; + USHORT buffer[EEPROM_SIZE >> 1]; + + offset = OS_NTOHS(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = OS_NTOHS(len); + + rt_ee_read_all(pAd, (USHORT *)buffer); + + if (offset + len <= EEPROM_SIZE) + memcpy_exs(pAd, pRaCfg->data, (UCHAR *)buffer+offset, len); + else + DBGPRINT_ERR(("%s : exceed EEPROM size\n", __FUNCTION__)); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status)+len, NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_E2PROM_WRITE_BULK( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + USHORT offset; + USHORT len; + USHORT buffer[EEPROM_SIZE >> 1]; + + offset = OS_NTOHS(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = OS_NTOHS(len); + + memcpy_exs(pAd, (UCHAR *)buffer + offset, (UCHAR *)pRaCfg->data + 2, len); + + if ((offset + len) <= EEPROM_SIZE) + { + rt_ee_write_bulk(pAd,(USHORT *)(((UCHAR *)buffer) + offset), offset, len); + } + else + { + DBGPRINT_ERR(("%s : exceed EEPROM size(%d)\n", __FUNCTION__, EEPROM_SIZE)); + DBGPRINT(RT_DEBUG_ERROR,("offset=%u\n", offset)); + DBGPRINT(RT_DEBUG_ERROR,("length=%u\n", len)); + DBGPRINT(RT_DEBUG_ERROR,("offset+length=%u\n", (offset+len))); + } + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_IO_WRITE_BULK( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + UINT32 offset, pos, value; + USHORT len; + + memcpy(&offset, &pRaCfg->status, 4); + offset = OS_NTOHL(offset); + memcpy(&len, pRaCfg->data+2, 2); + len = OS_NTOHS(len); + + DBGPRINT(RT_DEBUG_WARN,("\n\n")); + for (pos = 0; pos < len; pos += 4) + { + memcpy_exl(pAd, (UCHAR *)&value, pRaCfg->data+4+pos, 4); + RTMP_IO_WRITE32(pAd, ((offset+pos) & (0xffff)), value); + DBGPRINT(RT_DEBUG_WARN,("mac w 0x%04X=0x%08X\n", offset + pos, value)); + } + DBGPRINT(RT_DEBUG_WARN,("\n\n")); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_BBP_READ_BULK( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + USHORT offset; + USHORT len; + USHORT pos; + + offset = OS_NTOHS(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = OS_NTOHS(len); + + DBGPRINT(RT_DEBUG_WARN,("\n\n")); + for (pos = offset; pos < (offset+len); pos++) + { + pRaCfg->data[pos - offset] = 0; + + ATE_BBPRead(pAd, pos, &pRaCfg->data[pos - offset]); + DBGPRINT(RT_DEBUG_WARN,("bbp r R%u=0x%02X\n" + , pos, pRaCfg->data[pos - offset])); + } + DBGPRINT(RT_DEBUG_WARN,("\n\n")); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status)+len, NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_BBP_WRITE_BULK( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + USHORT offset; + USHORT len; + USHORT pos; + UCHAR *value; + + offset = OS_NTOHS(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = OS_NTOHS(len); + + DBGPRINT(RT_DEBUG_WARN,("\n\n")); + for (pos = offset; pos < (offset+len); pos++) + { + value = pRaCfg->data + 2 + (pos - offset); + ATE_BBPWrite(pAd, pos, *value); + DBGPRINT(RT_DEBUG_WARN,("bbp w R%u=0x%02X\n", pos, *value)); + } + DBGPRINT(RT_DEBUG_WARN,("\n\n")); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +#ifdef RT3883 +static INT DO_RACFG_CMD_ATE_ETH_EXT_SETTING( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + UINT32 value = 0; + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_ETH_EXT_SETTING\n")); + memcpy((PUCHAR)&value, pRaCfg->data-2, 4); + value = OS_NTOHL(value); + + if (value == 0) + { + /* GPIO pull low */ + RTMPRT3883ABandSel(36); + } + else + { + /* GPIO pull high */ + RTMPRT3883ABandSel(1); + } + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} +#endif /* RT3883 */ + + +#if defined (RT3883) || defined (RT3352) || defined (RT5350) +/* busy mode - make CPU in ATE mode as busy as in normal driver */ +static INT DO_RACFG_CMD_ATE_RUN_CPUBUSY( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ +#ifdef LINUX + UINT32 mode = 0; + char *argv_busy[] = {"/sbin/cpubusy.sh", "2", NULL }; + char *argv_idle[] = {"/usr/bin/killall", "cpubusy.sh", "3", NULL }; + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_RUN_CPUBUSY\n")); + memcpy((PUCHAR)&mode, pRaCfg->data-2, 4); + mode = OS_NTOHL(mode); + + if (mode == 0) + { + /* idle mode */ + call_usermodehelper(argv_idle[0], argv_idle, NULL, 0); + } + else + { + /* busy mode */ + call_usermodehelper(argv_busy[0], argv_busy, NULL, 0); + } + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); +#endif /* LINUX */ + return NDIS_STATUS_SUCCESS; +} +#endif /* defined (RT3883) || defined (RT3352) || defined (RT5350) */ + + +#ifdef RT6352 +static INT DO_RACFG_CMD_ATE_CALIBRATION( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + UINT32 cal_id = 0; + UINT32 value = 0; + STRING str[LEN_OF_ARG]; + UCHAR RFValue; + + NdisZeroMemory(str, LEN_OF_ARG); + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_CALIBRATION\n")); + + memcpy((PUCHAR)&cal_id, pRaCfg->data-2, 4); + cal_id = OS_NTOHL(cal_id); + memcpy((PUCHAR)&value, pRaCfg->data+2, 4); + value = OS_NTOHL(value); +/* snprintf((char *)str, sizeof(str), "%d", value); */ + + switch (cal_id) + { + case 5: /* QA BW filter compensation */ + if (value == 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 if (value == BW_40) + { + 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); + } + else + { + DBGPRINT_ERR(("%s: Unknown bandwidth = %u\n", __FUNCTION__, value)); + } + break; + case 7: /* QA TX LOFT and IQ calibration */ + LOFT_IQ_Calibration(pAd); + break; + case 8: /* QA RF SELF TX DC calibration */ + RF_SELF_TXDC_CAL(pAd); + break; + case 9: /* QA DPD calibration */ + if (value == ANT_ALL) + { + Set_TestDPDCalibration_Proc(pAd, "1"); + } + else if (value == ANT_0) + { + Set_TestDPDCalibrationTX0_Proc(pAd, "1"); + } + else if (value == ANT_1) + { + Set_TestDPDCalibrationTX1_Proc(pAd, "1"); + } + else if (value == 0x80000000) + { + /* disable DPD calibration */ + Set_TestDPDCalibration_Proc(pAd, "0"); + } + else + { + DBGPRINT_ERR(("%s: Unknown Tx path of DPD = %u\n", __FUNCTION__, value)); + } + break; + default: + DBGPRINT_ERR(("%s: Unknown calibration ID = %u\n", __FUNCTION__, cal_id)); + break; + } + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_TSSI_COMPENSATION( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + UINT32 value = 0; + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_TSSI_COMPENSATION\n")); + memcpy((PUCHAR)&value, pRaCfg->data-2, 4); + value = OS_NTOHL(value); + + switch (value) + { + case 0: + /* disable TSSI compensation */ + Set_ATE_AUTO_ALC_Proc(pAd, "0"); + DBGPRINT(RT_DEBUG_TRACE, ("%s: disable TSSI compensation.\n", __FUNCTION__)); + break; + case 1: +#ifdef RTMP_INTERNAL_TX_ALC + /* enable TSSI compensation */ + Set_ATE_AUTO_ALC_Proc(pAd, "1"); + DBGPRINT(RT_DEBUG_TRACE,("%s: enable TSSI compensation.\n", __FUNCTION__)); +#else + DBGPRINT_ERR(("%s: not support TSSI compensation.\n", __FUNCTION__)); +#endif /* RTMP_INTERNAL_TX_ALC */ + break; + default: + DBGPRINT_ERR(("%s: Unknown payload from QA = %u\n", __FUNCTION__, value)); + break; + } + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_TEMP_COMPENSATION( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + UINT32 value = 0; + + DBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_TEMP_COMPENSATION\n")); + memcpy((PUCHAR)&value, pRaCfg->data-2, 4); + value = OS_NTOHL(value); + + switch (value) + { + case 0: + /* disable temperature compensation */ + Set_ATE_AUTO_ALC_Proc(pAd, "0"); + DBGPRINT(RT_DEBUG_TRACE, ("%s: disable temperature compensation.\n", __FUNCTION__)); + break; + case 1: +#ifdef RTMP_TEMPERATURE_COMPENSATION + /* enable temperature compensation */ + Set_ATE_AUTO_ALC_Proc(pAd, "1"); + DBGPRINT(RT_DEBUG_TRACE,("%s: enable temperature compensation.\n", __FUNCTION__)); +#else + DBGPRINT_ERR(("%s: not support temperature compensation.\n", __FUNCTION__)); +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + break; + default: + DBGPRINT_ERR(("%s: Unknown payload from QA = %u\n", __FUNCTION__, value)); + break; + } + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + +#endif /* RT6352 */ + + +#ifdef RTMP_RF_RW_SUPPORT +#ifndef RF_BANK +static INT DO_RACFG_CMD_ATE_RF_READ_BULK( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + USHORT offset; + USHORT len; + USHORT pos; + + offset = OS_NTOHS(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = OS_NTOHS(len); + + DBGPRINT(RT_DEBUG_WARN,("\n\n")); + for (pos = offset; pos < (offset+len); pos++) + { + pRaCfg->data[pos - offset] = 0; + ATE_RF_IO_READ8_BY_REG_ID(pAd, pos, &pRaCfg->data[pos - offset]); + DBGPRINT(RT_DEBUG_WARN,("rf r R%u=0x%02X\n" + , pos, pRaCfg->data[pos - offset])); + } + DBGPRINT(RT_DEBUG_WARN,("\n\n")); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status)+len, NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_RF_WRITE_BULK( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + USHORT offset; + USHORT len; + USHORT pos; + UCHAR *value; + + offset = OS_NTOHS(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = OS_NTOHS(len); + + DBGPRINT(RT_DEBUG_WARN,("\n\n")); + for (pos = offset; pos < (offset+len); pos++) + { + value = pRaCfg->data + 2 + (pos - offset); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, pos, *value); + DBGPRINT(RT_DEBUG_WARN,("rf w R%u=0x%02X\n", pos, *value)); + } + DBGPRINT(RT_DEBUG_WARN,("\n\n")); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} +#endif /* !RF_BANK */ + + +#ifdef RF_BANK +static INT DO_RACFG_CMD_ATE_RF_READ_BULK_BANK( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + USHORT offset; + USHORT bank; + USHORT len; + USHORT pos; + + bank = OS_NTOHS(pRaCfg->status); + memcpy(&offset, pRaCfg->data, 2 /* sizeof(offset) */); + offset = OS_NTOHS(offset); + memcpy(&len, pRaCfg->data + 2 /* sizeof(offset) */, 2 /* sizeof(len) */); + len = OS_NTOHS(len); + + DBGPRINT(RT_DEBUG_WARN,("\n\n")); + for (pos = offset; pos < (offset+len); pos++) + { + pRaCfg->data[pos - offset] = 0; + ATE_RF_IO_READ8_BY_REG_ID(pAd, bank, pos, &pRaCfg->data[pos - offset]); + DBGPRINT(RT_DEBUG_WARN,("rf bank%u r R%u=0x%02X\n" + , bank, pos, pRaCfg->data[pos - offset])); + } + DBGPRINT(RT_DEBUG_WARN,("\n\n")); + + ResponseToGUI(pRaCfg, wrq, 2/* sizeof(pRaCfg->status) */+len, NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_RF_WRITE_BULK_BANK( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + USHORT offset; + USHORT bank; + USHORT len; + USHORT pos; + UCHAR *value; + + bank = OS_NTOHS(pRaCfg->status); + memcpy(&offset, pRaCfg->data, 2 /* sizeof(offset) */); + offset = OS_NTOHS(offset); + memcpy(&len, pRaCfg->data + 2 /* sizeof(offset) */, 2 /* sizeof(len) */); + len = OS_NTOHS(len); + + DBGPRINT(RT_DEBUG_WARN,("\n\n")); + for (pos = offset; pos < (offset+len); pos++) + { + value = pRaCfg->data + sizeof(offset) + sizeof(len) + (pos - offset); + ATE_RF_IO_WRITE8_BY_REG_ID(pAd, bank, pos, *value); + DBGPRINT(RT_DEBUG_WARN,("rf bank%u w R%u=0x%02X\n", bank, pos, *value)); + } + DBGPRINT(RT_DEBUG_WARN,("\n\n")); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} +#endif /* RF_BANK */ +#endif /* RTMP_RF_RW_SUPPORT */ + + +#ifdef TXBF_SUPPORT +static INT DO_RACFG_CMD_ATE_TXBF_DUT_INIT( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + DBGPRINT(RT_DEBUG_TRACE,("DO_RACFG_CMD_ATE_TXBF_DUT_INIT\n")); + + Set_ATE_TXBF_INIT_Proc(pAd, "1"); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_TXBF_LNA_CAL( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + USHORT band; + CHAR bandStr[32] = {0}; + + DBGPRINT(RT_DEBUG_TRACE,("DO_RACFG_CMD_ATE_TXBF_LNA_CAL\n")); + + band = OS_NTOHS(pRaCfg->status); + DBGPRINT(RT_DEBUG_TRACE, ("%s : band=0x%x(0x%x)\n", + __FUNCTION__, band, pRaCfg->status)); + snprintf(bandStr, sizeof(bandStr), "%d\n", band); + Set_ATE_TXBF_LNACAL_Proc(pAd, &bandStr[0]); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_TXBF_DIV_CAL( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + USHORT band; + CHAR bandStr[32] = {0}; + + DBGPRINT(RT_DEBUG_TRACE,("DO_RACFG_CMD_ATE_TXBF_DIV_CAL\n")); + + band = OS_NTOHS(pRaCfg->status); + DBGPRINT(RT_DEBUG_TRACE, ("%s : band=0x%x(0x%x)\n", + __FUNCTION__, band, pRaCfg->status)); + snprintf(bandStr, sizeof(bandStr), "%d\n", band); + Set_ATE_TXBF_DIVCAL_Proc(pAd, &bandStr[0]); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_TXBF_PHASE_CAL( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + SHORT value = 0; + STRING str[LEN_OF_ARG]; + BOOLEAN result = FALSE; + + NdisZeroMemory(str, LEN_OF_ARG); + + DBGPRINT(RT_DEBUG_TRACE,("DO_RACFG_CMD_ATE_TXBF_PHASE_CAL\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = OS_NTOHS(value); + snprintf((char *)str, sizeof(str), "%d", value); + + result = (BOOLEAN)Set_ATE_TXBF_CAL_Proc(pAd, str); + pRaCfg->data[0] = result; + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status) + 1, NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_TXBF_GOLDEN_INIT( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + SHORT value = 0; + STRING str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + DBGPRINT(RT_DEBUG_TRACE,("DO_RACFG_CMD_ATE_TXBF_GOLDEN_INIT\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = OS_NTOHS(value); + snprintf((char *)str, sizeof(str), "%d", value); + + Set_ATE_TXBF_GOLDEN_Proc(pAd, str); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_TXBF_VERIFY( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + SHORT value = 0; + STRING str[LEN_OF_ARG]; + BOOLEAN result; + + DBGPRINT(RT_DEBUG_TRACE,("DO_RACFG_CMD_ATE_TXBF_VERIFY\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = OS_NTOHS(value); + snprintf((char *)str, sizeof(str), "%d", value); + + result = (BOOLEAN)Set_ATE_TXBF_VERIFY_Proc(pAd, str); + + pRaCfg->data[0] = result; + pRaCfg->data[1] = pATEInfo->calParams[0]; + pRaCfg->data[2] = pATEInfo->calParams[1]; + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status) + 3, NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} + + +static INT DO_RACFG_CMD_ATE_TXBF_VERIFY_NOCOMP( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + SHORT value = 0; + STRING str[LEN_OF_ARG]; + BOOLEAN result; + + DBGPRINT(RT_DEBUG_TRACE,("DO_RACFG_CMD_ATE_TXBF_VERIFY_NOCOMP\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = OS_NTOHS(value); + snprintf((char *)str, sizeof(str), "%d", value); + + result = (BOOLEAN)Set_ATE_TXBF_VERIFY_NoComp_Proc(pAd, str); + + pRaCfg->data[0] = result; + pRaCfg->data[1] = pATEInfo->calParams[0]; + pRaCfg->data[2] = pATEInfo->calParams[1]; + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status) + 3, NDIS_STATUS_SUCCESS); + + return NDIS_STATUS_SUCCESS; +} +#endif /* TXBF_SUPPORT */ + + +static INT32 DO_RACFG_CMD_ATE_SHOW_PARAM( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + INT32 Status = NDIS_STATUS_SUCCESS; + UINT32 Len; + ATE_EX_PARAM ATEExParam; + + ATEExParam.mode = pATEInfo->Mode; + ATEExParam.TxPower0 = pATEInfo->TxPower0; + ATEExParam.TxPower1 = pATEInfo->TxPower1; + +#ifdef DOT11N_SS3_SUPPORT + ATEExParam.TxPower2 = pATEInfo->TxPower2; +#endif /* DOT11N_SS3_SUPPORT */ + + ATEExParam.TxAntennaSel = pATEInfo->TxAntennaSel; + ATEExParam.RxAntennaSel = pATEInfo->RxAntennaSel; + +#ifdef CONFIG_AP_SUPPORT + NdisMoveMemory(ATEExParam.DA, pATEInfo->Addr1, MAC_ADDR_LEN); + NdisMoveMemory(ATEExParam.SA, pATEInfo->Addr3, MAC_ADDR_LEN); + NdisMoveMemory(ATEExParam.BSSID, pATEInfo->Addr2, MAC_ADDR_LEN); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + NdisMoveMemory(ATEExParam.DA, pATEInfo->Addr3, MAC_ADDR_LEN); + NdisMoveMemory(ATEExParam.SA, pATEInfo->Addr2, MAC_ADDR_LEN); + NdisMoveMemory(ATEExParam.BSSID, pATEInfo->Addr1, MAC_ADDR_LEN); +#endif /* CONFIG_STA_SUPPORT */ + + ATEExParam.MCS = pATEInfo->TxWI.MCS; + ATEExParam.PhyMode = pATEInfo->TxWI.PHYMODE; + ATEExParam.ShortGI = pATEInfo->TxWI.ShortGI; + ATEExParam.BW = pATEInfo->TxWI.BW; + ATEExParam.Channel = OS_HTONL(pATEInfo->Channel); + ATEExParam.TxLength = OS_HTONL(pATEInfo->TxLength); + ATEExParam.TxCount = OS_HTONL(pATEInfo->TxCount); + ATEExParam.RFFreqOffset = OS_HTONL(pATEInfo->RFFreqOffset); + ATEExParam.IPG = OS_HTONL(pATEInfo->IPG); + ATEExParam.RxTotalCnt = OS_HTONL(pATEInfo->RxTotalCnt); + ATEExParam.RxCntPerSec = OS_HTONL(pATEInfo->RxCntPerSec); + ATEExParam.LastSNR0 = pATEInfo->LastSNR0; + ATEExParam.LastSNR1 = pATEInfo->LastSNR1; +#ifdef DOT11N_SS3_SUPPORT + ATEExParam.LastSNR2 = pATEInfo->LastSNR2; +#endif /* DOT11N_SS3_SUPPORT */ + ATEExParam.LastRssi0 = pATEInfo->LastRssi0; + ATEExParam.LastRssi1 = pATEInfo->LastRssi1; + ATEExParam.LastRssi2 = pATEInfo->LastRssi2; + ATEExParam.AvgRssi0 = pATEInfo->AvgRssi0; + ATEExParam.AvgRssi1 = pATEInfo->AvgRssi1; + ATEExParam.AvgRssi2 = pATEInfo->AvgRssi2; + ATEExParam.AvgRssi0X8 = OS_HTONS(pATEInfo->AvgRssi0X8); + ATEExParam.AvgRssi1X8 = OS_HTONS(pATEInfo->AvgRssi1X8); + ATEExParam.AvgRssi2X8 = OS_HTONS(pATEInfo->AvgRssi2X8); + + Len = sizeof(ATEExParam); + NdisMoveMemory(pRaCfg->data, &ATEExParam, Len); + + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status) + Len, NDIS_STATUS_SUCCESS); + + return Status; +} + + +typedef INT (*RACFG_CMD_HANDLER)( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN struct ate_racfghdr *pRaCfg); + + +static RACFG_CMD_HANDLER RACFG_CMD_SET1[] = +{ + /* cmd id start from 0x0 */ + DO_RACFG_CMD_RF_WRITE_ALL,/* 0x0000 */ + DO_RACFG_CMD_E2PROM_READ16,/* 0x0001 */ + DO_RACFG_CMD_E2PROM_WRITE16,/* 0x0002 */ + DO_RACFG_CMD_E2PROM_READ_ALL,/* 0x0003 */ + DO_RACFG_CMD_E2PROM_WRITE_ALL,/* 0x0004 */ + DO_RACFG_CMD_IO_READ,/* 0x0005 */ + DO_RACFG_CMD_IO_WRITE,/* 0x0006 */ + DO_RACFG_CMD_IO_READ_BULK,/* 0x0007 */ + DO_RACFG_CMD_BBP_READ8,/* 0x0008 */ + DO_RACFG_CMD_BBP_WRITE8,/* 0x0009 */ + DO_RACFG_CMD_BBP_READ_ALL,/* 0x000a */ + DO_RACFG_CMD_GET_COUNTER,/* 0x000b */ + DO_RACFG_CMD_CLEAR_COUNTER,/* 0x000c */ + NULL /* RACFG_CMD_RSV1 */,/* 0x000d */ + NULL /* RACFG_CMD_RSV2 */,/* 0x000e */ + NULL /* RACFG_CMD_RSV3 */,/* 0x000f */ + DO_RACFG_CMD_TX_START,/* 0x0010 */ + DO_RACFG_CMD_GET_TX_STATUS,/* 0x0011 */ + DO_RACFG_CMD_TX_STOP,/* 0x0012 */ + DO_RACFG_CMD_RX_START,/* 0x0013 */ + DO_RACFG_CMD_RX_STOP,/* 0x0014 */ + DO_RACFG_CMD_GET_NOISE_LEVEL,/* 0x0015 */ +#if defined(RT2883) || defined(RT3883) +#ifdef TXBF_SUPPORT + DO_RACFG_CMD_QUERY_BF_RSP,/* 0x0016 */ + DO_RACFG_CMD_QUERY_IBF_TAG,/* 0x0017 */ + DO_RACFG_CMD_QUERY_IBF_TAG,/* 0x0018 */ + DO_RACFG_CMD_QUERY_IBF_PROFILE,/* 0x0019 */ + DO_RACFG_CMD_QUERY_IBF_PROFILE,/* 0x001a */ + DO_RACFG_CMD_WRITE_IBF_TAG,/* 0x001b */ + DO_RACFG_CMD_WRITE_IBF_TAG,/* 0x001c */ + DO_RACFG_CMD_WRITE_IBF_PROFILE,/* 0x001d */ + DO_RACFG_CMD_WRITE_IBF_PROFILE,/* 0x001e */ + NULL /* RACFG_CMD_RSV4 */,/* 0x001f */ + DO_RACFG_CALIBRATION_CAPTURE/* 0x0020 */ +#else + NULL +#endif /* TXBF_SUPPORT */ +#else + NULL +#endif /* defined(RT2883) || defined(RT3883) */ + /* cmd id end with 0x20 */ +}; + + +static RACFG_CMD_HANDLER RACFG_CMD_SET2[] = +{ + /* cmd id start from 0x80 */ + DO_RACFG_CMD_ATE_START,/* 0x0080 */ + DO_RACFG_CMD_ATE_STOP/* 0x0081 */ + /* cmd id end with 0x81 */ +}; + + +static RACFG_CMD_HANDLER RACFG_CMD_SET3[] = +{ + /* cmd id start from 0x100 */ + DO_RACFG_CMD_ATE_START_TX_CARRIER,/* 0x0100 */ + DO_RACFG_CMD_ATE_START_TX_CONT,/* 0x0101 */ + DO_RACFG_CMD_ATE_START_TX_FRAME,/* 0x0102 */ + DO_RACFG_CMD_ATE_SET_BW,/* 0x0103 */ + DO_RACFG_CMD_ATE_SET_TX_POWER0,/* 0x0104 */ + DO_RACFG_CMD_ATE_SET_TX_POWER1,/* 0x0105 */ + DO_RACFG_CMD_ATE_SET_FREQ_OFFSET,/* 0x0106 */ + DO_RACFG_CMD_ATE_GET_STATISTICS,/* 0x0107 */ + DO_RACFG_CMD_ATE_RESET_COUNTER,/* 0x0108 */ + DO_RACFG_CMD_ATE_SEL_TX_ANTENNA,/* 0x0109 */ + DO_RACFG_CMD_ATE_SEL_RX_ANTENNA,/* 0x010a */ + DO_RACFG_CMD_ATE_SET_PREAMBLE,/* 0x010b */ + DO_RACFG_CMD_ATE_SET_CHANNEL,/* 0x010c */ + DO_RACFG_CMD_ATE_SET_ADDR1,/* 0x010d */ + DO_RACFG_CMD_ATE_SET_ADDR2,/* 0x010e */ + DO_RACFG_CMD_ATE_SET_ADDR3,/* 0x010f */ + DO_RACFG_CMD_ATE_SET_RATE,/* 0x0110 */ + DO_RACFG_CMD_ATE_SET_TX_FRAME_LEN,/* 0x0111 */ + DO_RACFG_CMD_ATE_SET_TX_FRAME_COUNT,/* 0x0112 */ + DO_RACFG_CMD_ATE_START_RX_FRAME,/* 0x0113 */ + DO_RACFG_CMD_ATE_E2PROM_READ_BULK,/* 0x0114 */ + DO_RACFG_CMD_ATE_E2PROM_WRITE_BULK,/* 0x0115 */ + DO_RACFG_CMD_ATE_IO_WRITE_BULK,/* 0x0116 */ + DO_RACFG_CMD_ATE_BBP_READ_BULK,/* 0x0117 */ + DO_RACFG_CMD_ATE_BBP_WRITE_BULK,/* 0x0118 */ +#ifdef RTMP_RF_RW_SUPPORT +#ifndef RF_BANK + DO_RACFG_CMD_ATE_RF_READ_BULK,/* 0x0119 */ + DO_RACFG_CMD_ATE_RF_WRITE_BULK,/* 0x011a */ +#else + NULL,/* 0x0119 */ + NULL,/* 0x011a */ +#endif /* !RF_BANK */ +#else + NULL,/* 0x0119 */ + NULL,/* 0x011a */ +#endif /* RTMP_RF_RW_SUPPORT */ +#ifdef DOT11N_SS3_SUPPORT + DO_RACFG_CMD_ATE_SET_TX_POWER2,/* 0x011b */ +#else + NULL,/* 0x011b */ +#endif /* DOT11N_SS3_SUPPORT */ +#ifdef TXBF_SUPPORT + DO_RACFG_CMD_ATE_TXBF_DUT_INIT,/* 0x011c */ + DO_RACFG_CMD_ATE_TXBF_LNA_CAL,/* 0x011d */ + DO_RACFG_CMD_ATE_TXBF_DIV_CAL,/* 0x011e */ + DO_RACFG_CMD_ATE_TXBF_PHASE_CAL,/* 0x011f */ + DO_RACFG_CMD_ATE_TXBF_GOLDEN_INIT,/* 0x0120 */ + DO_RACFG_CMD_ATE_TXBF_VERIFY,/* 0x0121 */ + DO_RACFG_CMD_ATE_TXBF_VERIFY_NOCOMP,/* 0x0122 */ +#else + NULL,/* 0x011c */ + NULL,/* 0x011d */ + NULL,/* 0x011e */ + NULL,/* 0x011f */ + NULL,/* 0x0120 */ + NULL,/* 0x0121 */ + NULL,/* 0x0122 */ +#endif /* TXBF_SUPPORT */ + +#ifdef RTMP_RF_RW_SUPPORT +#ifdef RF_BANK + DO_RACFG_CMD_ATE_RF_READ_BULK_BANK,/* 0x0123 */ + DO_RACFG_CMD_ATE_RF_WRITE_BULK_BANK,/* 0x0124 */ +#else + NULL,/* 0x0123 */ + NULL,/* 0x0124 */ +#endif /* RF_BANK */ +#else + NULL,/* 0x0123 */ + NULL,/* 0x0124 */ +#endif /* RTMP_RF_RW_SUPPORT */ + /* cmd id end with 0x124 */ +}; + + +static RACFG_CMD_HANDLER RACFG_CMD_SET4[] = +{ + /* cmd id start from 0x200 */ +#ifdef RT3883 + DO_RACFG_CMD_ATE_ETH_EXT_SETTING,/* 0x0200 */ +#else + NULL,/* 0x0200 */ +#endif /* RT3883 */ + NULL,/* 0x0201 */ +#if defined (RT3883) || defined (RT3352) || defined (RT5350) + DO_RACFG_CMD_ATE_RUN_CPUBUSY,/* 0x0202 */ +#else + NULL,/* 0x0202 */ +#endif /* defined (RT3883) || defined (RT3352) || defined (RT5350) */ + NULL,/* 0x0203 */ +#ifdef RT6352 + DO_RACFG_CMD_ATE_CALIBRATION,/* 0x0204 */ + DO_RACFG_CMD_ATE_TSSI_COMPENSATION,/* 0x0205 */ + DO_RACFG_CMD_ATE_TEMP_COMPENSATION,/* 0x0206 */ +#else + NULL,/* 0x0204 */ + NULL,/* 0x0205 */ + NULL,/* 0x0206 */ +#endif /* RT6352 */ + + /* cmd id end with 0x206 */ +}; + + +static RACFG_CMD_HANDLER RACFG_CMD_SET5[] = +{ + DO_RACFG_CMD_ATE_SHOW_PARAM +}; + + +typedef struct RACFG_CMD_TABLE_{ + RACFG_CMD_HANDLER *cmdSet; + int cmdSetSize; + int cmdOffset; +}RACFG_CMD_TABLE; + + +RACFG_CMD_TABLE RACFG_CMD_TABLES[]={ + { + RACFG_CMD_SET1, + sizeof(RACFG_CMD_SET1) / sizeof(RACFG_CMD_HANDLER), + 0x0, + }, + { + RACFG_CMD_SET2, + sizeof(RACFG_CMD_SET2) / sizeof(RACFG_CMD_HANDLER), + 0x80, + }, + { + RACFG_CMD_SET3, + sizeof(RACFG_CMD_SET3) / sizeof(RACFG_CMD_HANDLER), + 0x100, + }, + { + RACFG_CMD_SET4, + sizeof(RACFG_CMD_SET4) / sizeof(RACFG_CMD_HANDLER), + 0x200, + }, + { + RACFG_CMD_SET5, + sizeof(RACFG_CMD_SET5) / sizeof(RACFG_CMD_HANDLER), + 0xff00, + } + +}; + + +static INT32 RACfgCMDHandler( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN pRACFGHDR pRaCfg) +{ + PATE_INFO pATEInfo = &(pAd->ate); + INT32 Status = NDIS_STATUS_SUCCESS; + USHORT Command_Id; + UINT32 TableIndex = 0; + + Command_Id = OS_NTOHS(pRaCfg->command_id); + DBGPRINT(RT_DEBUG_TRACE,("\n%s: Command_Id = 0x%04x !\n", __FUNCTION__, Command_Id)); + + while (TableIndex < (sizeof(RACFG_CMD_TABLES) / sizeof(RACFG_CMD_TABLE))) + { + int cmd_index = 0; + cmd_index = Command_Id - RACFG_CMD_TABLES[TableIndex].cmdOffset; + if ((cmd_index >= 0) && (cmd_index < RACFG_CMD_TABLES[TableIndex].cmdSetSize)) + { + RACFG_CMD_HANDLER *pCmdSet; + + pCmdSet = RACFG_CMD_TABLES[TableIndex].cmdSet; + + if (pCmdSet[cmd_index] != NULL) + Status = (*pCmdSet[cmd_index])(pAd, wrq, pRaCfg); + break; + } + TableIndex++; + } + + /* In passive mode, only commands that read registers are allowed. */ + if (pATEInfo->PassiveMode) + { + int entry, allowCmd = FALSE; + static int allowedCmds[] = { + RACFG_CMD_E2PROM_READ16, RACFG_CMD_E2PROM_READ_ALL, + RACFG_CMD_IO_READ, RACFG_CMD_IO_READ_BULK, + RACFG_CMD_BBP_READ8, RACFG_CMD_BBP_READ_ALL, + RACFG_CMD_ATE_E2PROM_READ_BULK, + RACFG_CMD_ATE_BBP_READ_BULK, +#ifdef RTMP_RF_RW_SUPPORT +#ifdef RF_BANK + RACFG_CMD_ATE_RF_READ_BULK_BANK, +#else + RACFG_CMD_ATE_RF_READ_BULK, +#endif /* RF_BANK */ +#endif /* RTMP_RF_RW_SUPPORT */ +#if defined(RT2883) || defined(RT3883) + RACFG_CMD_QUERY_IBF_TAG, RACFG_CMD_QUERY_EBF_TAG, + RACFG_CMD_QUERY_IBF_PROFILE, RACFG_CMD_QUERY_EBF_PROFILE +#endif /* defined(RT2883) || defined(RT3883) */ + }; + + for (entry=0; entrystatus); + if (offset==BBP_R27 || (offset>=BBP_R174 && offset<=BBP_R182)) + allowCmd = TRUE; + } + + /* If not allowed, then ignore the command. */ + if (!allowCmd) + { + ResponseToGUI(pRaCfg, wrq, sizeof(pRaCfg->status), NDIS_STATUS_SUCCESS); + Status = NDIS_STATUS_FAILURE; + } + } + + return Status; +} + + +INT RtmpDoAte( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN PSTRING wrq_name) +{ + INT32 Status = NDIS_STATUS_SUCCESS; + struct ate_racfghdr *pRaCfg; + UINT32 ATEMagicNum; + + os_alloc_mem_suspend(pAd, (UCHAR **)&pRaCfg, sizeof(struct ate_racfghdr)); + + if (!pRaCfg) + { + Status = -ENOMEM; + goto ERROR0; + } + + NdisZeroMemory(pRaCfg, sizeof(struct ate_racfghdr)); + Status = copy_from_user((PUCHAR)pRaCfg, wrq->u.data.pointer, wrq->u.data.length); + + if (Status) + { + Status = -EFAULT; + goto ERROR1; + } + + ATEMagicNum = OS_NTOHL(pRaCfg->magic_no); + + switch(ATEMagicNum) + { + case RACFG_MAGIC_NO: + Status = RACfgCMDHandler(pAd, wrq, pRaCfg); + break; + + default: + Status = NDIS_STATUS_FAILURE; + DBGPRINT_ERR(("Unknown magic number of RACFG command = %x\n", ATEMagicNum)); + break; + } + + ERROR1: + os_free_mem(NULL, pRaCfg); + ERROR0: + return Status; +} + + +VOID ATE_QA_Statistics( + IN PRTMP_ADAPTER pAd, + IN PRXWI_STRUC pRxWI, + IN PRT28XX_RXD_STRUC pRxD, + IN PHEADER_802_11 pHeader) +{ + PATE_INFO pATEInfo = &(pAd->ate); +#if defined(RT2883) || defined(RT3883) + UINT32 lastRxRate = 0; +#endif /* defined(RT2883) || defined(RT3883) */ + + /* update counter first */ + if (pHeader != NULL) + { + if (pHeader->FC.Type == BTYPE_DATA) + { + if (pRxD->U2M) + { + pATEInfo->U2M++; +#if defined(RT2883) || defined(RT3883) + if (pRxWI->MPDUtotalByteCount >= 32) + { + lastRxRate = (pRxWI->MCS) + (pRxWI->BW << 7) + + (pRxWI->ShortGI << 8) + (pRxWI->STBC << 9) + + (pRxWI->PHYMODE << 14) + + (pRxWI->MPDUtotalByteCount<< 16); + } +#endif /* defined(RT2883) || defined(RT3883) */ + } + else + pATEInfo->OtherData++; + } + else if (pHeader->FC.Type == BTYPE_MGMT) + { + if (pHeader->FC.SubType == SUBTYPE_BEACON) + pATEInfo->Beacon++; + else + pATEInfo->OtherCount++; + } + else if (pHeader->FC.Type == BTYPE_CNTL) + { + pATEInfo->OtherCount++; + } + } + pATEInfo->RSSI0 = pRxWI->RSSI0; + pATEInfo->RSSI1 = pRxWI->RSSI1; + pATEInfo->RSSI2 = pRxWI->RSSI2; + pATEInfo->SNR0 = pRxWI->SNR0; + pATEInfo->SNR1 = pRxWI->SNR1; + +#if defined(RT2883) || defined(RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + { +#ifdef DOT11N_SS3_SUPPORT + pATEInfo->SNR2 = pRxWI->SNR2; +#endif /* DOT11N_SS3_SUPPORT */ +#ifdef TXBF_SUPPORT + pATEInfo->LastRxRate = lastRxRate; +#endif /* TXBF_SUPPORT */ + pATEInfo->BF_SNR[0] = BF_SNR_OFFSET + pRxWI->BF_SNR0; + pATEInfo->BF_SNR[1] = BF_SNR_OFFSET + pRxWI->BF_SNR1; +#ifdef DOT11N_SS3_SUPPORT + pATEInfo->BF_SNR[2] = BF_SNR_OFFSET + pRxWI->BF_SNR2; +#endif /* DOT11N_SS3_SUPPORT */ + } +#endif /* defined(RT2883) || defined(RT3883) */ + +} + + +INT Set_TxStop_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + DBGPRINT(RT_DEBUG_TRACE,("Set_TxStop_Proc\n")); + + if (Set_ATE_Proc(pAd, "TXSTOP")) + { + return TRUE; + } + else + { + return FALSE; + } +} + + +INT Set_RxStop_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + DBGPRINT(RT_DEBUG_TRACE,("Set_RxStop_Proc\n")); + + if (Set_ATE_Proc(pAd, "RXSTOP")) + { + return TRUE; + } + else + { + return FALSE; + } +} + + +#ifdef DBG +INT Set_EERead_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + USHORT buffer[EEPROM_SIZE >> 1]; + USHORT *p; + INT offset; + + rt_ee_read_all(pAd, (USHORT *)buffer); + p = buffer; + + for (offset = 0; offset < (EEPROM_SIZE >> 1); offset++) + { + DBGPRINT(RT_DEBUG_OFF, ("%4.4x ", *p)); + if (((offset+1) % 16) == 0) + DBGPRINT(RT_DEBUG_OFF, ("\n")); + p++; + } + + return TRUE; +} + + +INT Set_EEWrite_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + USHORT offset = 0, value; + PSTRING p2 = arg; + + while ((*p2 != ':') && (*p2 != '\0')) + { + p2++; + } + + if (*p2 == ':') + { + A2Hex(offset, arg); + A2Hex(value, p2 + 1); + } + else + { + A2Hex(value, arg); + } + + if (offset >= EEPROM_SIZE) + { + DBGPRINT_ERR(("Offset can not exceed EEPROM_SIZE( == 0x%04x)\n", EEPROM_SIZE)); + return FALSE; + } + + RT28xx_EEPROM_WRITE16(pAd, offset, value); + + return TRUE; +} + + +INT Set_BBPRead_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR value = 0, offset; + + A2Hex(offset, arg); + + ATE_BBPRead(pAd, offset, &value); + + DBGPRINT(RT_DEBUG_OFF, ("%x\n", value)); + + return TRUE; +} + + +INT Set_BBPWrite_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + USHORT offset = 0; + PSTRING p2 = arg; + UCHAR value; + + while ((*p2 != ':') && (*p2 != '\0')) + { + p2++; + } + + if (*p2 == ':') + { + A2Hex(offset, arg); + A2Hex(value, p2 + 1); + } + else + { + A2Hex(value, arg); + } + + ATE_BBPWrite(pAd, offset, value); + + return TRUE; +} + + +INT Set_RFWrite_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PSTRING p2, p3, p4; + UINT32 R1, R2, R3, R4; + + p2 = arg; + + while ((*p2 != ':') && (*p2 != '\0')) + { + p2++; + } + + if (*p2 != ':') + return FALSE; + + p3 = p2 + 1; + + while((*p3 != ':') && (*p3 != '\0')) + { + p3++; + } + + if (*p3 != ':') + return FALSE; + + p4 = p3 + 1; + + while ((*p4 != ':') && (*p4 != '\0')) + { + p4++; + } + + if (*p4 != ':') + return FALSE; + + + A2Hex(R1, arg); + A2Hex(R2, p2 + 1); + A2Hex(R3, p3 + 1); + A2Hex(R4, p4 + 1); + + RTMP_RF_IO_WRITE32(pAd, R1); + RTMP_RF_IO_WRITE32(pAd, R2); + RTMP_RF_IO_WRITE32(pAd, R3); + RTMP_RF_IO_WRITE32(pAd, R4); + + return TRUE; +} +#endif /* DBG */ +#endif /* RALINK_QA */ + diff --git a/mt7620/src/ate/include/rt_ate.h b/mt7620/src/ate/include/rt_ate.h new file mode 100644 index 0000000..d4197d2 --- /dev/null +++ b/mt7620/src/ate/include/rt_ate.h @@ -0,0 +1,1098 @@ +/* + *************************************************************************** + * 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_ate.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ + +#ifndef __RT_ATE_H__ +#define __RT_ATE_H__ + +#ifdef RALINK_ATE +#ifndef STATS_COUNT_SUPPORT +#error "For ATE support, please set HAS_ATE=y and HAS_STATS_COUNT=y." +#endif /* !STATS_COUNT_SUPPORT */ +#endif /* RALINK_ATE */ + +typedef struct _ATE_CHIP_STRUCT { + /* functions */ + VOID (*ChannelSwitch)(PRTMP_ADAPTER pAd); + INT (*TxPwrHandler)(PRTMP_ADAPTER pAd, char index); + INT (*TssiCalibration)(PRTMP_ADAPTER pAd, PSTRING arg); + INT (*ExtendedTssiCalibration)(PRTMP_ADAPTER pAd, PSTRING arg); + VOID (*RxVGAInit)(PRTMP_ADAPTER pAd); + VOID (*AsicSetTxRxPath)(PRTMP_ADAPTER pAd); + VOID (*AdjustTxPower)(PRTMP_ADAPTER pAd); + VOID (*AsicExtraPowerOverMAC)(PRTMP_ADAPTER pAd); + + /* command handlers */ + INT (*Set_BW_Proc)(PRTMP_ADAPTER pAd, PSTRING arg); + INT (*Set_FREQ_OFFSET_Proc)(PRTMP_ADAPTER pAd, PSTRING arg); + + /* variables */ + INT maxTxPwrCnt; + BOOLEAN bBBPStoreTXCARR; + BOOLEAN bBBPStoreTXCARRSUPP; + BOOLEAN bBBPStoreTXCONT; + BOOLEAN bBBPLoadATESTOP; + + /* TSSI related */ + INT32 tssi_slope[2]; + INT32 tssi_offset[3][2]; + INT32 pwr_diff_pre[2]; + INT32 ant_pwr_offset[2]; + INT32 curr_temperature; +}ATE_CHIP_STRUCT, *PATE_CHIP_STRUCT; + +typedef union _CAPTURE_MODE_SHARE_MEMORY { + struct + { + UINT32 LOW_BYTE0:8; + UINT32 LOW_BYTE1:8; + UINT32 HIGH_BYTE0:8; + UINT32 HIGH_BYTE1:8; + } field; + UINT32 Value; +}CAPTURE_MODE_SHARE_MEMORY, *PCAPTURE_MODE_SHARE_MEMORY; + +typedef struct _ATE_INFO { + PATE_CHIP_STRUCT pChipStruct; + UCHAR Mode; + BOOLEAN PassiveMode; +#ifdef RT3350 + UCHAR PABias; +#endif /* RT3350 */ + CHAR TxPower0; + CHAR TxPower1; +#ifdef DOT11N_SS3_SUPPORT + CHAR TxPower2; +#endif /* DOT11N_SS3_SUPPORT */ + CHAR MinTxPowerBandA; /* Power range of early chipsets is -7~15 in A band */ + CHAR MaxTxPowerBandA; /* Power range of early chipsets is -7~15 in A band */ + CHAR TxAntennaSel; + CHAR RxAntennaSel; + TXWI_STRUC TxWI; /* TXWI */ + USHORT QID; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + UCHAR Addr3[MAC_ADDR_LEN]; + UCHAR Channel; + UCHAR Payload; /* Payload pattern */ + UCHAR TxMethod; /* Early chipsets must be applied old TXCONT/TXCARR/TXCARS mechanism. */ + UINT32 TxLength; + UINT32 TxCount; + UINT32 TxDoneCount; /* Tx DMA Done */ + UINT32 RFFreqOffset; + UINT32 IPG; + BOOLEAN bRxFER; /* Show Rx Frame Error Rate */ + BOOLEAN bQAEnabled; /* QA is used. */ + BOOLEAN bQATxStart; /* Have compiled QA in and use it to ATE tx. */ + BOOLEAN bQARxStart; /* Have compiled QA in and use it to ATE rx. */ + BOOLEAN bAutoTxAlc; /* Set Auto Tx Alc */ + BOOLEAN bDPDEnable; /* Set DPD Calibration Enable */ + BOOLEAN bLowTemperature; /* Trigger Temperature Sensor */ +#ifdef RTMP_INTERNAL_TX_ALC +#if defined(RT3350) || defined(RT3352) + BOOLEAN bTSSICalbrEnableG; /* Enable TSSI calibration */ + CHAR TssiRefPerChannel[CFG80211_NUM_OF_CHAN_2GHZ]; + CHAR TssiDeltaPerChannel[CFG80211_NUM_OF_CHAN_2GHZ]; +#endif /* defined(RT3350) || defined(RT3352) */ +#endif /* RTMP_INTERNAL_TX_ALC */ +#if defined(RT5592) || defined(RT6352) +#ifdef RTMP_TEMPERATURE_COMPENSATION + BOOLEAN bTSSICalbrEnableG; /* Enable G-band TSSI calibration */ + BOOLEAN bTSSICalbrEnableA; /* Enable A-band TSSI calibration */ + CHAR TssiReadSampleG[TSSI_READ_SAMPLE_NUM]; + CHAR TssiReadSampleA[TSSI_READ_SAMPLE_NUM]; +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + UCHAR rx_agc_fc_offset20M; + UCHAR rx_agc_fc_offset40M; + UCHAR CaliBW20RfR24; + UCHAR CaliBW40RfR24; +#endif /* defined(RT5592) || defined(RT6352) */ +#ifdef TXBF_SUPPORT + BOOLEAN bTxBF; /* Enable Tx Bean Forming */ + SHORT txSoundingMode; /* Sounding mode for non-QA ATE. 0=none, 1=Data Sounding, 2=NDP */ + UCHAR calParams[2]; +#endif /* TXBF_SUPPORT */ +#ifdef RTMP_MAC_PCI + BOOLEAN bFWLoading; /* Reload firmware when ATE is done. */ +#endif /* RTMP_MAC_PCI */ + UINT32 RxTotalCnt; + UINT32 RxCntPerSec; + UCHAR forceBBPReg; /* force to not update the specific BBP register, now used for ATE TxBF */ + + CHAR LastSNR0; /* last received SNR */ + CHAR LastSNR1; /* last received SNR for 2nd antenna */ +#ifdef DOT11N_SS3_SUPPORT + CHAR LastSNR2; +#endif /* DOT11N_SS3_SUPPORT */ + CHAR LastRssi0; /* last received RSSI */ + CHAR LastRssi1; /* last received RSSI for 2nd antenna */ + CHAR LastRssi2; /* last received RSSI for 3rd antenna */ + CHAR AvgRssi0; /* last 8 frames' average RSSI */ + CHAR AvgRssi1; /* last 8 frames' average RSSI */ + CHAR AvgRssi2; /* last 8 frames' average RSSI */ + SHORT AvgRssi0X8; /* sum of last 8 frames' RSSI */ + SHORT AvgRssi1X8; /* sum of last 8 frames' RSSI */ + SHORT AvgRssi2X8; /* sum of last 8 frames' RSSI */ + UINT32 NumOfAvgRssiSample; + UINT32 Default_TX_PIN_CFG; + USHORT HLen; /* Header Length */ + +#ifdef RALINK_QA + /* Tx frame */ + USHORT PLen; /* Pattern Length */ + UCHAR Header[32]; /* Header buffer */ + UCHAR Pattern[32]; /* Pattern buffer */ + USHORT DLen; /* Data Length */ + USHORT seq; + UINT32 CID; + RTMP_OS_PID AtePid; + /* counters */ + UINT32 U2M; + UINT32 OtherData; + UINT32 Beacon; + UINT32 OtherCount; + UINT32 TxAc0; + UINT32 TxAc1; + UINT32 TxAc2; + UINT32 TxAc3; + UINT32 TxHCCA; + UINT32 TxMgmt; + UINT32 RSSI0; + UINT32 RSSI1; + UINT32 RSSI2; + UINT32 SNR0; + UINT32 SNR1; +#ifdef DOT11N_SS3_SUPPORT + UINT32 SNR2; +#endif /* DOT11N_SS3_SUPPORT */ + INT32 BF_SNR[3]; /* Last RXWI BF SNR. Units=0.25 dB */ + /* TxStatus : 0 --> task is idle, 1 --> task is running */ + UCHAR TxStatus; +#endif /* RALINK_QA */ +#ifdef TXBF_SUPPORT +#define MAX_SOUNDING_RESPONSE_SIZE (57*2*2*9+3+2+6) /* Assume 114 carriers (40MHz), 3x3, 8bits/coeff, + SNR + HT HEADER + MIMO CONTROL FIELD */ + UCHAR sounding; + UINT32 sounding_jiffies; + CHAR soundingSNR[3]; + UINT32 LastRxRate; + UINT32 LastTxRate; + UINT32 soundingRespSize; /* Size of Sounding response */ + UCHAR soundingResp[MAX_SOUNDING_RESPONSE_SIZE]; /* Entire Sounding response */ +#endif /* TXBF_SUPPORT */ + RALINK_TIMER_STRUCT PeriodicTimer; + ULONG OneSecPeriodicRound; + ULONG PeriodicRound; + OS_NDIS_SPIN_LOCK TssiSemLock; +} ATE_INFO, *PATE_INFO; + +/* + Use bitmap to allow coexist of ATE_TXFRAME + and ATE_RXFRAME(i.e.,to support LoopBack mode). +*/ +#define fATE_IDLE 0x00 +#define fATE_TX_ENABLE 0x01 +#define fATE_RX_ENABLE 0x02 +#define fATE_TXCONT_ENABLE 0x04 +#define fATE_TXCARR_ENABLE 0x08 +#define fATE_TXCARRSUPP_ENABLE 0x10 +#define fATE_RESERVED_1 0x20 +#define fATE_RESERVED_2 0x40 +#define fATE_EXIT 0x80 + +/* Enter/Reset ATE */ +#define ATE_START (fATE_IDLE) +/* Stop/Exit ATE */ +#define ATE_STOP (fATE_EXIT) +/* Continuous Transmit Frames (without time gap) */ +#define ATE_TXCONT ((fATE_TX_ENABLE)|(fATE_TXCONT_ENABLE)) +/* Transmit Carrier */ +#define ATE_TXCARR ((fATE_TX_ENABLE)|(fATE_TXCARR_ENABLE)) +/* Transmit Carrier Suppression (information without carrier) */ +#define ATE_TXCARRSUPP ((fATE_TX_ENABLE)|(fATE_TXCARRSUPP_ENABLE)) +/* Transmit Frames */ +#define ATE_TXFRAME (fATE_TX_ENABLE) +/* Receive Frames */ +#define ATE_RXFRAME (fATE_RX_ENABLE) + + +#ifdef RTMP_INTERNAL_TX_ALC +#define EEPROM_TSSI_ENABLE 0x36 +#define EEPROM_TSSI_MODE_EXTEND 0x76 + +#define ATE_MDSM_NORMAL_TX_POWER 0x00 +#define ATE_MDSM_DROP_TX_POWER_BY_6dBm 0x01 +#define ATE_MDSM_DROP_TX_POWER_BY_12dBm 0x02 +#define ATE_MDSM_ADD_TX_POWER_BY_6dBm 0x03 +#define ATE_MDSM_BBP_R1_STATIC_TX_POWER_CONTROL_MASK 0x03 +#endif /* RTMP_INTERNAL_TX_ALC */ + +#define LEN_OF_ARG 16 +#define ATE_ON(_p) (((_p)->ate.Mode) != ATE_STOP) +#define TX_METHOD_0 0 /* Early chipsets must be applied this original TXCONT/TXCARR/TXCARS mechanism. */ +#define TX_METHOD_1 1 /* Default TXCONT/TXCARR/TXCARS mechanism is TX_METHOD_1 */ +#define ANT_ALL 0 +#define ANT_0 1 +#define ANT_1 2 +#ifdef DOT11N_SS3_SUPPORT +#define ANT_2 3 +#endif /* DOT11N_SS3_SUPPORT */ + +#define ATE_MAC_TX_ENABLE(_A, _I, _pV) \ +{ \ + RTMP_IO_READ32(_A, _I, _pV); \ + (*(_pV)) |= (1 << 2); \ + RTMP_IO_WRITE32(_A, _I, (*(_pV))); \ +} + +#define ATE_MAC_TX_DISABLE(_A, _I, _pV) \ +{ \ + RTMP_IO_READ32(_A, _I, _pV); \ + (*(_pV)) &= ~(1 << 2); \ + RTMP_IO_WRITE32(_A, _I, (*(_pV))); \ +} + +#define ATE_MAC_RX_ENABLE(_A, _I, _pV) \ +{ \ + RTMP_IO_READ32(_A, _I, _pV); \ + (*(_pV)) |= (1 << 3); \ + RTMP_IO_WRITE32(_A, _I, (*(_pV))); \ +} + +#define ATE_MAC_RX_DISABLE(_A, _I, _pV) \ +{ \ + RTMP_IO_READ32(_A, _I, _pV); \ + (*(_pV)) &= ~(1 << 3); \ + RTMP_IO_WRITE32(_A, _I, (*(_pV))); \ +} + +/* Set MAC_SYS_CTRL(0x1004) Continuous Tx Production Test (bit4) = 1. */ +#define ATE_MAC_TX_CTS_ENABLE(_A, _I, _pV) \ +{ \ + RTMP_IO_READ32(_A, _I, _pV); \ + (*(_pV)) |= (1 << 4); \ + RTMP_IO_WRITE32(_A, _I, (*(_pV))); \ +} + +/* Clear MAC_SYS_CTRL(0x1004) Continuous Tx Production Test (bit4) = 0. */ +#define ATE_MAC_TX_CTS_DISABLE(_A, _I, _pV) \ +{ \ + RTMP_IO_READ32(_A, _I, _pV); \ + (*(_pV)) &= ~(1 << 4); \ + RTMP_IO_WRITE32(_A, _I, (*(_pV))); \ +} + +/* Clear BBP R22 to reset Tx Mode (bit7~bit0) = 0. */ +#define ATE_BBP_RESET_TX_MODE(_A, _I, _pV) \ +{ \ + ATE_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV); \ + (*(_pV)) &= (0x00); \ + ATE_BBP_IO_WRITE8_BY_REG_ID(_A, _I, (*(_pV))); \ +} + +/* Set BBP R22 to start Continuous Tx Mode (bit7) = 1. */ +#define ATE_BBP_START_CTS_TX_MODE(_A, _I, _pV) \ +{ \ + ATE_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV); \ + (*(_pV)) |= (1 << 7); \ + ATE_BBP_IO_WRITE8_BY_REG_ID(_A, _I, (*(_pV))); \ +} + +/* Clear BBP R22 to stop Continuous Tx Mode (bit7) = 0. */ +#define ATE_BBP_STOP_CTS_TX_MODE(_A, _I, _pV) \ +{ \ + ATE_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV); \ + (*(_pV)) &= ~(1 << 7); \ + ATE_BBP_IO_WRITE8_BY_REG_ID(_A, _I, (*(_pV))); \ +} + +/* Set BBP R24 to send out Continuous Tx sin wave (bit0) = 1. */ +#define ATE_BBP_CTS_TX_SIN_WAVE_ENABLE(_A, _I, _pV) \ +{ \ + ATE_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV); \ + (*(_pV)) |= (1 << 0); \ + ATE_BBP_IO_WRITE8_BY_REG_ID(_A, _I, (*(_pV))); \ +} + +/* Clear BBP R24 to stop Continuous Tx sin wave (bit0) = 0. */ +#define ATE_BBP_CTS_TX_SIN_WAVE_DISABLE(_A, _I, _pV) \ +{ \ + ATE_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV); \ + (*(_pV)) &= ~(1 << 0); \ + ATE_BBP_IO_WRITE8_BY_REG_ID(_A, _I, (*(_pV))); \ +} + +/* +========================================================================== + Description: + This routine sets initial value of VGA in the RX chain. + AGC is the abbreviation of "Automatic Gain Controller", + while VGA (Variable Gain Amplifier) is a part of AGC loop. + (i.e., VGA + level detector + feedback loop = AGC) + + Return: + VOID +========================================================================== +*/ +#define ATE_CHIP_RX_VGA_GAIN_INIT(__pAd) \ + if (__pAd->ate.pChipStruct->RxVGAInit != NULL) \ + __pAd->ate.pChipStruct->RxVGAInit(__pAd) + +#ifdef RTMP_MAC_PCI +#define ATEPCIReadBBPRegister(_A, _I, _pV) \ +{ \ + BBP_CSR_CFG_STRUC BbpCsr; \ + int j, k; \ + for (j=0; jBbpWriteLatch[_I]; \ + } \ +} + +#define ATEPCIWriteBBPRegister(_A, _I, _V) \ +{ \ + BBP_CSR_CFG_STRUC BbpCsr; \ + int BusyCnt; \ + for (BusyCnt=0; BusyCntBbpWriteLatch[_I] = _V; \ + break; \ + } \ + if (BusyCnt == MAX_BUSY_COUNT) \ + { \ + DBGPRINT_ERR(("BBP write R%d fail\n", _I)); \ + } \ +} + +#ifdef RT6352 +#define ATE_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) RTMP_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) +#define ATE_BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V) RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V) +#endif /* RT6352 */ +#ifndef RT6352 +#define ATE_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) ATEPCIReadBBPRegister(_A, _I, _pV) +#define ATE_BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V) ATEPCIWriteBBPRegister(_A, _I, _V) +#endif /* !RT6352 */ +#endif /* RTMP_MAC_PCI */ + + +INT DefaultATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index); + +#ifdef RT3883 +INT RT3883ATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index); +#endif /* RT3883 */ + +#ifdef RT305x +#if defined(RT3050) || defined(RT3052) || defined(RT3350) +#ifdef RT3050 +/* +========================================================================== + Description: + + AsicSwitchChannel() dedicated for RT3050 ATE. + +========================================================================== +*/ +VOID RT3050ATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd); +#endif /* RT3050 */ + +#ifdef RT3052 +VOID RT3052ATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd); +#endif /* RT3052 */ + +#ifdef RT3350 +VOID RT3350ATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd); +#endif /* RT3350 */ + +/* This routine is also for RT3050/RT3052/RT3350 */ +INT RT305xATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index); +#endif /* defined(RT3050) || defined(RT3052) || defined(RT3350) */ + +#ifdef RT3352 +VOID RT3352ATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd); + +INT RT3352ATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index); +#endif /* RT3352 */ + +#ifdef RT5350 +VOID RT5350ATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd); + +INT RT5350ATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index); +#endif /* RT5350 */ +#endif /* RT305x */ + + +#ifdef RT2883 +VOID RT2883ATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd); + +INT RT2883ATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index); +#endif /* RT2883 */ + +#if defined(RT28xx) || defined(RT2880) +VOID RT28xxATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd); + +INT RT28xxATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index); +#endif /* defined(RT28xx) || defined(RT2880) */ + + +#ifdef RT6352 +VOID RT635xATEFilterCalibration( + IN PRTMP_ADAPTER pAd); + +VOID RT635xATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd); + +INT RT635xATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index); + +VOID RT635xATEAsicCompensatePowerViaBBP( + IN PRTMP_ADAPTER pAd, + INOUT PCHAR pTotalDeltaPower); +#endif /* RT6352 */ + +#ifdef RALINK_QA +VOID ATE_QA_Statistics( + IN PRTMP_ADAPTER pAd, + IN PRXWI_STRUC pRxWI, + IN PRT28XX_RXD_STRUC p28xxRxD, + IN PHEADER_802_11 pHeader); + +INT RtmpDoAte( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN PSTRING wrq_name); + +INT Set_TxStop_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_RxStop_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef DBG +INT Set_EERead_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_EEWrite_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_BBPRead_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_BBPWrite_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_RFWrite_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* DBG */ +#endif /* RALINK_QA */ + + +#ifdef RTMP_RF_RW_SUPPORT +#ifdef RF_BANK +#define ATE_RF_IO_READ8_BY_REG_ID(_A, _B, _I, _pV) RT635xReadRFRegister(_A, _B, _I, _pV) +#define ATE_RF_IO_WRITE8_BY_REG_ID(_A, _B, _I, _V) RT635xWriteRFRegister(_A, _B, _I, _V) +#endif /* RF_BANK */ +#ifndef RF_BANK +#define ATE_RF_IO_READ8_BY_REG_ID(_A, _I, _pV) RT30xxReadRFRegister(_A, _I, _pV) +#define ATE_RF_IO_WRITE8_BY_REG_ID(_A, _I, _V) RT30xxWriteRFRegister(_A, _I, _V) +#endif /* !RF_BANK */ +#endif /* RTMP_RF_RW_SUPPORT */ + +#ifdef RALINK_QA +#define SYNC_CHANNEL_WITH_QA(_A, _pV)\ + if ((_A->bQATxStart == TRUE) || (_A->bQARxStart == TRUE))\ + {\ + return;\ + }\ + else\ + *_pV = _A->Channel +#else +#define SYNC_CHANNEL_WITH_QA(_A, _pV)\ + *_pV = _A->Channel +#endif /* RALINK_QA */ + +VOID rt_ee_read_all( + IN PRTMP_ADAPTER pAd, + OUT USHORT *Data); + +VOID rt_ee_write_all( + IN PRTMP_ADAPTER pAd, + IN USHORT *Data); + +VOID rt_ee_write_bulk( + IN PRTMP_ADAPTER pAd, + IN USHORT *Data, + IN USHORT offset, + IN USHORT length); + +INT Set_ATE_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_DA_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_SA_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_BSSID_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + + +INT Set_ATE_CHANNEL_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_INIT_CHAN_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ADCDump_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#ifdef RTMP_INTERNAL_TX_ALC +INT Set_ATE_TSSI_CALIBRATION_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_TSSI_CALIBRATION_EX_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef RT5350 +INT RT5350_ATETssiCalibrationExtend( + IN struct _RTMP_ADAPTER *pAd, + IN PSTRING arg); +#endif /* RT5350 */ + +#if defined(RT3350) || defined(RT3352) +INT RT335x_Set_ATE_TSSI_CALIBRATION_ENABLE_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +CHAR InsertTssi( + IN UCHAR InChannel, + IN UCHAR Channel0, + IN UCHAR Channel1, + IN CHAR Tssi0, + IN CHAR Tssi1); + +INT RT335xATETssiCalibrationExtend( + IN struct _RTMP_ADAPTER *pAd, + IN PSTRING arg); +#endif /* defined(RT3350) || defined(RT3352) */ + +CHAR ATEGetDesiredTSSI( + IN PRTMP_ADAPTER pAd); + +#endif /* RTMP_INTERNAL_TX_ALC */ + +#ifdef RTMP_TEMPERATURE_CALIBRATION +INT Set_ATE_TEMP_CAL_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_SHOW_TSSI_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* RTMP_TEMPERATURE_CALIBRATION */ + +#ifdef RT6352 +#ifdef RTMP_TEMPERATURE_CALIBRATION +INT RT6352_ATETempCalibration( + IN struct _RTMP_ADAPTER *pAd, + IN PSTRING arg); +#endif /* RTMP_TEMPERATURE_CALIBRATION */ +#endif /* RT6352 */ + +#ifdef RTMP_TEMPERATURE_COMPENSATION + +INT Set_ATE_READ_EXTERNAL_TSSI_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + +INT Set_ATE_TX_POWER0_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_TX_POWER1_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef DOT11N_SS3_SUPPORT +INT Set_ATE_TX_POWER2_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* DOT11N_SS3_SUPPORT */ + +INT Set_ATE_TX_Antenna_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_RX_Antenna_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +VOID DefaultATEAsicExtraPowerOverMAC( + IN PRTMP_ADAPTER pAd); + +VOID ATEAsicExtraPowerOverMAC( + IN PRTMP_ADAPTER pAd); +#ifdef RT3350 +INT Set_ATE_PA_Bias_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* RT3350 */ + +INT Default_Set_ATE_TX_FREQ_OFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef RT3883 +INT RT3883_Set_ATE_TX_FREQ_OFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* RT3883 */ + +#ifdef RT305x +#if defined(RT3050) || defined(RT3052) +INT RT305x_Set_ATE_TX_FREQ_OFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* defined(RT3050) || defined(RT3052) */ + +#ifdef RT3350 +INT RT3350_Set_ATE_TX_FREQ_OFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* RT3350 */ + +#ifdef RT3352 +INT RT3352_Set_ATE_TX_FREQ_OFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* RT3352 */ + +#ifdef RT5350 +INT RT5350_Set_ATE_TX_FREQ_OFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* RT5350 */ +#endif /* RT305x */ + + +#ifdef RT2883 +INT RT2883_Set_ATE_TX_FREQ_OFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* RT2883 */ + +#if defined(RT28xx) || defined(RT2880) +INT RT28xx_Set_ATE_TX_FREQ_OFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* defined(RT28xx) || defined(RT2880) */ + + +INT Set_ATE_TX_FREQ_OFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Default_Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef RT3883 +INT RT3883_Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* RT3883 */ + +#ifdef RT305x +#if defined(RT3050) || defined(RT3052) +INT RT305x_Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* defined(RT3050) || defined(RT3052) */ + +#ifdef RT3350 +INT RT3350_Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* RT3350 */ + +#ifdef RT3352 +INT RT3352_Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* RT3352 */ + +#ifdef RT5350 +INT RT5350_Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* RT5350 */ +#endif /* RT305x */ + + +#ifdef RT2883 +INT RT2883_Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* RT2883 */ + +#if defined(RT28xx) || defined(RT2880) +INT RT28xx_Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* defined(RT28xx) || defined(RT2880) */ + + +INT Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_TX_LENGTH_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_TX_COUNT_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_TX_MCS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_TX_STBC_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_TX_MODE_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_TX_GI_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + + +INT Set_ATE_RX_FER_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_Read_RF_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifndef RTMP_RF_RW_SUPPORT +INT Set_ATE_Write_RF1_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_Write_RF2_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_Write_RF3_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_Write_RF4_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* RTMP_RF_RW_SUPPORT */ + +INT Set_ATE_Load_E2P_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_Read_E2P_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef LED_CONTROL_SUPPORT +#endif /* LED_CONTROL_SUPPORT */ + +INT Set_ATE_AUTO_ALC_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_TEMP_SENSOR_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_IPG_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_Payload_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef TXBF_SUPPORT +INT Set_ATE_TXBF_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_TXSOUNDING_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_TXBF_DIVCAL_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_TXBF_LNACAL_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_TXBF_INIT_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_TXBF_CAL_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_TXBF_GOLDEN_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_TXBF_VERIFY_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_TXBF_VERIFY_NoComp_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_ForceBBP_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* TXBF_SUPPORT */ + + +INT Set_ATE_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ATE_Help_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +VOID DefaultATEAsicAdjustTxPower( + IN PRTMP_ADAPTER pAd); + +#ifdef RT305x +#ifdef RT3350 +VOID RT3350ATEAsicAdjustTxPower( + IN PRTMP_ADAPTER pAd); +#endif /* RT3350 */ +#ifdef RT3352 +VOID RT3352ATEAsicAdjustTxPower( + IN PRTMP_ADAPTER pAd); +#endif /* RT3352 */ +#ifdef RT5350 +#ifdef RTMP_INTERNAL_TX_ALC +UINT32 RT5350_ATEGetDesiredTSSI( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBbpR49); +#endif /* RTMP_INTERNAL_TX_ALC */ +VOID RT5350ATEAsicAdjustTxPower( + IN PRTMP_ADAPTER pAd); +#endif /* RT5350 */ +#endif /* RT305x */ + +VOID ATEAsicAdjustTxPower( + IN PRTMP_ADAPTER pAd); + +VOID ATESampleRssi( + IN PRTMP_ADAPTER pAd, + IN PRXWI_STRUC pRxWI); + +#ifdef RTMP_MAC_PCI +INT TxDmaBusy( + IN PRTMP_ADAPTER pAd); + +INT RxDmaBusy( + IN PRTMP_ADAPTER pAd); + +VOID RtmpDmaEnable( + IN PRTMP_ADAPTER pAd, + IN INT Enable); + +INT ATESetUpFrame( + IN PRTMP_ADAPTER pAd, + IN UINT32 TxIdx); +#endif /* RTMP_MAC_PCI */ + + + +NDIS_STATUS ChipStructAssign( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS ATEInit( + IN PRTMP_ADAPTER pAd); + +#ifdef RALINK_QA +VOID ReadQATxTypeFromBBP( + IN PRTMP_ADAPTER pAd); +#endif /* RALINK_QA */ + +NDIS_STATUS ATEBBPWriteWithRxChain( + IN RTMP_ADAPTER *pAd, + IN UCHAR bbpId, + IN CHAR bbpVal, + IN RX_CHAIN_IDX rx_ch_idx); + + +#ifdef RT3883 +VOID RT3883ATERxVGAInit( + IN PRTMP_ADAPTER pAd); +#endif /* RT3883 */ + +#ifdef RT305x +#if defined(RT3050) || defined(RT3052) || defined(RT3350) +VOID RT305xATERxVGAInit( + IN PRTMP_ADAPTER pAd); +#endif /* defined(RT3050) || defined(RT3052) || defined(RT3350) */ + +#ifdef RT3352 +VOID RT3352ATERxVGAInit( + IN PRTMP_ADAPTER pAd); +#endif /* RT3352 */ + +#ifdef RT5350 +VOID RT5350ATERxVGAInit( + IN PRTMP_ADAPTER pAd); + +VOID RT5350ATEAsicExtraPowerOverMAC( + IN PRTMP_ADAPTER pAd); +#endif /* RT5350 */ +#endif /* RT305x */ + + +#ifdef RT2883 +VOID RT2883ATERxVGAInit( + IN PRTMP_ADAPTER pAd); +#endif /* RT2883 */ + +#if defined(RT28xx) || defined(RT2880) +VOID RT28xxATERxVGAInit( + IN PRTMP_ADAPTER pAd); +#endif /* defined(RT28xx) || defined(RT2880) */ + + +VOID ATEPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID ATEAsicSetTxRxPath( + IN PRTMP_ADAPTER pAd); + +VOID RtmpRfIoWrite( + IN PRTMP_ADAPTER pAd); + +VOID ATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd); + +VOID BbpSoftReset( + IN PRTMP_ADAPTER pAd); + +#endif /* __RT_ATE_H__ */ + diff --git a/mt7620/src/ate/include/rt_qa.h b/mt7620/src/ate/include/rt_qa.h new file mode 100644 index 0000000..412cd4a --- /dev/null +++ b/mt7620/src/ate/include/rt_qa.h @@ -0,0 +1,210 @@ +/* + *************************************************************************** + * 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_qa.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ + +#ifndef __RT_QA_H__ +#define __RT_QA_H__ + +#ifdef RALINK_QA +#ifndef RALINK_ATE +#error "For supporting QA GUI, please set HAS_ATE=y and HAS_QA_SUPPORT=y." +#endif /* RALINK_ATE */ + +#include "rt_ate.h" + +typedef struct ate_racfghdr { + UINT32 magic_no; + USHORT command_type; + USHORT command_id; + USHORT length; + USHORT sequence; + USHORT status; + UCHAR data[2046]; +} __attribute__((packed))RACFGHDR, *pRACFGHDR; + +/* Stop Transmission */ +#define ATE_TXSTOP ((~(fATE_TX_ENABLE))&(~(fATE_TXCONT_ENABLE))&(~(fATE_TXCARR_ENABLE))&(~(fATE_TXCARRSUPP_ENABLE))) +/* Stop Receiving Frames */ +#define ATE_RXSTOP (~(fATE_RX_ENABLE)) + +/* NOTE : may be different with chipset in the future ++ */ +#define BBP22_TXFRAME 0x00 /* Transmit Frames */ +#define BBP22_TXCONT_OR_CARRSUPP 0x80 /* Continuous Transmit or Carrier Suppression */ +#define BBP22_TXCARR 0xc1 /* Transmit Carrier */ +#define BBP24_TXCONT 0x00 /* Continuous Transmit */ +#define BBP24_CARRSUPP 0x01 /* Carrier Suppression */ +/* NOTE : may be different with chipset in the future -- */ + +/* Eth QA RACFG Command */ +#define RACFG_MAGIC_NO 0x18142880 +/* command id with Cmd Type == 0x0005(for iNIC)/0x0008(for others) */ +#define RACFG_CMD_RF_WRITE_ALL 0x0000 +#define RACFG_CMD_E2PROM_READ16 0x0001 +#define RACFG_CMD_E2PROM_WRITE16 0x0002 +#define RACFG_CMD_E2PROM_READ_ALL 0x0003 +#define RACFG_CMD_E2PROM_WRITE_ALL 0x0004 +#define RACFG_CMD_IO_READ 0x0005 +#define RACFG_CMD_IO_WRITE 0x0006 +#define RACFG_CMD_IO_READ_BULK 0x0007 +#define RACFG_CMD_BBP_READ8 0x0008 +#define RACFG_CMD_BBP_WRITE8 0x0009 +#define RACFG_CMD_BBP_READ_ALL 0x000a +#define RACFG_CMD_GET_COUNTER 0x000b +#define RACFG_CMD_CLEAR_COUNTER 0x000c + +#define RACFG_CMD_RSV1 0x000d +#define RACFG_CMD_RSV2 0x000e +#define RACFG_CMD_RSV3 0x000f + +#define RACFG_CMD_TX_START 0x0010 +#define RACFG_CMD_GET_TX_STATUS 0x0011 +#define RACFG_CMD_TX_STOP 0x0012 +#define RACFG_CMD_RX_START 0x0013 +#define RACFG_CMD_RX_STOP 0x0014 +#define RACFG_CMD_GET_NOISE_LEVEL 0x0015 +#if defined(RT2883) || defined(RT3883) +#define RACFG_CMD_QUERY_BF_RSP 0x0016 +#define RACFG_CMD_QUERY_IBF_TAG 0x0017 +#define RACFG_CMD_QUERY_EBF_TAG 0x0018 +#define RACFG_CMD_QUERY_IBF_PROFILE 0x0019 +#define RACFG_CMD_QUERY_EBF_PROFILE 0x001a +#define RACFG_CMD_WRITE_IBF_TAG 0x001b +#define RACFG_CMD_WRITE_EBF_TAG 0x001c +#define RACFG_CMD_WRITE_IBF_PROFILE 0x001d +#define RACFG_CMD_WRITE_EBF_PROFILE 0x001e +#define RACFG_CMD_CALIBRATION_CAPTURE 0x0020 +#endif /* defined(RT2883) || defined(RT3883) */ + +#define RACFG_CMD_ATE_START 0x0080 +#define RACFG_CMD_ATE_STOP 0x0081 + +#define RACFG_CMD_ATE_START_TX_CARRIER 0x0100 +#define RACFG_CMD_ATE_START_TX_CONT 0x0101 +#define RACFG_CMD_ATE_START_TX_FRAME 0x0102 +#define RACFG_CMD_ATE_SET_BW 0x0103 +#define RACFG_CMD_ATE_SET_TX_POWER0 0x0104 +#define RACFG_CMD_ATE_SET_TX_POWER1 0x0105 +#define RACFG_CMD_ATE_SET_FREQ_OFFSET 0x0106 +#define RACFG_CMD_ATE_GET_STATISTICS 0x0107 +#define RACFG_CMD_ATE_RESET_COUNTER 0x0108 +#define RACFG_CMD_ATE_SEL_TX_ANTENNA 0x0109 +#define RACFG_CMD_ATE_SEL_RX_ANTENNA 0x010a +#define RACFG_CMD_ATE_SET_PREAMBLE 0x010b +#define RACFG_CMD_ATE_SET_CHANNEL 0x010c +#define RACFG_CMD_ATE_SET_ADDR1 0x010d +#define RACFG_CMD_ATE_SET_ADDR2 0x010e +#define RACFG_CMD_ATE_SET_ADDR3 0x010f +#define RACFG_CMD_ATE_SET_RATE 0x0110 +#define RACFG_CMD_ATE_SET_TX_FRAME_LEN 0x0111 +#define RACFG_CMD_ATE_SET_TX_FRAME_COUNT 0x0112 +#define RACFG_CMD_ATE_START_RX_FRAME 0x0113 +#define RACFG_CMD_ATE_E2PROM_READ_BULK 0x0114 +#define RACFG_CMD_ATE_E2PROM_WRITE_BULK 0x0115 +#define RACFG_CMD_ATE_IO_WRITE_BULK 0x0116 +#define RACFG_CMD_ATE_BBP_READ_BULK 0x0117 +#define RACFG_CMD_ATE_BBP_WRITE_BULK 0x0118 +#ifndef RF_BANK +#define RACFG_CMD_ATE_RF_READ_BULK 0x0119 +#define RACFG_CMD_ATE_RF_WRITE_BULK 0x011a +#endif /* RF_BANK */ +#define RACFG_CMD_ATE_SET_TX_POWER2 0x011b +#ifdef TXBF_SUPPORT +#define RACFG_CMD_ATE_TXBF_DUT_INIT 0x011c +#define RACFG_CMD_ATE_TXBF_LNA_CAL 0x011d +#define RACFG_CMD_ATE_TXBF_DIV_CAL 0x011e +#define RACFG_CMD_ATE_TXBF_PHASE_CAL 0x011f +#define RACFG_CMD_ATE_TXBF_GOLDEN_INIT 0x0120 +#define RACFG_CMD_ATE_TXBF_VERIFY 0x0121 +#endif /* TXBF_SUPPORT */ +#ifdef RF_BANK +#define RACFG_CMD_ATE_RF_READ_BULK_BANK 0x0123 +#define RACFG_CMD_ATE_RF_WRITE_BULK_BANK 0x0124 +#endif /* RF_BANK */ + +#ifdef RT3883 +#define RACFG_CMD_ATE_ETH_EXT_SETTING 0x0200 +#endif /* RT3883 */ +#if defined (RT3883) || defined (RT3352) || defined (RT5350) +#define RACFG_CMD_ATE_RUN_CPUBUSY 0x0202 +#endif /* defined (RT3883) || defined (RT3352) || defined (RT5350) */ +#ifdef RT6352 +#define RACFG_CMD_ATE_CALIBRATION 0x0204 +#define RACFG_CMD_ATE_TSSI_COMPENSATION 0x0205 +#define RACFG_CMD_ATE_TEMP_COMPENSATION 0x0206 +#endif /* RT6352 */ + +/* QA RACFG Command for ate test from localhost */ +#define RACFG_CMD_ATE_SHOW_PARAM 0xff00 + +/* ATE export paramters to uppler layer */ +typedef struct __ATE_EX_PARAM +{ + unsigned char mode; + char TxPower0; + char TxPower1; +#ifdef DOT11N_SS3_SUPPORT + char TxPower2; +#endif /* DOT11N_SS3_SUPPORT */ + char TxAntennaSel; + char RxAntennaSel; + unsigned char DA[MAC_ADDR_LEN]; + unsigned char SA[MAC_ADDR_LEN]; + unsigned char BSSID[MAC_ADDR_LEN]; + unsigned char MCS; + unsigned char PhyMode; + BOOLEAN ShortGI; + BOOLEAN BW; + unsigned int Channel; + unsigned int TxLength; + unsigned int TxCount; + unsigned int RFFreqOffset; + unsigned int IPG; + unsigned int RxTotalCnt; + unsigned int RxCntPerSec; + char LastSNR0; + char LastSNR1; + char LastSNR2; + char LastRssi0; + char LastRssi1; + char LastRssi2; + char AvgRssi0; + char AvgRssi1; + char AvgRssi2; + short AvgRssi0X8; + short AvgRssi1X8; + short AvgRssi2X8; +}ATE_EX_PARAM, *pATE_EX_PARAM; + +NDIS_STATUS TXSTOP( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS RXSTOP( + IN PRTMP_ADAPTER pAd); + +#endif /* RALINK_QA */ + +#endif /* __RT_QA_H__ */ diff --git a/mt7620/src/ate_iwpriv_usage.txt b/mt7620/src/ate_iwpriv_usage.txt new file mode 100755 index 0000000..dcbc1bb --- /dev/null +++ b/mt7620/src/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=-89¡K + ¡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/mt7620/src/brftph_usage.txt b/mt7620/src/brftph_usage.txt new file mode 100755 index 0000000..b446c86 --- /dev/null +++ b/mt7620/src/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/mt7620/src/chips/rt2880.c b/mt7620/src/chips/rt2880.c new file mode 100644 index 0000000..5d0440d --- /dev/null +++ b/mt7620/src/chips/rt2880.c @@ -0,0 +1,86 @@ +/* + *************************************************************************** + * 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: + rt2880.c + + Abstract: + Specific funcitons and variables for RT2880 + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#include "rt_config.h" + +#ifdef RT2880 + +/* Default EEPROM value for RT2880 */ +UCHAR RT2880_EeBuffer[EEPROM_SIZE] = { + 0x80,0x28,0x03,0x01,0x00,0x0C,0x43,0x28,0x60,0x20,0x01,0x08,0x14,0x18,0x01,0x80, + 0x00,0x00,0x80,0x28,0x14,0x18,0x00,0x00,0x01,0x00,0x6A,0xFF,0x0C,0x00,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0x23,0x02,0x2C,0x00,0xFF,0xFF,0x1D,0x00,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0x0A,0x10,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x08,0xFF,0xFF, + 0xFF,0xFF,0x0F,0x0F,0x0F,0x0F,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E, + 0x13,0x13,0x12,0x12,0x11,0x11,0x10,0x10,0x10,0x10,0x0F,0x0F,0x0F,0x0F,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06, + + 0x06,0x06,0x06,0x06,0x04,0x04,0x04,0x04,0x04,0x04,0x05,0x05,0x05,0x05,0x05,0x05, + 0x05,0x05,0x06,0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x05,0x05,0x05,0x05,0x05,0x05,0x06,0x06,0x06,0x04, + 0x05,0x05,0x05,0x05,0x05,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06, + 0x06,0x06,0x06,0x06,0x07,0x07,0x08,0x09,0x09,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x66,0x66, + 0xCC,0xAA,0x88,0x66,0xCC,0xAA,0x88,0x66,0xCC,0xAA,0x88,0x66,0xCC,0xAA,0x88,0x66, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + }; + + +VOID RT2880_Init( + IN PRTMP_ADAPTER pAd) +{ + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + + pChipCap->MaxNumOfBbpId = 185; +#ifdef RTMP_FLASH_SUPPORT + pChipCap->eebuf = RT2880_EeBuffer; +#endif /* RTMP_FLASH_SUPPORT */ +} + +#endif /* RT2880*/ + diff --git a/mt7620/src/chips/rt2883.c b/mt7620/src/chips/rt2883.c new file mode 100644 index 0000000..5afffb3 --- /dev/null +++ b/mt7620/src/chips/rt2883.c @@ -0,0 +1,547 @@ +/* + *************************************************************************** + * 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: + rt2883.c + + Abstract: + Specific funcitons and variables for RT2883 + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#include "rt_config.h" + + +#ifdef RT2883 +REG_PAIR RT2883_BBPRegTable[] = +{ + {BBP_R4, 0x50}, /* 2883 need to */ + {BBP_R65, 0x6C}, /* fix rssi issue and add Fine AGC */ + {BBP_R103, 0xC0}, + {BBP_R105, 0x04 /*0xbc ?*/}, /* RT2883 default is 0x4. Initialized R105 to enable saving of Explicit and Implicit profiles */ + {BBP_R137, 0x0F}, /* julian suggest make the RF output more stable */ + {BBP_R179, 0x02}, /* Set ITxBF timeout to 0x9C40=1000msec*/ + {BBP_R180, 0x01}, + {BBP_R182, 0x9C}, +}; + + +UCHAR RT2883_EeBuffer[EEPROM_SIZE] = { + 0x83, 0x28, 0x01, 0x00, 0x00, 0x0c, 0x43, 0x28, 0x83, 0x00, 0x83, 0x28, 0x14, 0x18, 0xff, 0xff, + 0xff, 0xff, 0x83, 0x28, 0x14, 0x18, 0x00, 0x00, 0x01, 0x00, 0x6a, 0xff, 0x00, 0x02, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0c, 0x43, 0x28, 0x83, 0x01, 0x00, 0x0c, + 0x43, 0x28, 0x83, 0x02, 0x33, 0x0a, 0xec, 0x00, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x20, 0x01, 0x55, 0x77, 0xa8, 0xaa, 0x8c, 0x88, 0xff, 0xff, 0x0a, 0x08, 0x08, 0x06, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x66, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, + 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xaa, 0xaa, 0x88, 0x66, 0xaa, 0xaa, + 0x88, 0x66, 0xaa, 0xaa, 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, + 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xaa, 0xaa, 0x88, 0x66, 0xaa, 0xaa, 0x88, 0x66, 0xaa, 0xaa, + 0x88, 0x66, 0xaa, 0xaa, 0x88, 0x66, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + } ; + +UCHAR RT2883_NUM_BBP_REG_PARMS = (sizeof(RT2883_BBPRegTable) / sizeof(REG_PAIR)); + +RTMP_REG_PAIR RT2883_MACRegTable[] = { + {TX_SW_CFG0, 0x0}, /* Gary,2008-12-15 for Intel 5300 (FIXME)*/ + {TX_SW_CFG1, 0x0}, /* Gary,2008-12-15 for Intel 5300 (FIXME)*/ + {TX_SW_CFG2, 0x40000}, /* Gary,2008-12-15 for Intel 5300 (FIXME)*/ + {TX_TXBF_CFG_0, 0x8000FC21}, /* Force MCS0 for sounding response*/ + {TX_TXBF_CFG_3, 0x00009c40}, /* ETxBF Timeout = 1 sec = 0x9c40*(25 usec)*/ + {TX_FBK_CFG_3S_0, 0x12111008}, /* default value*/ +}; + +UCHAR RT2883_NUM_MAC_REG_PARMS = (sizeof(RT2883_MACRegTable) / sizeof(RTMP_REG_PAIR)); + +#ifdef CONFIG_AP_SUPPORT +RTMP_REG_PAIR RT2883_AP_MACRegTable[] = { + {TX_CHAIN_ADDR0_L, 0xFFFFFFFF}, /* Broadcast frames are in stream mode*/ + {TX_CHAIN_ADDR0_H, 0xFFFFF}, +}; + +UCHAR RT2883_NUM_AP_MAC_REG_PARMS = (sizeof(RT2883_AP_MACRegTable) / sizeof(RTMP_REG_PAIR)); +#endif /* CONFIG_AP_SUPPORT */ + +/* +======================================================================== +Routine Description: + Initialize specific MAC registers. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID NICInitRT2883MacRegisters( + IN PRTMP_ADAPTER pAd) +{ + UINT32 IdReg; + + + for (IdReg = 0; IdReg < RT2883_NUM_MAC_REG_PARMS; IdReg++) + { + /* if we want to change the full regiter content */ + RTMP_IO_WRITE32(pAd, (USHORT)RT2883_MACRegTable[IdReg].Register, + RT2883_MACRegTable[IdReg].Value); + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + for (IdReg = 0; IdReg < RT2883_NUM_AP_MAC_REG_PARMS; IdReg++) + { + RTMP_IO_WRITE32(pAd, (USHORT)RT2883_AP_MACRegTable[IdReg].Register, + RT2883_AP_MACRegTable[IdReg].Value); + } + } +#endif /* CONFIG_AP_SUPPORT */ + +} + + +/* +======================================================================== +Routine Description: + Initialize specific BBP registers. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID NICInitRT2883BbpRegisters( + IN PRTMP_ADAPTER pAd) +{ + UINT32 IdReg; + + DBGPRINT(RT_DEBUG_TRACE, ("%s --->\n", __FUNCTION__)); + + for (IdReg = 0; IdReg < RT2883_NUM_BBP_REG_PARMS; IdReg++) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, RT2883_BBPRegTable[IdReg].Register, + RT2883_BBPRegTable[IdReg].Value); + DBGPRINT(RT_DEBUG_TRACE, ("BBP_R%d=%d\n", RT2883_BBPRegTable[IdReg].Register, + RT2883_BBPRegTable[IdReg].Value)); + } + + /* Set ITxBF timeout to 0x9C40=1000msec*/ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R179, 0x02); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R180, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R182, 0x40); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R180, 0x01); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R182, 0x9C); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R179, 0x00); + + DBGPRINT(RT_DEBUG_TRACE, ("%s <---\n", __FUNCTION__)); + +} + + +/* + ======================================================================== + + 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 RTMPRT2883ReadTxPwrPerRate( + IN PRTMP_ADAPTER pAd) +{ + /*ULONG data; */ + USHORT /*i,*/ value, value2; + + DBGPRINT(RT_DEBUG_TRACE, ("Txpower per Rate\n")); + + + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_CCK_OFDM, value); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_CCK_OFDM + 2, value2); + pAd->Tx20MPwrCfgGBand[0] = (value2 << 16) | value; + pAd->Tx40MPwrCfgGBand[0] = pAd->Tx20MPwrCfgGBand[0]; + pAd->Tx20MPwrCfgABand[0] = pAd->Tx20MPwrCfgGBand[0]; + pAd->Tx40MPwrCfgABand[0] = pAd->Tx20MPwrCfgGBand[0]; + + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_CCK_OFDM + 4, value); + pAd->Tx20MPwrCfgGBand[1] = value; + pAd->Tx40MPwrCfgGBand[1] = value; + pAd->Tx20MPwrCfgABand[1] = value; + pAd->Tx40MPwrCfgABand[1] = value; + + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G, value); + pAd->Tx20MPwrCfgGBand[1] |= (value << 16); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 2.4G band-%lx \n", pAd->Tx20MPwrCfgGBand[1])); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G, value); + pAd->Tx40MPwrCfgGBand[1] |= (value << 16); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("40MHz BW, 2.4G band-%lx \n", pAd->Tx40MPwrCfgGBand[1])); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G, value); + pAd->Tx20MPwrCfgABand[1] |= (value << 16); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 5GHz band-%lx \n", pAd->Tx20MPwrCfgABand[1])); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G, value); + pAd->Tx40MPwrCfgABand[1] |= (value << 16); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("40MHz BW, 5GHz band-%lx \n", pAd->Tx40MPwrCfgABand[1])); + + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + 2, value); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + 4, value2); + pAd->Tx20MPwrCfgGBand[2] = (value2 << 16) | value; + DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 2.4G band-%lx \n", pAd->Tx20MPwrCfgGBand[2])); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 2, value); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 4, value2); + pAd->Tx40MPwrCfgGBand[2] = (value2 << 16) | value; + DBGPRINT_RAW(RT_DEBUG_TRACE, ("40MHz BW, 2.4G band-%lx \n", pAd->Tx40MPwrCfgGBand[2])); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 2, value); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 4, value2); + pAd->Tx20MPwrCfgABand[2] = (value2 << 16) | value; + DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 5GHz band-%lx \n", pAd->Tx20MPwrCfgABand[2])); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 2, value); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 4, value2); + pAd->Tx40MPwrCfgABand[2] = (value2 << 16) | value; + DBGPRINT_RAW(RT_DEBUG_TRACE, ("40MHz BW, 5GHz band-%lx \n", pAd->Tx40MPwrCfgABand[2])); + + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + 6, value); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + 12, value2); + pAd->Tx20MPwrCfgGBand[3] = (value2 << 16) | value; + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 6, value); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 12, value2); + pAd->Tx40MPwrCfgGBand[3] = (value2 << 16) | value; + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 6, value); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 12, value2); + pAd->Tx20MPwrCfgABand[3] = (value2 << 16) | value; + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 6, value); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 12, value2); + pAd->Tx40MPwrCfgABand[3] = (value2 << 16) | value; + + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + 14, value); + pAd->Tx20MPwrCfgGBand[4] = value; + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 14, value); + pAd->Tx40MPwrCfgGBand[4] = value; + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 14, value); + pAd->Tx20MPwrCfgABand[4] = value; + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 14, value); + pAd->Tx40MPwrCfgABand[4] = value; + + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + 8, value); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + 10, value2); + pAd->Tx20MPwrCfgGBand[5] = (value & 0xff) | ((value & 0xf0) << 4) | ((value & 0xff00) << 8) | ((value & 0xf000) << 12); + pAd->Tx20MPwrCfgGBand[6] = (value2 & 0xff) | ((value2 & 0xf0) << 4) | ((value2 & 0xff00) << 8) | ((value2 & 0xf000) << 12); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 8, value); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 10, value2); + pAd->Tx40MPwrCfgGBand[5] = (value & 0xff) | ((value & 0xf0) << 4) | ((value & 0xff00) << 8) | ((value & 0xf000) << 12); + pAd->Tx40MPwrCfgGBand[6] = (value2 & 0xff) | ((value2 & 0xf0) << 4) | ((value2 & 0xff00) << 8) | ((value2 & 0xf000) << 12); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 8, value); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 10, value2); + pAd->Tx20MPwrCfgABand[5] = (value & 0xff) | ((value & 0xf0) << 4) | ((value & 0xff00) << 8) | ((value & 0xf000) << 12); + pAd->Tx20MPwrCfgABand[6] = (value2 & 0xff) | ((value2 & 0xf0) << 4) | ((value2 & 0xff00) << 8) | ((value2 & 0xf000) << 12); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 8, value); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 10, value2); + pAd->Tx40MPwrCfgABand[5] = (value & 0xff) | ((value & 0xf0) << 4) | ((value & 0xff00) << 8) | ((value & 0xf000) << 12); + pAd->Tx40MPwrCfgABand[6] = (value2 & 0xff) | ((value2 & 0xf0) << 4) | ((value2 & 0xff00) << 8) | ((value2 & 0xf000) << 12); + + + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0, pAd->Tx20MPwrCfgGBand[0]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_1, pAd->Tx20MPwrCfgGBand[1]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_2, pAd->Tx20MPwrCfgGBand[2]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_3, pAd->Tx20MPwrCfgGBand[3]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_4, pAd->Tx20MPwrCfgGBand[4]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_5, pAd->Tx20MPwrCfgGBand[5]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_6, pAd->Tx20MPwrCfgGBand[6]); + + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0_EXT, (pAd->Tx20MPwrCfgGBand[0] & 0xf0f0f0f0) >> 4); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_1_EXT, (pAd->Tx20MPwrCfgGBand[1] & 0xf0f0f0f0) >> 4); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_2_EXT, (pAd->Tx20MPwrCfgGBand[2] & 0xf0f0f0f0) >> 4); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_3_EXT, (pAd->Tx20MPwrCfgGBand[3] & 0xf0f0f0f0) >> 4); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_4_EXT, (pAd->Tx20MPwrCfgGBand[4] & 0xf0f0f0f0) >> 4); +} + +/* + ======================================================================== + + Routine Description: + Read initial channel power parameters from EEPROM + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPRT2883ReadChannelPwr( + IN PRTMP_ADAPTER pAd) +{ + UCHAR i, choffset; + EEPROM_TX_PWR_STRUC Power; + EEPROM_TX_PWR_STRUC Power2; + EEPROM_TX_PWR_STRUC Power3; + + /* + 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++) + { + 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); + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX3_PWR_OFFSET + i * 2, Power3.word); + pAd->TxPower[i * 2].Channel = i * 2 + 1; + pAd->TxPower[i * 2 + 1].Channel = i * 2 + 2; + + if ((Power.field.Byte0 > 31) || (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 > 31) || (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 ((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 ((Power3.field.Byte0 > 31) || (Power3.field.Byte0 < 0)) + pAd->TxPower[i * 2].Power3 = DEFAULT_RF_TX_POWER; + else + pAd->TxPower[i * 2].Power3 = Power3.field.Byte0; + + if ((Power3.field.Byte1 > 31) || (Power3.field.Byte1 < 0)) + pAd->TxPower[i * 2 + 1].Power3 = DEFAULT_RF_TX_POWER; + else + pAd->TxPower[i * 2 + 1].Power3 = Power3.field.Byte1; + } + + /* 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 + 0].Power3 = 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 + 1].Power3 = 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; + pAd->TxPower[3 * i + choffset + 2].Power3 = 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); */ + 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); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX3_PWR_OFFSET + i * 2, Power3.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; + + if ((Power3.field.Byte0 < 16) && (Power3.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power3 = Power3.field.Byte0; + + if ((Power3.field.Byte1 < 16) && (Power3.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power3 = Power3.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 + 0].Power3 = 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 + 1].Power3 = 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 * i + choffset + 2].Power3 = 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; + pAd->TxPower[3 * 5 + choffset + 0].Power3 = 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); */ + 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); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX3_PWR_OFFSET + (choffset - 14) + i * 2, Power3.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; + + if ((Power3.field.Byte0 < 16) && (Power3.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power3 = Power3.field.Byte0; + + if ((Power3.field.Byte1 < 16) && (Power3.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power3 = Power3.field.Byte1; + } + + /* 3. U-NII upper band: 149, 151, 153; 157, 159, 161; 165 (including central frequency in BW 40MHz) */ + /* 3.1 Fill up channel */ + choffset = 14 + 12 + 16; + for (i = 0; i < 2; 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 + 0].Power3 = 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 + 1].Power3 = 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 * i + choffset + 2].Power3 = DEFAULT_RF_TX_POWER; + } + pAd->TxPower[3 * 2 + choffset + 0].Channel = 165; + pAd->TxPower[3 * 2 + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * 2 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * 2 + choffset + 0].Power3 = DEFAULT_RF_TX_POWER; + + /* 3.2 Fill up power */ + for (i = 0; i < 4; 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); */ + 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); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX3_PWR_OFFSET + (choffset - 14) + i * 2, Power3.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; + + if ((Power3.field.Byte0 < 16) && (Power3.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power3 = Power3.field.Byte0; + + if ((Power3.field.Byte1 < 16) && (Power3.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power3 = Power3.field.Byte1; + } + + /* 4. Print and Debug */ + choffset = 14 + 12 + 16 + 7; + +} + + +#endif /* RT2883 */ + diff --git a/mt7620/src/chips/rt28xx.c b/mt7620/src/chips/rt28xx.c new file mode 100644 index 0000000..cd58706 --- /dev/null +++ b/mt7620/src/chips/rt28xx.c @@ -0,0 +1,317 @@ +/* + *************************************************************************** + * 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: + rt2860.c + + Abstract: + Specific funcitons and variables for RT3070 + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifdef RT28xx + +#include "rt_config.h" + +VOID RT28xx_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; + ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0; + RTMP_RF_REGS *RFRegTable; + + i = i; /* avoid compile warning */ + RFValue = 0; + + /* Search Tx power value*/ + /* + 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, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel)); + } + + RFRegTable = RF2850RegTable; + + switch (pAd->RfIcType) + { + case RFIC_2820: + case RFIC_2850: + case RFIC_2720: + case RFIC_2750: + for (index = 0; index < NUM_OF_2850_CHNL; index++) + { + if (Channel == RFRegTable[index].Channel) + { + R2 = RFRegTable[index].R2; + if (pAd->Antenna.field.TxPath == 1) + { + R2 |= 0x4000; /*If TXpath is 1, bit 14 = 1;*/ + } + + if ((pAd->Antenna.field.RxPath == 2) +#ifdef GREENAP_SUPPORT + && (pAd->ApCfg.bGreenAPActive == FALSE) +#endif /* GREENAP_SUPPORT */ + ) + { + R2 |= 0x40; /*write 1 to off Rxpath.*/ + } + else if ((pAd->Antenna.field.RxPath == 1) +#ifdef GREENAP_SUPPORT + || (pAd->ApCfg.bGreenAPActive == TRUE) +#endif /* GREENAP_SUPPORT */ + ) + { + R2 |= 0x20040; /*write 1 to off RxPath*/ + } + + if (Channel > 14) + { + /* initialize R3, R4*/ + R3 = (RFRegTable[index].R3 & 0xffffc1ff); + R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15); + + /* 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB*/ + /*R3*/ + if ((TxPwer >= -7) && (TxPwer < 0)) + { + TxPwer = (7+TxPwer); + + /* TxPwer is not possible larger than 15 */ + + R3 |= (TxPwer << 10); + DBGPRINT(RT_DEBUG_TRACE, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer)); + } + else + { + TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); + R3 |= (TxPwer << 10) | (1 << 9); + } + + /* R4*/ + if ((TxPwer2 >= -7) && (TxPwer2 < 0)) + { + TxPwer2 = (7+TxPwer2); + + R4 |= (TxPwer2 << 7); + DBGPRINT(RT_DEBUG_TRACE, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2)); + } + else + { + TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); + R4 |= (TxPwer2 << 7) | (1 << 6); + } + } + else + { + R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); /* set TX power0*/ + R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);/* Set freq Offset & TxPwr1*/ + } + + /* Based on BBP current mode before changing RF channel.*/ + if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40) +#ifdef GREENAP_SUPPORT + && (pAd->ApCfg.bGreenAPActive == 0) +#endif /* GREENAP_SUPPORT */ + ) + { + R4 |=0x200000; + } + + /* Update variables*/ + pAd->LatchRfRegs.Channel = Channel; + pAd->LatchRfRegs.R1 = RFRegTable[index].R1; + pAd->LatchRfRegs.R2 = R2; + pAd->LatchRfRegs.R3 = R3; + pAd->LatchRfRegs.R4 = R4; + + /* Set RF value 1's set R3[bit2] = [0]*/ + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + RTMPusecDelay(200); + + /* Set RF value 2's set R3[bit2] = [1]*/ + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04)); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + RTMPusecDelay(200); + + /* Set RF value 3's set R3[bit2] = [0]*/ + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + break; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%lu, Pwr1=%lu, %dT) to , R1=0x%08x, R2=0x%08x, R3=0x%08x, R4=0x%08x\n", + Channel, + pAd->RfIcType, + (R3 & 0x00003e00) >> 9, + (R4 & 0x000007c0) >> 6, + pAd->Antenna.field.TxPath, + pAd->LatchRfRegs.R1, + pAd->LatchRfRegs.R2, + pAd->LatchRfRegs.R3, + pAd->LatchRfRegs.R4)); + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d : unknown RFIC=%d\n", Channel, pAd->RfIcType)); + break; + } + + /* Change BBP setting during siwtch from a->g, g->a*/ + if (Channel <= 14) + { + ULONG TxPinCfg = 0x00050F0A;/*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))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);/*(0x44 - GET_LNA_GAIN(pAd))); According the Rory's suggestion to solve the middle range issue.*/ + + /* Rx High power VGA offset for LNA select*/ + { + if (pAd->NicConfig2.field.ExternalLNAForG) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + } + + /* 5G band selection PIN, bit1 and bit2 are complement*/ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x04); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + /* 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); + + RtmpUpdateFilterCoefficientControl(pAd, Channel); + } + else + { + ULONG TxPinCfg = 0x00050F05;/*Gary 2007/8/9 0x050505*/ + UINT8 bbpValue; + + 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))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);/*(0x44 - GET_LNA_GAIN(pAd))); According the Rory's suggestion to solve the middle range issue. */ + + /* Set the BBP_R82 value here */ + bbpValue = 0xF2; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, bbpValue); + + + /* Rx High power VGA offset for LNA select*/ + if (pAd->NicConfig2.field.ExternalLNAForA) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + /* 5G band selection PIN, bit1 and bit2 are complement*/ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x02); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + /* Turn off unused PA or LNA when only 1T or 1R*/ + { + /* 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); + } + + /* R66 should be set according to Channel and use 20MHz when scanning*/ + + 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 + 005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL. + + */ + RTMPusecDelay(1000); +} + +#endif /*RT28xx */ + diff --git a/mt7620/src/chips/rt305x.c b/mt7620/src/chips/rt305x.c new file mode 100644 index 0000000..dbed250 --- /dev/null +++ b/mt7620/src/chips/rt305x.c @@ -0,0 +1,1603 @@ +/* + *************************************************************************** + * 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: + rt305x.c + + Abstract: + Specific funcitons and variables for RT305x(i.e., RT3050/RT3051/RT3052) + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#ifdef RT305x + +#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 // + +/* Default EEPROM value for RT3050 */ +UCHAR RT3050_EeBuffer[EEPROM_SIZE] = { + 0x50, 0x30, 0x01, 0x01, 0x00, 0x0c, 0x43, 0x30, 0x52, 0x88, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 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, 0x30, 0x52, 0x77, 0x00, 0x0c, 0x43, 0x30, 0x52, 0x66, 0x11, 0x05, 0x20, 0x00, + 0xff, 0xff, 0x2f, 0x01, 0x55, 0x77, 0xa8, 0xaa, 0x8c, 0x88, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x10, 0x10, + 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x14, 0x14, 0x14, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x66, 0x66, + 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, + 0x88, 0x66, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; + +/* Default EEPROM value for RT3052 */ +UCHAR RT3052_EeBuffer[EEPROM_SIZE] = { + 0x52, 0x30, 0x01, 0x01, 0x00, 0x0c, 0x43, 0x30, 0x52, 0x88, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 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, 0x30, 0x52, 0x77, 0x00, 0x0c, 0x43, 0x30, 0x52, 0x66, 0x22, 0x08, 0x24, 0x00, + 0xff, 0xff, 0x2f, 0x01, 0x55, 0x77, 0xa8, 0xaa, 0x8c, 0x88, 0xff, 0xff, 0x0c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x10, 0x10, + 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x14, 0x14, 0x14, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x66, 0x66, + 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, + 0x88, 0x66, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; + +REG_PAIR RT305x_BBPRegTable[] = { + {BBP_R31, 0x08}, //gary recommend for ACE + {BBP_R78, 0x0E}, + {BBP_R80, 0x08}, // requested by Gary for high power + {BBP_R103, 0xC0}, +}; + + +UCHAR RT305x_NUM_BBP_REG_PARMS = (sizeof(RT305x_BBPRegTable) / sizeof(REG_PAIR)); + + +#ifdef RT3350 +// +// RF register initialization set +// +REG_PAIR RT3350_RFRegTable[] = { + {RF_R00, 0xA1}, + {RF_R01, 0xC1}, + {RF_R02, 0xF1}, + {RF_R03, 0x72}, + {RF_R04, 0x40}, + {RF_R05, 0xCF}, + {RF_R06, 0x7E}, + {RF_R07, 0xD0}, + {RF_R08, 0x53}, + {RF_R09, 0x01}, + {RF_R10, 0x10}, + {RF_R11, 0x21}, + {RF_R12, 0x26},// QA : 0x2D(TX0_ALC) + {RF_R13, 0xB0}, + {RF_R14, 0x00}, + {RF_R15, 0x78}, + {RF_R16, 0x44}, + {RF_R17, 0x92}, + {RF_R18, 0x6C}, + {RF_R19, 0xCC}, + {RF_R20, 0xBB}, + {RF_R21, 0x6F}, + {RF_R22, 0x00}, + {RF_R23, 0x12}, + {RF_R24, 0x08}, + {RF_R25, 0x3F}, + {RF_R26, 0x0D}, + {RF_R27, 0x75}, + {RF_R28, 0x10}, + {RF_R29, 0x07}, + {RF_R30, 0x00}, + {RF_R31, 0x08}, +}; +#endif // RT3350 // + +// +// RF register initialization set +// +REG_PAIR RT305x_RFRegTable[] = { + {RF_R00, 0x50}, // + {RF_R01, 0x01}, // + {RF_R02, 0xF7}, // + {RF_R03, 0x75}, //0x02}, // + {RF_R04, 0x40}, + {RF_R05, 0x03}, //0x00}, + {RF_R06, 0x42}, //pass the crystal auto-tuned + {RF_R07, 0x50}, // + {RF_R08, 0x39}, // + {RF_R09, 0x0F}, //0x04}, + {RF_R10, 0x60}, //0x71}, //0x72}, + {RF_R11, 0x21}, //0x11}, + {RF_R12, 0x75}, //0x7B} + {RF_R13, 0x75}, // + {RF_R14, 0x90}, //0xC0}, + {RF_R15, 0x58}, //0x78}, + {RF_R16, 0xB3}, //0xB2}, + {RF_R17, 0x92}, //Mason Hsu 20080624 + {RF_R18, 0x2C}, + {RF_R19, 0x02}, + {RF_R20, 0xBA}, + {RF_R21, 0xDB}, + {RF_R22, 0x00}, // + {RF_R23, 0x31}, // + {RF_R24, 0x08}, // + {RF_R25, 0x01}, + {RF_R26, 0x25}, //Core Power: 0x25=1.25v + {RF_R27, 0x23}, //RF: 1.35v (Mason Hsu 20081023) + {RF_R28, 0x13}, //ADC: must consist with R27 + {RF_R29, 0x83}, //0x18}, + {RF_R30, 0x00}, // + {RF_R31, 0x00}, // +}; + +UCHAR RT305x_NUM_RF_REG_PARMS = (sizeof(RT305x_RFRegTable) / sizeof(REG_PAIR)); + +RTMP_REG_PAIR RT305x_MACRegTable[] = { + {TX_SW_CFG0, 0x400}, // Gary,2008-05-21 0x0 for CWC test , 2008-06-19 0x400 for rf reason + {TX_SW_CFG1, 0x0}, // Gary,2008-06-18 + {TX_SW_CFG2, 0x30}, // Bruce, CwC IOT issue +}; + +UCHAR RT305x_NUM_MAC_REG_PARMS = (sizeof(RT305x_MACRegTable) / sizeof(RTMP_REG_PAIR)); + +#ifdef RTMP_INTERNAL_TX_ALC +/* The Tx power tuning entry */ +TX_POWER_TUNING_ENTRY_STRUCT RT3350_TxPowerTuningTable[] = +{ +/* 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}, +}; + +/* 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[8] = {0}; + +/* The desired TSSI over HT using STBC */ +CHAR desiredTSSIOverHTUsingSTBC[8] = {0}; +#endif /* RTMP_INTERNAL_TX_ALC */ + +static VOID NICInitRT305xRF_R27_R28(IN PRTMP_ADAPTER pAd) +{ + if ((pAd->CommonCfg.CN >> 16) == 0x3033) + { + if (pAd->CommonCfg.CID < 0x103) + { + RT30xxWriteRFRegister(pAd, RF_R27, 0x23); + RT30xxWriteRFRegister(pAd, RF_R28, 0x13); + } + else + { + RT30xxWriteRFRegister(pAd, RF_R27, 0x20); + RT30xxWriteRFRegister(pAd, RF_R28, 0x10); + } + } + else + { + if (pAd->RfIcType == RFIC_3320) + { + RT30xxWriteRFRegister(pAd, RF_R27, 0x75); + RT30xxWriteRFRegister(pAd, RF_R28, 0x10); + } + + if (pAd->RfIcType == RFIC_3020) + { + RT30xxWriteRFRegister(pAd, RF_R27, 0x21); + RT30xxWriteRFRegister(pAd, RF_R28, 0x10); + } + } + +} + + + + +/* --------------------------- public functions ----------------------------- */ + +VOID NICInitRT305xRFRegisters(IN PRTMP_ADAPTER pAd) +{ + INT i; + + /* Driver must read EEPROM to get RfIcType before initial RF registers */ + /* Initialize RF register to default value */ + if ((pAd->RfIcType == RFIC_3320) || (pAd->RfIcType == RFIC_3020) || + (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3022)) + { + /* Init RF calibration */ + /* Driver should toggle RF R30 bit7 before init RF registers */ + UINT8 RfReg = 0; + RT30xxReadRFRegister(pAd, RF_R30, (PUCHAR)&RfReg); + RfReg |= 0x80; + RT30xxWriteRFRegister(pAd, RF_R30, (UCHAR)RfReg); + RTMPusecDelay(1000); + RfReg &= 0x7F; + RT30xxWriteRFRegister(pAd, RF_R30, (UCHAR)RfReg); + + /* Initialize RF register to default value */ + if (!IS_RT3350(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Not RT3350!\n")); + for (i = 0; i < RT305x_NUM_RF_REG_PARMS; i++) + { + RT30xxWriteRFRegister(pAd, RT305x_RFRegTable[i].Register, RT305x_RFRegTable[i].Value); + } + + if ((pAd->CommonCfg.CID == 0x103) || ((pAd->CommonCfg.CN >> 16) == 0x3333)) + { + RT30xxWriteRFRegister(pAd, RF_R17, 0x93); + } + } +#ifdef RT3350 + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Is RT3350!\n")); + RT305x_NUM_RF_REG_PARMS = (sizeof(RT3350_RFRegTable) / sizeof(REG_PAIR)); + for (i = 0; i < RT305x_NUM_RF_REG_PARMS; i++) + { + RT30xxWriteRFRegister(pAd, RT3350_RFRegTable[i].Register, RT3350_RFRegTable[i].Value); + } + } +#endif /* RT3350 */ + } + + NICInitRT305xRF_R27_R28(pAd); + +} + + +VOID RT305x_PowerTuning( + IN PRTMP_ADAPTER pAd, + IN RSSI_SAMPLE *pRssi) +{ + if (!pAd->CommonCfg.HighPowerPatchDisabled) + { + UCHAR RFValue; + + if (IS_RT3052B(pAd)) + { + if ((pRssi->AvgRssi0 != 0) && (pRssi->AvgRssi0 > (pAd->BbpRssiToDbmDelta - 35) )) + { + RT30xxReadRFRegister(pAd, RF_R27, (PUCHAR)&RFValue); + RFValue &= ~0x3; + RT30xxWriteRFRegister(pAd, RF_R27, (UCHAR)RFValue); + + RT30xxReadRFRegister(pAd, RF_R28, (PUCHAR)&RFValue); + RFValue &= ~0x3; + RT30xxWriteRFRegister(pAd, RF_R28, (UCHAR)RFValue); + } + else + { + RT30xxReadRFRegister(pAd, RF_R27, (PUCHAR)&RFValue); + RFValue |= 0x3; + RT30xxWriteRFRegister(pAd, RF_R27, (UCHAR)RFValue); + + RT30xxReadRFRegister(pAd, RF_R28, (PUCHAR)&RFValue); + RFValue |= 0x3; + RT30xxWriteRFRegister(pAd, RF_R28, (UCHAR)RFValue); + } + } + + if ((pAd->Antenna.field.RxPath == 2) && (IS_RT3052B(pAd))) + { + if ((pRssi->AvgRssi0 != 0) && (pRssi->AvgRssi0 > (pAd->BbpRssiToDbmDelta - 42) )) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x42); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R67, 0x18); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R67, 0x20); + } + } + } +} + + +/* +======================================================================== +Routine Description: + Initialize RT305x. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RT305x_Init( + IN PRTMP_ADAPTER pAd) +{ + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + + + /* init capability */ + pChipCap->MaxNumOfBbpId = 200; + pChipCap->pRFRegTable = RT305x_RFRegTable; + + /* init capability */ + pChipCap->pBBPRegTable = NULL; + pChipCap->FlgIsVcoReCalMode = VCO_CAL_MODE_1; + pChipCap->TXWISize = 16; + pChipCap->RXWISize = 16; +#ifdef RTMP_FLASH_SUPPORT + pChipCap->eebuf = RT3050_EeBuffer; + if (IS_RT3052(pAd)) + pChipCap->eebuf = RT3052_EeBuffer; +#endif /* RTMP_FLASH_SUPPORT */ + /* init operator */ + pChipOps->AsicRfInit = NICInitRT305xRFRegisters; + pChipOps->AsicMacInit = NICInitRT305xMacRegisters; + pChipOps->ChipSwitchChannel = RT305x_ChipSwitchChannel; + pChipOps->AsicAdjustTxPower = AsicAdjustTxPower; + pChipOps->AsicBbpInit = NICInitRT305xBbpRegisters; + pChipOps->HighPowerTuning = RT305x_PowerTuning; + pChipOps->AsicGetTxPowerOffset = AsicGetTxPowerOffset; + +#ifdef RTMP_INTERNAL_TX_ALC + if(IS_RT3350(pAd)) + { + pChipCap->TxAlcTxPowerUpperBound_2G = 45; + pChipCap->TxPowerTuningTable_2G = RT3350_TxPowerTuningTable; + pChipOps->InitDesiredTSSITable = RT3350_InitDesiredTSSITable; + pChipOps->AsicTxAlcGetAutoAgcOffset = RT3350_AsicTxAlcGetAutoAgcOffset; + } + else +#endif /* RTMP_INTERNAL_TX_ALC */ + { + pChipOps->AsicTxAlcGetAutoAgcOffset = AsicGetAutoAgcOffsetForExternalTxAlc; + } + +#ifdef CARRIER_DETECTION_SUPPORT + pAd->chipCap.carrier_func = TONE_RADAR_V1; + pChipOps->ToneRadarProgram = ToneRadarProgram_v1; +#endif /* CARRIER_DETECTION_SUPPORT */ + + RT305x_ChipSpecInit(pAd); +} + + +/* +======================================================================== +Routine Description: + Initialize specific MAC registers. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID NICInitRT305xMacRegisters( + IN RTMP_ADAPTER *pAd) +{ + UINT32 IdReg; + + + for(IdReg=0; IdReg\n", __FUNCTION__)); + + for (IdReg = 0; IdReg < RT305x_NUM_BBP_REG_PARMS; IdReg++) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, RT305x_BBPRegTable[IdReg].Register, + RT305x_BBPRegTable[IdReg].Value); + DBGPRINT(RT_DEBUG_TRACE, ("BBP_R%d=%d\n", RT305x_BBPRegTable[IdReg].Register, + RT305x_BBPRegTable[IdReg].Value)); + } + + if ((pAd->CommonCfg.CN >> 16) == 0x3333) + { + UINT8 BBPValue = 0; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R104, &BBPValue); + BBPValue |= 0x80; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R104, BBPValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R105, 0x31); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R106, 0x46); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R113, 0x0d); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R114, 0x64); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R115, 0x34); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R116, 0x67); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R117, 0x37); + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s <---\n", __FUNCTION__)); + +} + +VOID RT305x_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 + + /* + 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, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel)); + } + + // The RF programming sequence is difference between 3xxx and 2xxx + if (((pAd->MACVersion == 0x28720200)) && + ((pAd->RfIcType == RFIC_3320) || (pAd->RfIcType == RFIC_3322) || + (pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_3021) || + (pAd->RfIcType == RFIC_3022))) + { + for (index = 0; index < NUM_OF_3020_CHNL; index++) + { + if (Channel == FreqItems3020[index].Channel) + { + // Programming channel parameters + RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N); +#ifdef RT3350 + if (IS_RT3350(pAd)) + { + RT30xxReadRFRegister(pAd, RF_R03, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xF0) | (FreqItems3020[index].K & 0x0F); + RT30xxWriteRFRegister(pAd, RF_R03, (UCHAR)RFValue); + } + else +#endif // RT3350 // + RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K); + + + RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xFC) | FreqItems3020[index].R; + RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RFValue); + + // Set Tx Power + RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xE0) | TxPwer; + RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue); + + // Set Tx1 Power + RT30xxReadRFRegister(pAd, RF_R13, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xE0) | TxPwer2; + RT30xxWriteRFRegister(pAd, RF_R13, (UCHAR)RFValue); + + // Set RF offset + RT30xxReadRFRegister(pAd, RF_R23, (PUCHAR)&RFValue); + RFValue = (RFValue & 0x80) | pAd->RfFreqOffset; + RT30xxWriteRFRegister(pAd, RF_R23, (UCHAR)RFValue); + + // Set BW + RT30xxReadRFRegister(pAd, RF_R24, &RFValue); + +#ifdef RT3350 + /*R24, BW=20M*/ + if (IS_RT3350(pAd)) + { + if(pAd->CommonCfg.PhyMode == PHY_11B) + RFValue = 0x1F; + else + RFValue = 0x18; + } + else +#endif // RT3350 // + RFValue &= 0xDF; + + + if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40) +#ifdef GREENAP_SUPPORT + && (pAd->ApCfg.bGreenAPActive == 0) +#endif // GREENAP_SUPPORT // + ) + { +#ifdef RT3350 + if (IS_RT3350(pAd)) + { + if(pAd->CommonCfg.PhyMode == PHY_11B) + RFValue = 0x3F; + else + RFValue = 0x28; + } + else +#endif // RT3350 // + RFValue |= 0x20; + } + RT30xxWriteRFRegister(pAd, RF_R24, RFValue); + + // Rx filter + if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40) +#ifdef GREENAP_SUPPORT + && (pAd->ApCfg.bGreenAPActive == 0) +#endif // GREENAP_SUPPORT // + ) + { +#ifdef RT3350 + if (IS_RT3350(pAd)) + RT30xxWriteRFRegister(pAd, RF_R31, 0x68); + else +#endif // RT3350 // + RT30xxWriteRFRegister(pAd, RF_R31, 0x2F); + } + else + { +#ifdef RT3350 + if (IS_RT3350(pAd)) + RT30xxWriteRFRegister(pAd, RF_R31, 0x48); + else +#endif // RT3350 // + RT30xxWriteRFRegister(pAd, RF_R31, 0x0F); + } + + { + // Enable RF tuning + RT30xxReadRFRegister(pAd, RF_R07, (PUCHAR)&RFValue); + RFValue = RFValue | 0x1; + RT30xxWriteRFRegister(pAd, RF_R07, (UCHAR)RFValue); + + // Antenna + RT30xxReadRFRegister(pAd, RF_R01, (PUCHAR)&RFValue); + RFValue = RFValue & 0xab; + if (pAd->Antenna.field.RxPath == 2) + { + RT30xxWriteRFRegister(pAd, RF_R01, (UCHAR)RFValue); + } + else if (pAd->Antenna.field.RxPath == 1) + { + RFValue = RFValue | 0x10; + RT30xxWriteRFRegister(pAd, RF_R01, (UCHAR)RFValue); + } + + RT30xxReadRFRegister(pAd, RF_R01, (PUCHAR)&RFValue); + RFValue = RFValue & 0x57; + if (pAd->Antenna.field.TxPath == 2) + { + RT30xxWriteRFRegister(pAd, RF_R01, (UCHAR)RFValue); + } + else if (pAd->Antenna.field.TxPath == 1) + { + RFValue = RFValue | 0x20; + RT30xxWriteRFRegister(pAd, RF_R01, (UCHAR)RFValue); + } + } + + // latch channel for future usage. + pAd->LatchRfRegs.Channel = Channel; + break; + } + } + } + else + { + switch (pAd->RfIcType) + { + default: + DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d : unknown RFIC=%d\n", + Channel, pAd->RfIcType)); + break; + } + } + + // Change BBP setting during siwtch from a->g, g->a + if (Channel <= 14) + { + ULONG TxPinCfg = 0x00050F0A;//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))); + + // Rx High power VGA offset for LNA select + { + if (pAd->NicConfig2.field.ExternalLNAForG) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + } + + // 5G band selection PIN, bit1 and bit2 are complement + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x04); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + { + // 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); + + RtmpUpdateFilterCoefficientControl(pAd, Channel); + } + else + { + ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505 + UINT8 bbpValue; + + 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))); + + /* Set the BBP_R82 value here */ + bbpValue = 0xF2; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, bbpValue); + + + // Rx High power VGA offset for LNA select + if (pAd->NicConfig2.field.ExternalLNAForA) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + // 5G band selection PIN, bit1 and bit2 are complement + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x02); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + // Turn off unused PA or LNA when only 1T or 1R + { + // 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); + } + + // R66 should be set according to Channel and use 20MHz when scanning + //AsicBBPWriteWithRxChain(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)), 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); +} + + +/* --------------------------- local functions ------------------------------ */ + +static VOID RT305x_WlanModeChange( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ +#ifdef RT3350 + if (!IS_RT3350(pAd)) + return; + + if(pAd->CommonCfg.PhyMode == PHY_11B) + { + USHORT i; + USHORT value; + UCHAR rf_offset; + UCHAR rf_value; + + RT28xx_EEPROM_READ16(pAd, 0x126, value); + rf_value = value & 0x00FF; + rf_offset = (value & 0xFF00) >> 8; + + if(rf_offset == 0xff) + rf_offset = RF_R21; + if(rf_value == 0xff) + rf_value = 0x4F; + RT30xxWriteRFRegister(pAd, rf_offset, (UCHAR)rf_value); + + RT28xx_EEPROM_READ16(pAd, 0x12a, value); + rf_value = value & 0x00FF; + rf_offset = (value & 0xFF00) >> 8; + + if(rf_offset == 0xff) + rf_offset = RF_R29; + if(rf_value == 0xff) + rf_value = 0x07; + RT30xxWriteRFRegister(pAd, rf_offset, (UCHAR)rf_value); + + + // set RF_R24 + if(pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + { + value = 0x3F; + } + else + { + value = 0x1F; + } + RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)value); + } + else + { + USHORT i; + USHORT value; + UCHAR rf_offset; + UCHAR rf_value; + + RT28xx_EEPROM_READ16(pAd, 0x124, value); + rf_value = value & 0x00FF; + rf_offset = (value & 0xFF00) >> 8; + + if(rf_offset == 0xff) + rf_offset = RF_R21; + if(rf_value == 0xff) + rf_value = 0x6F; + RT30xxWriteRFRegister(pAd, rf_offset, (UCHAR)rf_value); + + RT28xx_EEPROM_READ16(pAd, 0x128, value); + rf_value = value & 0x00FF; + rf_offset = (value & 0xFF00) >> 8; + + if(rf_offset == 0xff) + rf_offset = RF_R29; + if(rf_value == 0xff) + rf_value = 0x07; + RT30xxWriteRFRegister(pAd, rf_offset, (UCHAR)rf_value); + + // set RF_R24 + if(pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + { + value = 0x28; + } + else + { + value = 0x18; + } + RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)value); + } +#endif /* RT3350 */ +} + + +static VOID RT305x_HtModeChange( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + UINT8 Value = 0; + UCHAR BW = Data; + + if (BW == BW_40) + { + if (!IS_RT3350(pAd)) + { + RT30xxReadRFRegister(pAd, RF_R24, (PUCHAR)&Value); +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPActive == 1) + Value &= 0xDF; + else +#endif // GREENAP_SUPPORT // + Value |= 0x20; + RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)Value); + + +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPActive == 1) + RT30xxWriteRFRegister(pAd, RF_R31, 0x0F); + else +#endif // GREENAP_SUPPORT // + RT30xxWriteRFRegister(pAd, RF_R31, 0x2F); + } + else + { + RT30xxReadRFRegister(pAd, RF_R24, (PUCHAR)&Value); +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPActive == 1) + Value &= 0xCF; + else +#endif // GREENAP_SUPPORT // + Value = 0x28; /*kurtis: RT3350 non CCK Mode, BW=40M => RF_R24=0x28*/ + RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)Value); + + +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPActive == 1) + RT30xxWriteRFRegister(pAd, RF_R31, 0x48); + else +#endif // GREENAP_SUPPORT // + RT30xxWriteRFRegister(pAd, RF_R31, 0x68); + } + } + else + { + if (!IS_RT3350(pAd)) + { + RT30xxReadRFRegister(pAd, RF_R24, (PUCHAR)&Value); + Value &= 0xDF; + RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)Value); + RT30xxWriteRFRegister(pAd, RF_R31, 0x0F); + } + else + { + /*kurtis: RT3350 non CCK Mode, BW=20M => RF_R24=0x18*/ + Value = 0x18; + RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)Value); + + RT30xxWriteRFRegister(pAd, RF_R31, 0x48); + } + } +} + + +static VOID RT305x_SpecificInit( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ +#ifdef RT3350 + if (!IS_RT3350(pAd)) + return; + + if(1) + { + USHORT i; + USHORT value; + UCHAR rf_offset; + UCHAR rf_value; + + RT28xx_EEPROM_READ16(pAd, 0x120, value); + rf_value = value & 0x00FF; + rf_offset = (value & 0xFF00) >> 8; + + if(rf_offset == 0xff) + rf_offset = RF_R09; + if(rf_value == 0xff) + rf_value = 0x01; + + RT30xxWriteRFRegister(pAd, rf_offset, (UCHAR)rf_value); + + RT28xx_EEPROM_READ16(pAd, 0x122, value); + rf_value = value & 0x00FF; + rf_offset = (value & 0xFF00) >> 8; + + if(rf_offset == 0xff) + rf_offset = RF_R19; + if(rf_value == 0xff) + rf_value = 0xcc; + + RT30xxWriteRFRegister(pAd, rf_offset, (UCHAR)rf_value); + } + + if(pAd->CommonCfg.PhyMode == PHY_11B) + { + USHORT i; + USHORT value; + UCHAR rf_offset; + UCHAR rf_value; + + RT28xx_EEPROM_READ16(pAd, 0x126, value); + rf_value = value & 0x00FF; + rf_offset = (value & 0xFF00) >> 8; + + if(rf_offset == 0xff) + rf_offset = RF_R21; + if(rf_value == 0xff) + rf_value = 0x4F; + RT30xxWriteRFRegister(pAd, rf_offset, (UCHAR)rf_value); + + RT28xx_EEPROM_READ16(pAd, 0x12a, value); + rf_value = value & 0x00FF; + rf_offset = (value & 0xFF00) >> 8; + + if(rf_offset == 0xff) + rf_offset = RF_R29; + if(rf_value == 0xff) + rf_value = 0x07; + RT30xxWriteRFRegister(pAd, rf_offset, (UCHAR)rf_value); + + + // set RF_R24 + if(pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + { + value = 0x3F; + } + else + { + value = 0x1F; + } + RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)value); + + + } + else + { + USHORT i; + USHORT value; + UCHAR rf_offset; + UCHAR rf_value; + + RT28xx_EEPROM_READ16(pAd, 0x124, value); + rf_value = value & 0x00FF; + rf_offset = (value & 0xFF00) >> 8; + + if(rf_offset == 0xff) + rf_offset = RF_R21; + if(rf_value == 0xff) + rf_value = 0x6F; + RT30xxWriteRFRegister(pAd, rf_offset, (UCHAR)rf_value); + + RT28xx_EEPROM_READ16(pAd, 0x128, value); + rf_value = value & 0x00FF; + rf_offset = (value & 0xFF00) >> 8; + + if(rf_offset == 0xff) + rf_offset = RF_R29; + if(rf_value == 0xff) + rf_value = 0x07; + RT30xxWriteRFRegister(pAd, rf_offset, (UCHAR)rf_value); + + // set RF_R24 + if(pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + { + value = 0x28; + } + else + { + value = 0x18; + } + RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)value); + + } + +#ifdef CONFIG_ZTE_RADIO_ONOFF + if (!pAd->CommonCfg.bRadioEnable) + RTMP_MLME_RADIO_OFF(pAd); +#endif // CONFIG_ZTE_RADIO_ONOFF // +#endif /* RT3350 */ +} + +#ifdef RTMP_INTERNAL_TX_ALC +VOID RT3350_InitDesiredTSSITable( + IN PRTMP_ADAPTER pAd) +{ + UCHAR TSSIBase = 0; /* The TSSI over OFDM 54Mbps */ + USHORT TSSIStepOver2dot4G = 0; /* The TSSI value/step (0.5 dB/unit) */ + UCHAR RFValue = 0; + BBP_R49_STRUC BbpR49; + ULONG i = 0; + USHORT TxPower = 0, TxPowerOFDM54 = 0, temp = 0; + + BbpR49.byte = 0; + + if (pAd->TxPowerCtrl.bInternalTxALC == FALSE) + { + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("---> %s\n", __FUNCTION__)); + + RT28xx_EEPROM_READ16(pAd, EEPROM_TSSI_OVER_OFDM_54, temp); + TSSIBase = (temp & 0x001F); + + RT28xx_EEPROM_READ16(pAd, (EEPROM_TSSI_STEP_OVER_2DOT4G - 1), TSSIStepOver2dot4G); + TSSIStepOver2dot4G = (0x000F & (TSSIStepOver2dot4G >> 8)); + + RT28xx_EEPROM_READ16(pAd, (EEPROM_OFDM_MCS6_MCS7 - 1), TxPowerOFDM54); + TxPowerOFDM54 = (0x000F & (TxPowerOFDM54 >> 8)); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: TSSIBase = %d, TSSIStepOver2dot4G = %d, TxPowerOFDM54 = %d\n", + __FUNCTION__, + TSSIBase, + TSSIStepOver2dot4G, + TxPowerOFDM54)); + + /* The desired TSSI over CCK */ + RT28xx_EEPROM_READ16(pAd, EEPROM_CCK_MCS0_MCS1, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xDE = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverCCK[MCS_0] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2)) + 6); + desiredTSSIOverCCK[MCS_1] = desiredTSSIOverCCK[MCS_0]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_CCK_MCS2_MCS3 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xDF = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverCCK[MCS_2] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2)) + 6); + desiredTSSIOverCCK[MCS_3] = desiredTSSIOverCCK[MCS_2]; + + /* Boundary verification: the desired TSSI value */ + for (i = 0; i < 4; i++) /* CCK: MCS 0 ~ MCS 3 */ + { + if (desiredTSSIOverCCK[i] < 0x00) + { + desiredTSSIOverCCK[i] = 0x00; + } + else if (desiredTSSIOverCCK[i] > 0x1F) + { + desiredTSSIOverCCK[i] = 0x1F; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverCCK[0] = %d, desiredTSSIOverCCK[1] = %d, desiredTSSIOverCCK[2] = %d, desiredTSSIOverCCK[3] = %d\n", + __FUNCTION__, + desiredTSSIOverCCK[0], + desiredTSSIOverCCK[1], + desiredTSSIOverCCK[2], + desiredTSSIOverCCK[3])); + + /* The desired TSSI over OFDM */ + RT28xx_EEPROM_READ16(pAd, EEPROM_OFDM_MCS0_MCS1, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE0 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverOFDM[MCS_0] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverOFDM[MCS_1] = desiredTSSIOverOFDM[MCS_0]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_OFDM_MCS2_MCS3 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE1 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverOFDM[MCS_2] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverOFDM[MCS_3] = desiredTSSIOverOFDM[MCS_2]; + RT28xx_EEPROM_READ16(pAd, EEPROM_OFDM_MCS4_MCS5, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE2 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverOFDM[MCS_4] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverOFDM[MCS_5] = desiredTSSIOverOFDM[MCS_4]; + desiredTSSIOverOFDM[MCS_6] = TSSIBase; + desiredTSSIOverOFDM[MCS_7] = TSSIBase; + + /* Boundary verification: the desired TSSI value */ + for (i = 0; i < 8; i++) /* OFDM: MCS 0 ~ MCS 7 */ + { + if (desiredTSSIOverOFDM[i] < 0x00) + { + desiredTSSIOverOFDM[i] = 0x00; + } + else if (desiredTSSIOverOFDM[i] > 0x1F) + { + desiredTSSIOverOFDM[i] = 0x1F; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverOFDM[0] = %d, desiredTSSIOverOFDM[1] = %d, desiredTSSIOverOFDM[2] = %d, desiredTSSIOverOFDM[3] = %d\n", + __FUNCTION__, + desiredTSSIOverOFDM[0], + desiredTSSIOverOFDM[1], + desiredTSSIOverOFDM[2], + desiredTSSIOverOFDM[3])); + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverOFDM[4] = %d, desiredTSSIOverOFDM[5] = %d, desiredTSSIOverOFDM[6] = %d, desiredTSSIOverOFDM[7] = %d\n", + __FUNCTION__, + desiredTSSIOverOFDM[4], + desiredTSSIOverOFDM[5], + desiredTSSIOverOFDM[6], + desiredTSSIOverOFDM[7])); + + /* The desired TSSI over HT */ + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_MCS0_MCS1, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE4 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHT[MCS_0] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_1] = desiredTSSIOverHT[MCS_0]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_MCS2_MCS3 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE5 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHT[MCS_2] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_3] = desiredTSSIOverHT[MCS_2]; + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_MCS4_MCS5, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE6 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHT[MCS_4] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_5] = desiredTSSIOverHT[MCS_4]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_MCS6_MCS7 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE7 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHT[MCS_6] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_7] = desiredTSSIOverHT[MCS_6]; + + /* Boundary verification: the desired TSSI value */ + for (i = 0; i < 8; i++) /* HT: MCS 0 ~ MCS 7 */ + { + if (desiredTSSIOverHT[i] < 0x00) + { + desiredTSSIOverHT[i] = 0x00; + } + else if (desiredTSSIOverHT[i] > 0x1F) + { + desiredTSSIOverHT[i] = 0x1F; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHT[0] = %d, desiredTSSIOverHT[1] = %d, desiredTSSIOverHT[2] = %d, desiredTSSIOverHT[3] = %d\n", + __FUNCTION__, + desiredTSSIOverHT[0], + desiredTSSIOverHT[1], + desiredTSSIOverHT[2], + desiredTSSIOverHT[3])); + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHT[4] = %d, desiredTSSIOverHT[5] = %d, desiredTSSIOverHT[6] = %d, desiredTSSIOverHT[7] = %d\n", + __FUNCTION__, + desiredTSSIOverHT[4], + desiredTSSIOverHT[5], + desiredTSSIOverHT[6], + desiredTSSIOverHT[7])); + + /* The desired TSSI over HT using STBC */ + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_USING_STBC_MCS0_MCS1, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xEC = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHTUsingSTBC[MCS_0] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHTUsingSTBC[MCS_1] = desiredTSSIOverHTUsingSTBC[MCS_0]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_USING_STBC_MCS2_MCS3 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xED = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHTUsingSTBC[MCS_2] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHTUsingSTBC[MCS_3] = desiredTSSIOverHTUsingSTBC[MCS_2]; + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_USING_STBC_MCS4_MCS5, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xEE = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHTUsingSTBC[MCS_4] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHTUsingSTBC[MCS_5] = desiredTSSIOverHTUsingSTBC[MCS_4]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_USING_STBC_MCS6_MCS7 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xEF = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHTUsingSTBC[MCS_6] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHTUsingSTBC[MCS_7] = desiredTSSIOverHTUsingSTBC[MCS_6]; + + /* Boundary verification: the desired TSSI value */ + for (i = 0; i < 8; i++) /* HT using STBC: MCS 0 ~ MCS 7 */ + { + if (desiredTSSIOverHTUsingSTBC[i] < 0x00) + { + desiredTSSIOverHTUsingSTBC[i] = 0x00; + } + else if (desiredTSSIOverHTUsingSTBC[i] > 0x1F) + { + desiredTSSIOverHTUsingSTBC[i] = 0x1F; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHTUsingSTBC[0] = %d, desiredTSSIOverHTUsingSTBC[1] = %d, desiredTSSIOverHTUsingSTBC[2] = %d, desiredTSSIOverHTUsingSTBC[3] = %d\n", + __FUNCTION__, + desiredTSSIOverHTUsingSTBC[0], + desiredTSSIOverHTUsingSTBC[1], + desiredTSSIOverHTUsingSTBC[2], + desiredTSSIOverHTUsingSTBC[3])); + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHTUsingSTBC[4] = %d, desiredTSSIOverHTUsingSTBC[5] = %d, desiredTSSIOverHTUsingSTBC[6] = %d, desiredTSSIOverHTUsingSTBC[7] = %d\n", + __FUNCTION__, + desiredTSSIOverHTUsingSTBC[4], + desiredTSSIOverHTUsingSTBC[5], + desiredTSSIOverHTUsingSTBC[6], + desiredTSSIOverHTUsingSTBC[7])); + + RT30xxReadRFRegister(pAd, RF_R27, (PUCHAR)(&RFValue)); + RFValue = (RFValue | 0x88); /* <7>: IF_Rxout_en, <3>: IF_Txout_en */ + RT30xxWriteRFRegister(pAd, RF_R27, RFValue); + + RT30xxReadRFRegister(pAd, RF_R28, (PUCHAR)(&RFValue)); + RFValue = (RFValue & (~0x60)); /* <6:5>: tssi_atten */ + RT30xxWriteRFRegister(pAd, RF_R28, RFValue); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49.byte); + BbpR49.field.adc5_in_sel = 1; /* Enable the PSI (internal components, new version - RT3390) */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R49, BbpR49.byte); + + DBGPRINT(RT_DEBUG_TRACE, ("<--- %s\n", __FUNCTION__)); +} + +/* + ========================================================================== + Description: + Get the desired TSSI based on the latest packet + + Arguments: + pAd + + Return Value: + The desired TSSI + ========================================================================== + */ +UCHAR RT3350_GetDesiredTSSI( + IN PRTMP_ADAPTER pAd) +{ + PHTTRANSMIT_SETTING pLatestTxHTSetting = (PHTTRANSMIT_SETTING)(&pAd->LastTxRate); + UCHAR desiredTSSI = 0; + UCHAR MCS = 0; + + MCS = (UCHAR)(pLatestTxHTSetting->field.MCS); + + if (pLatestTxHTSetting->field.MODE == MODE_CCK) + { + if ((MCS < 0) || (MCS > 3)) /* boundary verification */ + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: incorrect MCS: MCS = %d\n", __FUNCTION__, MCS)); + MCS = 0; + } + + desiredTSSI = desiredTSSIOverCCK[MCS]; + } + else if (pLatestTxHTSetting->field.MODE == MODE_OFDM) + { + if ((MCS < 0) || (MCS > 7)) /* boundary verification */ + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: incorrect MCS: MCS = %d\n", __FUNCTION__, MCS)); + MCS = 0; + } + + desiredTSSI = desiredTSSIOverOFDM[MCS]; + } + else if ((pLatestTxHTSetting->field.MODE == MODE_HTMIX) || (pLatestTxHTSetting->field.MODE == MODE_HTGREENFIELD)) + { + if ((MCS < 0) || (MCS > 7)) /* boundary verification */ + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: incorrect MCS: MCS = %d\n", __FUNCTION__, MCS)); + MCS = 0; + } + + if (pLatestTxHTSetting->field.STBC == 1) + { + desiredTSSI = desiredTSSIOverHT[MCS]; + } + else + { + desiredTSSI = desiredTSSIOverHTUsingSTBC[MCS]; + } + + /* For HT BW40 MCS 7 with/without STBC configuration, the desired TSSI value should subtract one from the formula */ + if ((pLatestTxHTSetting->field.BW == BW_40) && (MCS == MCS_7)) + { + desiredTSSI -= 1; + } + } + + DBGPRINT(RT_DEBUG_INFO, ("%s: desiredTSSI = %d, Latest Tx HT setting: MODE = %d, MCS = %d, STBC = %d\n", + __FUNCTION__, + desiredTSSI, + pLatestTxHTSetting->field.MODE, + pLatestTxHTSetting->field.MCS, + pLatestTxHTSetting->field.STBC)); + + DBGPRINT(RT_DEBUG_INFO, ("<--- %s\n", __FUNCTION__)); + + return desiredTSSI; +} + +VOID RT3350_AsicTxAlcGetAutoAgcOffset( + IN PRTMP_ADAPTER pAd, + IN PCHAR pDeltaPwr, + IN PCHAR pTotalDeltaPwr, + IN PCHAR pAgcCompensate, + IN PCHAR pDeltaPowerByBbpR1) +{ + const TX_POWER_TUNING_ENTRY_STRUCT *TxPowerTuningTable = pAd->chipCap.TxPowerTuningTable_2G; + PTX_POWER_TUNING_ENTRY_STRUCT pTxPowerTuningEntry = NULL; + BBP_R49_STRUC BbpR49; + UCHAR RFValue = 0; + CHAR desiredTssi = 0; + CHAR currentTssi = 0; + CHAR TotalDeltaPower = 0; + CHAR TuningTableIndex = 0; + + BbpR49.byte = 0; + + /* Locate the Internal Tx ALC tuning entry */ + if ((pAd->TxPowerCtrl.bInternalTxALC == TRUE) && (IS_RT3350(pAd))) + { + if ((pAd->Mlme.OneSecPeriodicRound % 4 == 0) && (*pDeltaPowerByBbpR1 == 0)) + { + desiredTssi = RT3350_GetDesiredTSSI(pAd); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49.byte); + currentTssi = BbpR49.field.TSSI; + + if (desiredTssi > currentTssi) + { + pAd->TxPowerCtrl.idxTxPowerTable++; + } + + if (desiredTssi < currentTssi) + { + pAd->TxPowerCtrl.idxTxPowerTable--; + } + + TuningTableIndex = pAd->TxPowerCtrl.idxTxPowerTable +#ifdef DOT11_N_SUPPORT + + pAd->TxPower[pAd->CommonCfg.CentralChannel-1].Power; +#else + + pAd->TxPower[pAd->CommonCfg.Channel-1].Power; +#endif /* DOT11_N_SUPPORT */ + + if (TuningTableIndex < LOWERBOUND_TX_POWER_TUNING_ENTRY) + { + TuningTableIndex = LOWERBOUND_TX_POWER_TUNING_ENTRY; + } + + if (TuningTableIndex > UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd)) + { + TuningTableIndex = UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd); + } + + /* Valide pAd->TxPowerCtrl.idxTxPowerTable: -30 ~ 45 */ + pTxPowerTuningEntry = &TxPowerTuningTable[TuningTableIndex + TX_POWER_TUNING_ENTRY_OFFSET]; + pAd->TxPowerCtrl.RF_TX_ALC = pTxPowerTuningEntry->RF_TX_ALC; + pAd->TxPowerCtrl.MAC_PowerDelta = pTxPowerTuningEntry->MAC_PowerDelta; + + /* Tx power adjustment over RF */ + RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)(&RFValue)); + RFValue = ((RFValue & 0xE0) | pAd->TxPowerCtrl.RF_TX_ALC); + RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)(RFValue)); + + /* Tx power adjustment over MAC */ + TotalDeltaPower += pAd->TxPowerCtrl.MAC_PowerDelta; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSI = %d, currentTSSI = %d, idxTxPowerTable = %d, TuningTableIndex = %d, {RF_TX_ALC = %d, MAC_PowerDelta = %d}\n", + __FUNCTION__, + desiredTssi, + currentTssi, + pAd->TxPowerCtrl.idxTxPowerTable, + TuningTableIndex, + pTxPowerTuningEntry->RF_TX_ALC, + pTxPowerTuningEntry->MAC_PowerDelta)); + } + else + { + /* Tx power adjustment over RF */ + RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)(&RFValue)); + RFValue = ((RFValue & 0xE0) | pAd->TxPowerCtrl.RF_TX_ALC); + RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)(RFValue)); + + /* Tx power adjustment over MAC */ + TotalDeltaPower += pAd->TxPowerCtrl.MAC_PowerDelta; + } + } + + *pTotalDeltaPwr = TotalDeltaPower; +} +#endif /* RTMP_INTERNAL_TX_ALC */ + +VOID RT305x_ChipSpecInit( + IN RTMP_ADAPTER *pAd) +{ + INT i; + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + + printk("%s: CHIP_SPEC_ID_NUM(%d)\n", __FUNCTION__, CHIP_SPEC_ID_NUM); + + /* Default as NULL function */ + for (i = 0; i < CHIP_SPEC_ID_NUM; i++) + { + pChipOps->ChipSpecFunc[i] = NULL; + } + + /* re-assign the corresponding routine */ + pChipOps->ChipSpecFunc[RT305x_WLAN_MODE_CHANGE] = + (CHIP_SPEC_FUNC)RT305x_WlanModeChange; + pChipOps->ChipSpecFunc[RT305x_INITIALIZATION] = + (CHIP_SPEC_FUNC)RT305x_SpecificInit; + pChipOps->ChipSpecFunc[RT305x_HT_MODE_CHANGE] = + (CHIP_SPEC_FUNC)RT305x_HtModeChange; + + + +} + + +#endif // RT305x // + +/* End of rt305x.c */ diff --git a/mt7620/src/chips/rt3352.c b/mt7620/src/chips/rt3352.c new file mode 100644 index 0000000..c9dcc28 --- /dev/null +++ b/mt7620/src/chips/rt3352.c @@ -0,0 +1,2481 @@ +/* + *************************************************************************** + * 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: + rt3352.c + + Abstract: + Specific funcitons and variables for RT3352 + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifdef RT3352 + +#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 RT3352_EeBuffer[EEPROM_SIZE] = { + 0x52, 0x33, 0x01, 0x01, 0x00, 0x0c, 0x43, 0x30, 0x52, 0x88, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 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, 0x33, 0x52, 0x77, 0x00, 0x0c, 0x43, 0x33, 0x52, 0x66, 0x22, 0x0c, 0x20, 0x00, + 0xff, 0xff, 0x2f, 0x01, 0x55, 0x77, 0xa8, 0xaa, 0x8c, 0x88, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x10, 0x10, + 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x14, 0x14, 0x14, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x66, 0x66, + 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, + 0x88, 0x66, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + } ; + +REG_PAIR RT3352_RFRegTable[] = { + {RF_R00, 0xF0}, + {RF_R01, 0x23}, /* R1 bit<1,0>=11 Path setting By EEPROM */ + {RF_R02, 0x50}, /* Fix Power DAC Variation.(20110928) */ + {RF_R03, 0x18}, + {RF_R04, 0x00}, + {RF_R05, 0x00}, /* Read only */ + {RF_R06, 0x33}, + {RF_R07, 0x00}, + {RF_R08, 0xF1}, /* By Channel Plan */ + {RF_R09, 0x02}, /* By Channel Plan */ + {RF_R10, 0xD2}, + {RF_R11, 0x42}, + {RF_R12, 0x1C}, + {RF_R13, 0x00}, + {RF_R14, 0x5A}, + {RF_R15, 0x00}, + {RF_R16, 0x01}, +/* {RF_R17, 0x1A}, By EEPROM Frequency offset */ + {RF_R18, 0x45}, + {RF_R19, 0x02}, + {RF_R20, 0x00}, + {RF_R21, 0x00}, + {RF_R22, 0x00}, + {RF_R23, 0x00}, + {RF_R24, 0x00}, + {RF_R25, 0x80}, + {RF_R26, 0x00}, + {RF_R27, 0x03}, + {RF_R28, 0x03}, + {RF_R29, 0x00}, + {RF_R30, 0x10}, /* 20MBW=0x10 40MBW=0x13 */ + {RF_R31, 0x80}, + {RF_R32, 0x80}, + {RF_R33, 0x00}, + {RF_R34, 0x01}, + {RF_R35, 0x03}, + {RF_R36, 0xBD}, + {RF_R37, 0x3C}, + {RF_R38, 0x5F}, + {RF_R39, 0xC5}, + {RF_R40, 0x33}, + {RF_R41, 0x5B}, + {RF_R42, 0x5B}, + {RF_R43, 0xDB}, + {RF_R44, 0xDB}, + {RF_R45, 0xDB}, + {RF_R46, 0xDD}, + {RF_R47, 0x0D}, + {RF_R48, 0x14}, + {RF_R49, 0x00}, + {RF_R50, 0x2D}, + {RF_R51, 0x7F}, + {RF_R52, 0x00}, + {RF_R53, 0x52}, + {RF_R54, 0x1B}, + {RF_R55, 0x7F}, + {RF_R56, 0x00}, + {RF_R57, 0x52}, + {RF_R58, 0x1B}, + {RF_R59, 0x00}, + {RF_R60, 0x00}, + {RF_R61, 0x00}, + {RF_R62, 0x00}, + {RF_R63, 0x00}, +}; + +UCHAR RT3352_NUM_RF_REG_PARMS = (sizeof(RT3352_RFRegTable) / sizeof(REG_PAIR)); + + +REG_PAIR RT3352_BBPRegTable[] = { + /* + Power saving on: 5bit mode(BBP R3[7:6]=11) + Power saving off: 8bit mode(BBP R3[7:6]=00) + */ + /* 0x01 --> 0x00 for packet detection (2011/7/1) */ + /* It shall always select ADC 0 as RX ADC input.BBP_R3[1:0]=0 */ + {BBP_R3, 0x00}, /* use 5bit ADC for Acquisition */ + {BBP_R4, 0x50}, // 2883 need to + //The new 8-b ADC applies to the following projects: RT3352/RT3593/RT3290/RT5390 and the coming new projects. + //BB REG: R31: 0x08. ( bit4:2 ADC buffer current: 010, bit1:0 ADC current: 00 (40uA)). + {BBP_R31, 0x08}, //gary recommend for ACE + {BBP_R47, 0x48}, // ALC Functions change from 0x7 to 0x48 Baron suggest +// turn on find AGC cause QA have Rx problem 2009-10-26 in 3883 + {BBP_R65, 0x2C}, // fix rssi issue + {BBP_R66, 0x38}, // Also set this default value to pAd->BbpTuning.R66CurrentValue at initial + {BBP_R68, 0x0B}, // Gary 2009-05-14: for all platform + {BBP_R69, 0x1C}, + {BBP_R70, 0xa}, // BBP_R70 will change to 0x8 in ApStartUp and LinkUp for rt2860C, otherwise value is 0xa + {BBP_R73, 0x10}, + {BBP_R78, 0x0E}, + {BBP_R80, 0x08}, // requested by Gary for high power + {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, 0x38}, /* Gary, 20100721, for 6M sensitivity improvement */ + {BBP_R88, 0x90}, // for rt3883 middle range, Henry 2009-12-31 + {BBP_R91, 0x04}, // middle range issue, Rory @2008-01-28 + {BBP_R92, 0x02}, // middle range issue, Rory @2008-01-28 + + {BBP_R103, 0xC0}, + {BBP_R104, 0x92}, + {BBP_R105, 0x34}, + {BBP_R106, 0x1D}, + {BBP_R120, 0x50}, // for long range -2db, Gary 2010-01-22 + {BBP_R137, 0x0F}, // julian suggest make the RF output more stable + {BBP_R163, 0xBD}, // Enable saving of Explicit and Implicit profiles + + {BBP_R179, 0x02}, // Set ITxBF timeout to 0x9C40=1000msec + {BBP_R180, 0x00}, + {BBP_R182, 0x40}, + {BBP_R180, 0x01}, + {BBP_R182, 0x9C}, + {BBP_R179, 0x00}, + + {BBP_R142, 0x04}, // Reprogram the inband interface to put right values in RXWI + {BBP_R143, 0x3b}, + {BBP_R142, 0x06}, + {BBP_R143, 0xA0}, + {BBP_R142, 0x07}, + {BBP_R143, 0xA1}, + {BBP_R142, 0x08}, + {BBP_R143, 0xA2}, + + {BBP_R148, 0xC8}, // Gary, 2010-02-12 +}; + +UCHAR RT3352_NUM_BBP_REG_PARMS = (sizeof(RT3352_BBPRegTable) / sizeof(REG_PAIR)); + + +RTMP_REG_PAIR RT3352_MACRegTable[] = { + {TX_SW_CFG0, 0x402}, // Gary,2010-07-20 + {TX_SW_CFG2, 0x00}, // Gary,2010-08-17 +}; + +UCHAR RT3352_NUM_MAC_REG_PARMS = (sizeof(RT3352_MACRegTable) / sizeof(RTMP_REG_PAIR)); + + +#ifdef RTMP_INTERNAL_TX_ALC +TX_POWER_TUNING_ENTRY_STRUCT RT3352_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 */ + +/* +======================================================================== +Routine Description: + Initialize RT3352. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RT3352_Init( + IN PRTMP_ADAPTER pAd) +{ + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + + /* init capability */ + pChipCap->MaxNumOfRfId = 63; + pChipCap->MaxNumOfBbpId = 255; + pChipCap->pRFRegTable = RT3352_RFRegTable; + pChipCap->pBBPRegTable = RT3352_BBPRegTable; + pChipCap->bbpRegTbSize = RT3352_NUM_BBP_REG_PARMS; + pChipCap->SnrFormula = SNR_FORMULA2; + pChipCap->RfReg17WtMethod = RF_REG_WT_METHOD_STEP_ON; + pChipOps->AsicGetTxPowerOffset = AsicGetTxPowerOffset; + +#ifdef RTMP_INTERNAL_TX_ALC + pChipCap->TxAlcTxPowerUpperBound_2G = 61; + pChipCap->TxPowerMaxCompenStep = 8; /* default 4dB (one step is 0.5dB) */ + pChipCap->TxPowerTableMaxIdx = 0; + pChipCap->TxPowerTuningTable_2G = RT3352_TxPowerTuningTable; + pChipOps->InitDesiredTSSITable = RT3352_InitDesiredTSSITable; + pChipOps->AsicTxAlcGetAutoAgcOffset = RT3352_AsicTxAlcGetAutoAgcOffset; +#endif /* RTMP_INTERNAL_TX_ALC */ + + pChipCap->FlgIsHwWapiSup = TRUE; + + pChipCap->FlgIsVcoReCalMode = VCO_CAL_MODE_2; + pChipCap->TXWISize = 16; + pChipCap->RXWISize = 16; +#ifdef RTMP_FLASH_SUPPORT + pChipCap->eebuf = RT3352_EeBuffer; +#endif /* RTMP_FLASH_SUPPORT */ + +#ifdef NEW_MBSSID_MODE + pChipCap->MBSSIDMode = MBSSID_MODE1; +#else + pChipCap->MBSSIDMode = MBSSID_MODE0; +#endif /* NEW_MBSSID_MODE */ + + + /* init operator */ + pChipOps->AsicRfInit = NICInitRT3352RFRegisters; + pChipOps->AsicBbpInit = NICInitRT3352BbpRegisters; + pChipOps->AsicMacInit = NICInitRT3352MacRegisters; + +#ifdef GREENAP_SUPPORT + pChipOps->EnableAPMIMOPS = RT3352_EnableAPMIMOPS; + pChipOps->DisableAPMIMOPS = RT3352_DisableAPMIMOPS; +#endif /* GREENAP_SUPPORT */ + + pChipOps->RxSensitivityTuning = RT3352_RxSensitivityTuning; +#ifdef CONFIG_STA_SUPPORT + pChipOps->ChipAGCAdjust = RT3352_ChipAGCAdjust; +#endif /* CONFIG_STA_SUPPORT */ + pChipOps->ChipBBPAdjust = RT3352_ChipBBPAdjust; + pChipOps->ChipSwitchChannel = RT3352_ChipSwitchChannel; + pChipOps->AsicAdjustTxPower = AsicAdjustTxPower; + pChipOps->ChipAGCInit = RT3352_RTMPSetAGCInitValue; +#ifdef CARRIER_DETECTION_SUPPORT + pAd->chipCap.carrier_func = TONE_RADAR_V2; + pChipOps->ToneRadarProgram = ToneRadarProgram_v2; +#endif /* CARRIER_DETECTION_SUPPORT */ +#ifdef RTMP_INTERNAL_TX_ALC + pChipOps->InitDesiredTSSITable = RT3352_AsicInitDesiredTSSITable; +#endif /* RTMP_INTERNAL_TX_ALC */ +#ifdef GREENAP_SUPPORT + pChipOps->EnableAPMIMOPS = EnableAPMIMOPSv2; + pChipOps->DisableAPMIMOPS = DisableAPMIMOPSv2; +#endif /* GREENAP_SUPPORT */ + RtmpChipBcnSpecInit(pAd); +} + + +/* +======================================================================== +Routine Description: + Initialize specific MAC registers for RT3352. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID NICInitRT3352MacRegisters( + IN PRTMP_ADAPTER pAd) +{ + UINT32 IdReg; + + + for(IdReg=0; IdRegRfFreqOffset & 0x7F; + RT30xxReadRFRegister(pAd, RF_R17, (PUCHAR)&RfValue1); + if (RFValue != RfValue1) + RT30xxWriteRFRegister(pAd, RF_R17, (UCHAR)RFValue); + + // Initialize RF register to default value + for (i = 0; i < RT3352_NUM_RF_REG_PARMS; i++) + { + RT30xxWriteRFRegister(pAd, RT3352_RFRegTable[i].Register, RT3352_RFRegTable[i].Value); + } + + + RT28xx_EEPROM_READ16(pAd, EEPROM_NIC2_OFFSET, value); + + if (value!=0xFFFF) + { + /* EEPROM is empty */ + if (value & (1<<14)) + { + /* TX0: 0=internal PA, 1=external PA */ + RT30xxReadRFRegister(pAd, RF_R34, (PUCHAR)&RfReg); + RfReg |= (0x1 << 2); /* tx0_lowgain=20db attenuation */ + RT30xxWriteRFRegister(pAd, RF_R34, (UCHAR)RfReg); + + RfReg = 0x52; + RT30xxWriteRFRegister(pAd, RF_R41, (UCHAR)RfReg); + + RT30xxReadRFRegister(pAd, RF_R50, (PUCHAR)&RfReg); + RfReg |= 0x7; + RT30xxWriteRFRegister(pAd, RF_R50, (UCHAR)RfReg); + + RfReg = 0x52; + RT30xxWriteRFRegister(pAd, RF_R51, (UCHAR)RfReg); + + RfReg = 0xC0; + RT30xxWriteRFRegister(pAd, RF_R52, (UCHAR)RfReg); + + RfReg = 0xD2; + RT30xxWriteRFRegister(pAd, RF_R53, (UCHAR)RfReg); + + RfReg = 0xC0; + RT30xxWriteRFRegister(pAd, RF_R54, (UCHAR)RfReg); + } + else + { + RT30xxReadRFRegister(pAd, RF_R34, (PUCHAR)&RfReg); + RfReg &= ~(0x1 << 2); + RT30xxWriteRFRegister(pAd, RF_R34, (UCHAR)RfReg); + + RfReg = 0x5B; + RT30xxWriteRFRegister(pAd, RF_R41, (UCHAR)RfReg); + + RT30xxReadRFRegister(pAd, RF_R50, (PUCHAR)&RfReg); + RfReg &= ~0x7; + RfReg |= 0x5; + RT30xxWriteRFRegister(pAd, RF_R50, (UCHAR)RfReg); + + RfReg = 0x7F; + RT30xxWriteRFRegister(pAd, RF_R51, (UCHAR)RfReg); + + RfReg = 0x00; + RT30xxWriteRFRegister(pAd, RF_R52, (UCHAR)RfReg); + + RfReg = 0x52; + RT30xxWriteRFRegister(pAd, RF_R53, (UCHAR)RfReg); + + RfReg = 0x1B; + RT30xxWriteRFRegister(pAd, RF_R54, (UCHAR)RfReg); + } + + if (value & (1<<15)) + { + /* TX1: 0=internal PA, 1=external PA */ + RT30xxReadRFRegister(pAd, RF_R34, (PUCHAR)&RfReg); + RfReg |= (0x1 << 3); /* tx1_lowgain=20db attenuation */ + RT30xxWriteRFRegister(pAd, RF_R34, (UCHAR)RfReg); + + RfReg = 0x52; + RT30xxWriteRFRegister(pAd, RF_R42, (UCHAR)RfReg); + + RT30xxReadRFRegister(pAd, RF_R50, (PUCHAR)&RfReg); + RfReg |= (0x7<<3); + RT30xxWriteRFRegister(pAd, RF_R50, (UCHAR)RfReg); + + RfReg = 0x52; + RT30xxWriteRFRegister(pAd, RF_R55, (UCHAR)RfReg); + + RfReg = 0xC0; + RT30xxWriteRFRegister(pAd, RF_R56, (UCHAR)RfReg); + + RfReg = 0x49; + RT30xxWriteRFRegister(pAd, RF_R57, (UCHAR)RfReg); + + RfReg = 0xC0; + RT30xxWriteRFRegister(pAd, RF_R58, (UCHAR)RfReg); + } + else + { + RT30xxReadRFRegister(pAd, RF_R34, (PUCHAR)&RfReg); + RfReg &= ~(0x1 << 3); + RT30xxWriteRFRegister(pAd, RF_R34, (UCHAR)RfReg); + + RfReg = 0x5B; + RT30xxWriteRFRegister(pAd, RF_R42, (UCHAR)RfReg); + + RT30xxReadRFRegister(pAd, RF_R50, (PUCHAR)&RfReg); + RfReg &= ~(0x7<<3); + RfReg |= (0x5<<3); + RT30xxWriteRFRegister(pAd, RF_R50, (UCHAR)RfReg); + + RfReg = 0x7F; + RT30xxWriteRFRegister(pAd, RF_R55, (UCHAR)RfReg); + + RfReg = 0x00; + RT30xxWriteRFRegister(pAd, RF_R56, (UCHAR)RfReg); + + RfReg = 0x52; + RT30xxWriteRFRegister(pAd, RF_R57, (UCHAR)RfReg); + + RfReg = 0x1B; + RT30xxWriteRFRegister(pAd, RF_R58, (UCHAR)RfReg); + } + } +} + + +#ifdef GREENAP_SUPPORT +extern REG_PAIR RT305x_RFRegTable[]; + +VOID RT3352_EnableAPMIMOPS( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN ReduceCorePower) +{ + UCHAR BBPR3 = 0,BBPR1 = 0; + ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A + UCHAR BBPR4=0; + + UCHAR CentralChannel; + //UINT32 Value=0; + +#ifdef RT305x + UCHAR RFValue=0; + + RT30xxReadRFRegister(pAd, RF_R01, &RFValue); + RFValue &= 0x03; //clear bit[7~2] + RFValue |= 0x3C; // default 2Tx 2Rx + // turn off tx1 + RFValue &= ~(0x1 << 5); + // turn off rx1 + RFValue &= ~(0x1 << 4); + // Turn off unused PA or LNA when only 1T or 1R +#endif // RT305x // + + 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 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPR4); + BBPR4 &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPR4); + /* RF Bandwidth related registers would be set in AsicSwitchChannel() */ + pAd->CommonCfg.BBPCurrentBW = BW_20; + if (pAd->Antenna.field.RxPath>1||pAd->Antenna.field.TxPath>1) + { + //TX Stream + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1); + //Rx Stream + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); + + + BBPR3 &= (~0x18); + BBPR1 &= (~0x18); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1); + +#ifdef RT3352 + /* + For power saving purpose, Gary set BBP_R3[7:6]=11 to save more power + and he also rewrote the description about BBP_R3 to point out the + WiFi driver should modify BBP_R3[5] based on Low/High frequency + channel.(not a fixed value). + */ + BBPR3 |= 0xe0; //bit 6 & 7, i.e. Use 5-bit ADC for Acquisition +#endif // RT3352 // + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + +#ifdef RT305x + RT30xxWriteRFRegister(pAd, RF_R01, RFValue); +#endif // RT305x // + } + AsicSwitchChannel(pAd, CentralChannel, FALSE); + + DBGPRINT(RT_DEBUG_INFO, ("EnableAPMIMOPS, 305x/28xx changes the # of antenna to 1\n")); +} + + +VOID RT3352_DisableAPMIMOPS( + IN PRTMP_ADAPTER pAd) +{ + UCHAR BBPR3=0,BBPR1=0; + ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A + + UCHAR CentralChannel; + UINT32 Value=0; + +#ifdef RT305x + UCHAR RFValue=0; + + RT30xxReadRFRegister(pAd, RF_R01, &RFValue); + RFValue &= 0x03; //clear bit[7~2] + RFValue |= 0x3C; // default 2Tx 2Rx +#endif // RT305x // + + 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)) + { + 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; + + // 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, &Value); + Value &= (~0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); + } + else if ((pAd->CommonCfg.Channel > 2) && (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_BELOW)) + { + 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, &Value); + Value |= (0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); + } + CentralChannel = pAd->CommonCfg.CentralChannel; + + /* Set BBP registers to BW40 */ + 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); + /* RF Bandwidth related registers would be set in AsicSwitchChannel() */ + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, CentralChannel, FALSE); + } + //Rx Stream + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1); + //Tx Stream + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); + BBPR3 &= (~0x18); + + //RX Stream + if(pAd->Antenna.field.RxPath == 3) + { + BBPR3 |= (0x10); + } + else if(pAd->Antenna.field.RxPath == 2) + { + BBPR3 |= (0x8); + } + else if(pAd->Antenna.field.RxPath == 1) + { + BBPR3 |= (0x0); + } + + //Tx Stream + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->Antenna.field.TxPath == 2)) + { + BBPR1 &= (~0x18); + BBPR1 |= 0x10; + } + else + { + BBPR1 &= (~0x18); + } + +#ifdef RT3352 + /* + For power saving purpose, Gary set BBP_R3[7:6]=11 to save more power + and he also rewrote the description about BBP_R3 to point out the + WiFi driver should modify BBP_R3[5] based on Low/High frequency + channel.(not a fixed value). + */ + BBPR3 &= (~0xe0); //bit 6 & 7, i.e. Use 5-bit ADC for Acquisition +#endif // RT3352 // + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1); + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + +#ifdef RT305x + RT30xxWriteRFRegister(pAd, RF_R01, RFValue); +#endif // RT305x // + + DBGPRINT(RT_DEBUG_INFO, ("DisableAPMIMOPS, 305x/28xx reserve only one antenna\n")); +} +#endif // GREENAP_SUPPORT // + + +VOID RT3352_RxSensitivityTuning( + IN PRTMP_ADAPTER pAd) +{ + UCHAR R66; + + + R66 = 0x26 + GET_LNA_GAIN(pAd); +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { +#ifdef RTMP_RBUS_SUPPORT + // TODO: we need to add MACVersion Check here!!!! +#if defined(RT3352) + if (IS_RT3352(pAd)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, 0x0); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, 0x20); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); + } + else +#endif // defined(RT3352) // +#endif // RTMP_RBUS_SUPPORT // + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); + } + else +#endif // RALINK_ATE // + AsicBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + + DBGPRINT(RT_DEBUG_TRACE,("turn off R17 tuning, restore to 0x%02x\n", R66)); +} + + +#ifdef CONFIG_STA_SUPPORT +UCHAR RT3352_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 + if (IS_RT3352(pAd)) + { + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + R66 = (lanGain * 2 +0x1C); + else + R66 = (lanGain * 2 +0x24); + } + else + { + 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) + AsicBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + + return R66; +} +#endif // CONFIG_STA_SUPPORT // + + +VOID RT3352_ChipBBPAdjust( + IN RTMP_ADAPTER *pAd) +{ + UINT32 Value; + UCHAR byteValue = 0; + UCHAR R66; + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && + (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + /*(pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == 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); + + if (pAd->CommonCfg.Channel > 14) + { // request by Gary 20070208 for middle and long range A Band + AsicBBPWriteWithRxChain(pAd, BBP_R66, 0x48, RX_CHAIN_ALL); + } + else + { // request by Gary 20070208 for middle and long range G Band + if (IS_RT3352(pAd)) + { + /* Gary 20100714: Update BBP R66 programming: */ + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + R66 = GET_LNA_GAIN(pAd)*2 + 0x1C; + else + R66 = GET_LNA_GAIN(pAd)*2 + 0x24; + + AsicBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + } + } + // + 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); + } + 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, ("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.AddHTInfo.AddHtInfo.ExtChanOffset == 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); + + if (pAd->CommonCfg.Channel > 14) + { // request by Gary 20070208 for middle and long range A Band + AsicBBPWriteWithRxChain(pAd, BBP_R66, 0x48, RX_CHAIN_ALL); + } + else + { // request by Gary 20070208 for middle and long range G band + if (IS_RT3352(pAd)) + { + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + R66 = GET_LNA_GAIN(pAd)*2 + 0x1C; + else + R66 = GET_LNA_GAIN(pAd)*2 + 0x24; + AsicBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + } + } + + + 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); + } + 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, ("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); + + // 20 MHz bandwidth + if (pAd->CommonCfg.Channel > 14) + { // request by Gary 20070208 + AsicBBPWriteWithRxChain(pAd, BBP_R66, 0x40, RX_CHAIN_ALL); + } + else + { // request by Gary 20070208 + //AsicBBPWriteWithRxChain(pAd, BBP_R66, 0x30, RX_CHAIN_ALL); + // request by Brian 20070306 + if (IS_RT3352(pAd)) + { + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + R66 = GET_LNA_GAIN(pAd)*2 + 0x1C; + else + R66 = GET_LNA_GAIN(pAd)*2 + 0x24; + AsicBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + } + } + + 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); + } + 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); + } + +#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 // + } + + if (pAd->CommonCfg.Channel > 14) + { // request by Gary 20070208 for middle and long range A Band + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, 0x1D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, 0x1D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, 0x1D); + //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x1D); + } + else + { // request by Gary 20070208 for middle and long range G band + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, 0x2D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, 0x2D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, 0x2D); + //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x2D); + } +} + + +VOID RT3352_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 + + /* + 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, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel)); + } + +#ifdef RT305x + // The RF programming sequence is difference between 3xxx and 2xxx + if (((pAd->MACVersion == 0x28720200) +#ifdef RT3352 + || IS_RT3352(pAd) +#endif // RT3352 // + ) && + ((pAd->RfIcType == RFIC_3320) || (pAd->RfIcType == RFIC_3322) || + (pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3022))) + { + /* modify by WY for Read RF Reg. error */ + + for (index = 0; index < NUM_OF_3020_CHNL; index++) + { + if (Channel == FreqItems3020[index].Channel) + { +#if defined (RT3352) + if (IS_RT3352(pAd)) + { + // Programming channel parameters + Value = (*((volatile u32 *)(RALINK_SYSCTL_BASE + 0x10))); + + if(Value & (1<<20)) { //Xtal=40M + RT30xxWriteRFRegister(pAd, RF_R08, FreqItems3020[index].N); + RT30xxWriteRFRegister(pAd, RF_R09, FreqItems3020[index].K); + }else { + RT30xxWriteRFRegister(pAd, RF_R08, FreqItems3020_Xtal20M[index].N); + RT30xxWriteRFRegister(pAd, RF_R09, FreqItems3020_Xtal20M[index].K); + } + + RFValue = 0x42; + RT30xxWriteRFRegister(pAd, RF_R11, (UCHAR)RFValue); + + RFValue = 0x1C; + RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue); + + RFValue = 0x00; + RT30xxWriteRFRegister(pAd, RF_R13, (UCHAR)RFValue); + RT30xxReadRFRegister(pAd, RF_R30, (PUCHAR)&RFValue); + if ((pAd->CommonCfg.BBPCurrentBW == BW_40) +#ifdef RTMP_RBUS_SUPPORT +#ifdef COC_SUPPORT + && (pAd->CoC_sleep == 0) +#endif // COC_SUPPORT // +#endif // RTMP_RBUS_SUPPORT // + ) + RFValue |= 0x03; // 40MBW tx_h20M=1,rx_h20M=1 + else + RFValue &= ~(0x03); // 20MBW tx_h20M=0,rx_h20M=0 + RT30xxWriteRFRegister(pAd, RF_R30, (UCHAR)RFValue); + + + for (i = 0; i < MAX_NUM_OF_CHANNELS; i++) { + if (Channel != pAd->TxPower[i].Channel) + continue; + + RT30xxWriteRFRegister(pAd, RF_R47, pAd->TxPower[i].Power); + RT30xxWriteRFRegister(pAd, RF_R48, pAd->TxPower[i].Power2); + break; + } + + RT30xxReadRFRegister(pAd, RF_R03, (PUCHAR)&RFValue); + RFValue = RFValue | 0x80; // bit 7=vcocal_en + RT30xxWriteRFRegister(pAd, RF_R03, (UCHAR)RFValue); + + RTMPusecDelay(2000); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, (PUCHAR)&RFValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R49, RFValue & 0xfe); // clear update flag + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, (PUCHAR)&RFValue); + + // latch channel for future usage. + pAd->LatchRfRegs.Channel = Channel; + } +#endif // RT3352 // + +#ifdef RT3352 + if (IS_RT3352(pAd)) + RFValue = 0; /* RF_R24 is reserved bits */ +#endif // RT3352 // + + if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40) +#ifdef GREENAP_SUPPORT + && (pAd->ApCfg.bGreenAPActive == 0) +#endif // GREENAP_SUPPORT // + ) + { +#ifdef RT3352 + if (IS_RT3352(pAd)) + RFValue = 0; /* RF_R24 is reserved bits */ +#endif // RT3352 // + } + RT30xxWriteRFRegister(pAd, RF_R24, RFValue); + + // Rx filter + if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40) +#ifdef GREENAP_SUPPORT + && (pAd->ApCfg.bGreenAPActive == 0) +#endif // GREENAP_SUPPORT // + ) + { +#ifdef RT3352 + if (IS_RT3352(pAd)) + RT30xxWriteRFRegister(pAd, RF_R31, 0x80); //FIXME: I don't know the RF_R31 for BW40 case +#endif // RT3352 // + } + else + { +#ifdef RT3352 + if (IS_RT3352(pAd)) + RT30xxWriteRFRegister(pAd, RF_R31, 0x80); +#endif // RT3352 // + } + +#if defined (RT3352) + if (IS_RT3352(pAd)) + { + // Enable RF tuning, this must be in the last, RF_R03=RF_R07 (RT30xx) + RT30xxReadRFRegister(pAd, RF_R03, (PUCHAR)&RFValue); + RFValue = RFValue | 0x80; // bit 7=vcocal_en + RT30xxWriteRFRegister(pAd, RF_R03, (UCHAR)RFValue); + + RTMPusecDelay(2000); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, (PUCHAR)&RFValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R49, RFValue & 0xfe); // clear update flag + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, (PUCHAR)&RFValue); + + // Antenna + RT30xxReadRFRegister(pAd, RF_R01, (PUCHAR)&RFValue); + RFValue &= 0x03; //clear bit[7~2] + RFValue |= 0x3C; // default 2Tx 2Rx + + if (pAd->Antenna.field.TxPath == 1) + RFValue &= ~(0x1 << 5); + + if (pAd->Antenna.field.RxPath == 1) + RFValue &= ~(0x1 << 4); + + RT30xxWriteRFRegister(pAd, RF_R01, (UCHAR)RFValue); + } +#endif // RT3352 // + + // latch channel for future usage. + pAd->LatchRfRegs.Channel = Channel; + + break; + } + } + +#if defined (RT3352) + Value = (*((volatile u32 *)(RALINK_SYSCTL_BASE + 0x10))); + + if(Value & (1<<20)) { //Xtal=40M + DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", + Channel, + pAd->RfIcType, + TxPwer, + TxPwer2, + pAd->Antenna.field.TxPath, + FreqItems3020[index].N, + FreqItems3020[index].K, + FreqItems3020[index].R)); + }else { + DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", + Channel, + pAd->RfIcType, + TxPwer, + TxPwer2, + pAd->Antenna.field.TxPath, + FreqItems3020_Xtal20M[index].N, + FreqItems3020_Xtal20M[index].K, + FreqItems3020_Xtal20M[index].R)); + } +#endif // RT3352 // + } + else +#endif // RT305x // + { + switch (pAd->RfIcType) + { + default: + DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d : unknown RFIC=%d\n", + Channel, pAd->RfIcType)); + break; + } + } + + // Change BBP setting during siwtch from a->g, g->a + if (Channel <= 14) + { + ULONG TxPinCfg = 0x00050F0A;//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))); +#if defined(RT3352) + if (IS_RT3352(pAd)) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x38); // Gary 2010-07-21 +#endif // RT3352 // + + // Rx High power VGA offset for LNA select + { + if (pAd->NicConfig2.field.ExternalLNAForG) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + } + +#if defined (RT3352) + if (IS_RT3352(pAd)) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R83, 0x6a); + } +#endif // RT3352 // + + // 5G band selection PIN, bit1 and bit2 are complement + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x04); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + { + // 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); + + RtmpUpdateFilterCoefficientControl(pAd, Channel); + } + else + { + ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505 + UINT8 bbpValue; + + 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))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);//(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue. + + /* Set the BBP_R82 value here */ + bbpValue = 0xF2; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, bbpValue); + + // Rx High power VGA offset for LNA select + if (pAd->NicConfig2.field.ExternalLNAForA) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + // 5G band selection PIN, bit1 and bit2 are complement + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x02); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + // Turn off unused PA or LNA when only 1T or 1R + { + // 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); + } + + // R66 should be set according to Channel and use 20MHz when scanning + //AsicBBPWriteWithRxChain(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)), 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); +} + + +VOID RT3352_RTMPSetAGCInitValue( + IN PRTMP_ADAPTER pAd, + IN UCHAR BandWidth) +{ + UCHAR R66 = 0x30; + CHAR lanGain = GET_LNA_GAIN(pAd); + + if (pAd->LatchRfRegs.Channel <= 14) + { // BG band + { + R66 = 0x2E + lanGain; +#if defined(RT3352) + if (IS_RT3352(pAd)) + { + /* Gary 20100714: Update BBP R66 programming: */ + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + R66 = (lanGain * 2 + 0x1C); + else + R66 = (lanGain * 2 + 0x24); + } +#endif /* RT3352 */ + AsicBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + } + } + else + { //A band + { + if (BandWidth == BW_20) + R66 = (UCHAR)(0x32 + (lanGain * 5) / 3); +#ifdef DOT11_N_SUPPORT + else + R66 = (UCHAR)(0x3A + (lanGain * 5) / 3); +#endif // DOT11_N_SUPPORT // + AsicBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + } + } + +} + +#ifdef RTMP_INTERNAL_TX_ALC +VOID RT3352_InitDesiredTSSITable( + IN PRTMP_ADAPTER pAd) +{ + UCHAR TSSIBase = 0; /* The TSSI over OFDM 54Mbps */ + USHORT TSSIStepOver2dot4G = 0; /* The TSSI value/step (0.5 dB/unit) */ + UCHAR RFValue = 0; + BBP_R49_STRUC BbpR49; + ULONG i = 0; + USHORT TxPower = 0, TxPowerOFDM54 = 0, temp = 0; + + BbpR49.byte = 0; + + if (pAd->TxPowerCtrl.bInternalTxALC == FALSE) + { + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("---> %s\n", __FUNCTION__)); + + RT28xx_EEPROM_READ16(pAd, EEPROM_TSSI_OVER_OFDM_54, temp); + TSSIBase = (temp & 0x001F); + + RT28xx_EEPROM_READ16(pAd, (EEPROM_TSSI_STEP_OVER_2DOT4G - 1), TSSIStepOver2dot4G); + TSSIStepOver2dot4G = (0x000F & (TSSIStepOver2dot4G >> 8)); + + RT28xx_EEPROM_READ16(pAd, (EEPROM_OFDM_MCS6_MCS7 - 1), TxPowerOFDM54); + TxPowerOFDM54 = (0x000F & (TxPowerOFDM54 >> 8)); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: TSSIBase = %d, TSSIStepOver2dot4G = %d, TxPowerOFDM54 = %d\n", + __FUNCTION__, + TSSIBase, + TSSIStepOver2dot4G, + TxPowerOFDM54)); + + /* The desired TSSI over CCK */ + RT28xx_EEPROM_READ16(pAd, EEPROM_CCK_MCS0_MCS1, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xDE = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverCCK[MCS_0] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2)) + 6); + desiredTSSIOverCCK[MCS_1] = desiredTSSIOverCCK[MCS_0]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_CCK_MCS2_MCS3 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xDF = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverCCK[MCS_2] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2)) + 6); + desiredTSSIOverCCK[MCS_3] = desiredTSSIOverCCK[MCS_2]; + + /* Boundary verification: the desired TSSI value */ + for (i = 0; i < 4; i++) /* CCK: MCS 0 ~ MCS 3 */ + { + if (desiredTSSIOverCCK[i] < 0x00) + { + desiredTSSIOverCCK[i] = 0x00; + } + else if (desiredTSSIOverCCK[i] > 0x1F) + { + desiredTSSIOverCCK[i] = 0x1F; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverCCK[0] = %d, desiredTSSIOverCCK[1] = %d, desiredTSSIOverCCK[2] = %d, desiredTSSIOverCCK[3] = %d\n", + __FUNCTION__, + desiredTSSIOverCCK[0], + desiredTSSIOverCCK[1], + desiredTSSIOverCCK[2], + desiredTSSIOverCCK[3])); + + /* The desired TSSI over OFDM */ + RT28xx_EEPROM_READ16(pAd, EEPROM_OFDM_MCS0_MCS1, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE0 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverOFDM[MCS_0] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverOFDM[MCS_1] = desiredTSSIOverOFDM[MCS_0]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_OFDM_MCS2_MCS3 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE1 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverOFDM[MCS_2] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverOFDM[MCS_3] = desiredTSSIOverOFDM[MCS_2]; + RT28xx_EEPROM_READ16(pAd, EEPROM_OFDM_MCS4_MCS5, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE2 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverOFDM[MCS_4] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverOFDM[MCS_5] = desiredTSSIOverOFDM[MCS_4]; + desiredTSSIOverOFDM[MCS_6] = TSSIBase; + desiredTSSIOverOFDM[MCS_7] = TSSIBase; + + /* Boundary verification: the desired TSSI value */ + for (i = 0; i < 8; i++) /* OFDM: MCS 0 ~ MCS 7 */ + { + if (desiredTSSIOverOFDM[i] < 0x00) + { + desiredTSSIOverOFDM[i] = 0x00; + } + else if (desiredTSSIOverOFDM[i] > 0x1F) + { + desiredTSSIOverOFDM[i] = 0x1F; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverOFDM[0] = %d, desiredTSSIOverOFDM[1] = %d, desiredTSSIOverOFDM[2] = %d, desiredTSSIOverOFDM[3] = %d\n", + __FUNCTION__, + desiredTSSIOverOFDM[0], + desiredTSSIOverOFDM[1], + desiredTSSIOverOFDM[2], + desiredTSSIOverOFDM[3])); + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverOFDM[4] = %d, desiredTSSIOverOFDM[5] = %d, desiredTSSIOverOFDM[6] = %d, desiredTSSIOverOFDM[7] = %d\n", + __FUNCTION__, + desiredTSSIOverOFDM[4], + desiredTSSIOverOFDM[5], + desiredTSSIOverOFDM[6], + desiredTSSIOverOFDM[7])); + + /* The desired TSSI over HT */ + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_MCS0_MCS1, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE4 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHT[MCS_0] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_1] = desiredTSSIOverHT[MCS_0]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_MCS2_MCS3 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE5 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHT[MCS_2] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_3] = desiredTSSIOverHT[MCS_2]; + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_MCS4_MCS5, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE6 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHT[MCS_4] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_5] = desiredTSSIOverHT[MCS_4]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_MCS6_MCS7 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE7 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHT[MCS_6] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_7] = desiredTSSIOverHT[MCS_6] - 1; + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_MCS8_MCS9, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_HT_MCS9_MCS9(0xE8) = 0x%X\n", TxPower)); + desiredTSSIOverHT[MCS_8] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_9] = desiredTSSIOverHT[MCS_8]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_MCS10_MCS11 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_HT_MCS10_MCS11(0xE9) = 0x%X\n", TxPower)); + desiredTSSIOverHT[MCS_10] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_11] = desiredTSSIOverHT[MCS_10]; + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_MCS12_MCS13, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_HT_MCS12_MCS13(0xEA) = 0x%X\n", TxPower)); + desiredTSSIOverHT[MCS_12] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_13] = desiredTSSIOverHT[MCS_12]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_MCS14_MCS15 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_HT_MCS14_MCS15(0xEB) = 0x%X\n", TxPower)); + desiredTSSIOverHT[MCS_14] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_15] = desiredTSSIOverHT[MCS_14] - 1; + + /* Boundary verification: the desired TSSI value */ + for (i = 0; i < 16; i++) /* HT: MCS 0 ~ MCS 15 */ + { + if (desiredTSSIOverHT[i] < 0x00) + { + desiredTSSIOverHT[i] = 0x00; + } + else if (desiredTSSIOverHT[i] > 0x1F) + { + desiredTSSIOverHT[i] = 0x1F; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHT[0] = %d, desiredTSSIOverHT[1] = %d, desiredTSSIOverHT[2] = %d, desiredTSSIOverHT[3] = %d\n", + __FUNCTION__, + desiredTSSIOverHT[0], + desiredTSSIOverHT[1], + desiredTSSIOverHT[2], + desiredTSSIOverHT[3])); + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHT[4] = %d, desiredTSSIOverHT[5] = %d, desiredTSSIOverHT[6] = %d, desiredTSSIOverHT[7] = %d\n", + __FUNCTION__, + desiredTSSIOverHT[4], + desiredTSSIOverHT[5], + desiredTSSIOverHT[6], + desiredTSSIOverHT[7])); + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHT[8] = %d, desiredTSSIOverHT[9] = %d, desiredTSSIOverHT[10] = %d, desiredTSSIOverHT[11] = %d\n", + __FUNCTION__, + desiredTSSIOverHT[8], + desiredTSSIOverHT[9], + desiredTSSIOverHT[10], + desiredTSSIOverHT[11])); + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHT[12] = %d, desiredTSSIOverHT[13] = %d, desiredTSSIOverHT[14] = %d, desiredTSSIOverHT[15] = %d\n", + __FUNCTION__, + desiredTSSIOverHT[12], + desiredTSSIOverHT[13], + desiredTSSIOverHT[14], + desiredTSSIOverHT[15])); + + /* The desired TSSI over HT using STBC */ + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_USING_STBC_MCS0_MCS1, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xEC = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHTUsingSTBC[MCS_0] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHTUsingSTBC[MCS_1] = desiredTSSIOverHTUsingSTBC[MCS_0]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_USING_STBC_MCS2_MCS3 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xED = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHTUsingSTBC[MCS_2] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHTUsingSTBC[MCS_3] = desiredTSSIOverHTUsingSTBC[MCS_2]; + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_USING_STBC_MCS4_MCS5, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xEE = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHTUsingSTBC[MCS_4] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHTUsingSTBC[MCS_5] = desiredTSSIOverHTUsingSTBC[MCS_4]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_USING_STBC_MCS6_MCS7 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xEF = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHTUsingSTBC[MCS_6] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHTUsingSTBC[MCS_7] = desiredTSSIOverHTUsingSTBC[MCS_6]; + + /* Boundary verification: the desired TSSI value */ + for (i = 0; i < 8; i++) /* HT using STBC: MCS 0 ~ MCS 7 */ + { + if (desiredTSSIOverHTUsingSTBC[i] < 0x00) + { + desiredTSSIOverHTUsingSTBC[i] = 0x00; + } + else if (desiredTSSIOverHTUsingSTBC[i] > 0x1F) + { + desiredTSSIOverHTUsingSTBC[i] = 0x1F; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHTUsingSTBC[0] = %d, desiredTSSIOverHTUsingSTBC[1] = %d, desiredTSSIOverHTUsingSTBC[2] = %d, desiredTSSIOverHTUsingSTBC[3] = %d\n", + __FUNCTION__, + desiredTSSIOverHTUsingSTBC[0], + desiredTSSIOverHTUsingSTBC[1], + desiredTSSIOverHTUsingSTBC[2], + desiredTSSIOverHTUsingSTBC[3])); + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHTUsingSTBC[4] = %d, desiredTSSIOverHTUsingSTBC[5] = %d, desiredTSSIOverHTUsingSTBC[6] = %d, desiredTSSIOverHTUsingSTBC[7] = %d\n", + __FUNCTION__, + desiredTSSIOverHTUsingSTBC[4], + desiredTSSIOverHTUsingSTBC[5], + desiredTSSIOverHTUsingSTBC[6], + desiredTSSIOverHTUsingSTBC[7])); + + /* + * | RF_R28[5:4] | RF_R27[4] | RF_R27[5] + * | Adc5b_sel | Rf_tssi_sel | rf_tssi_en + *-----------------------+---------------------+---------------+------------- + * Internal TSSI0 | 00 | 1 | 1 + * Internal TSSI1 | 10 | 0 | 1 + * External TSSI0 | 00 | 0 | 0 + * External TSSI1 | 10 | 1 | 0 + * + */ + + /* Internal TSSI0 */ + /* RFValue = (0x3 | 0x0<<2 | 0x1<<4 | 0x1 << 5); // tssi_gain0:x9, tssi_atten0:-17db, rf_tssi_sel=1, rf_tssi_en=1 */ + /* External TSSI0 */ + /* RFValue = (0x3 | 0x0<<2 | 0x0<<4 | 0x1 << 5); // tssi_gain0:x9, tssi_atten0:-17db, rf_tssi_sel=0, rf_tssi_en=1 */ + RFValue = (0x3 | 0x0<<2 | 0x3<<4);/* tssi_gain0:x9, tssi_atten0:-17db, rf_tssi_sel=0, rf_tssi_en=1 */ + /* Internal TSSI1 */ + /* RFValue = (0x3 | 0x0<<2 | 0x0<<4 | 0x1 << 5); // tssi_gain0:x9, tssi_atten0:-17db, rf_tssi_sel=0, rf_tssi_en=1 */ + RT30xxWriteRFRegister(pAd, RF_R27, RFValue); + + /* Internal TSSI0 */ + /* RFValue = (0x3 | 0x0<<2 | 0x2 << 4); // tssi_gain1:x9, tssi_atten1:-17db, Adc5b_sel=10 (Internal TSSI1) */ + RFValue = (0x3 | 0x0<<2);/* tssi_gain1:x9, tssi_atten1:-17db, Adc5b_sel=10 (Internal TSSI1) */ + /* Internal TSSI1 */ + /* RFValue = (0x3 | 0x0<<2 | 0x2 << 4); // tssi_gain1:x9, tssi_atten1:-17db, Adc5b_sel=10 (Internal TSSI1) */ + RT30xxWriteRFRegister(pAd, RF_R28, RFValue); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49.byte); + BbpR49.field.adc5_in_sel = 1; /* PSI */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R49, BbpR49.byte); + + DBGPRINT(RT_DEBUG_TRACE, ("<--- %s\n", __FUNCTION__)); +} + +/* + ========================================================================== + Description: + Get the desired TSSI based on the latest packet + + Arguments: + pAd + + Return Value: + The desired TSSI + ========================================================================== + */ +UCHAR RT3352_GetDesiredTSSI( + IN PRTMP_ADAPTER pAd) +{ + PHTTRANSMIT_SETTING pLatestTxHTSetting = (PHTTRANSMIT_SETTING)(&pAd->LastTxRate); + UCHAR desiredTSSI = 0; + UCHAR MCS = 0; +#ifdef CONFIG_AP_SUPPORT + UCHAR BBPValue = 0; + UCHAR BBPRate = 0; + UCHAR BBPMode = 0; +#endif /* CONFIG_AP_SUPPORT */ + + MCS = (UCHAR)(pLatestTxHTSetting->field.MCS); + + if (pLatestTxHTSetting->field.MODE == MODE_CCK) + { + if (/* (MCS < 0) || */(MCS > 3)) /* boundary verification */ + { + DBGPRINT_ERR(("%s: incorrect MCS: MCS = %d\n", __FUNCTION__, MCS)); + MCS = 0; + } + + desiredTSSI = desiredTSSIOverCCK[MCS]; + } + else if (pLatestTxHTSetting->field.MODE == MODE_OFDM) + { + if (/* (MCS < 0) || */(MCS > 7)) /* boundary verification */ + { + DBGPRINT_ERR(("%s: incorrect MCS: MCS = %d\n", __FUNCTION__, MCS)); + MCS = 0; + } + + desiredTSSI = desiredTSSIOverOFDM[MCS]; + } + else if ((pLatestTxHTSetting->field.MODE == MODE_HTMIX) || (pLatestTxHTSetting->field.MODE == MODE_HTGREENFIELD)) + { + if (/* (MCS < 0) || */(MCS > 15)) /* boundary verification */ + { + DBGPRINT_ERR(("%s: incorrect MCS: MCS = %d\n", __FUNCTION__, MCS)); + MCS = 0; + } + + if (pLatestTxHTSetting->field.STBC == 1) + { + desiredTSSI = desiredTSSIOverHT[MCS]; + } + else + { + desiredTSSI = desiredTSSIOverHTUsingSTBC[MCS]; + } + + /* For HT BW40 MCS 7 with/without STBC configuration, the desired TSSI value should subtract one from the formula */ + if ((pLatestTxHTSetting->field.BW == BW_40) && (MCS == MCS_7)) + { + desiredTSSI -= 1; + } + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* For beacon power */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R2, &BBPValue); + BBPMode = ((BBPValue >> 6) & (0x03)); + + if (BBPMode == 0x00) /* CCK */ + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R10, &BBPValue); + BBPRate = (BBPValue & 0x03); + + if (BBPRate == 0x00) /* MCS */ + { + MCS = 0; + desiredTSSI = desiredTSSIOverCCK[MCS]; + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + + DBGPRINT(RT_DEBUG_INFO, ("%s: desiredTSSI = %d, Latest Tx HT setting: MODE = %d, MCS = %d, STBC = %d\n", + __FUNCTION__, + desiredTSSI, + pLatestTxHTSetting->field.MODE, + pLatestTxHTSetting->field.MCS, + pLatestTxHTSetting->field.STBC)); + + DBGPRINT(RT_DEBUG_INFO, ("<--- %s\n", __FUNCTION__)); + + return desiredTSSI; +} + +VOID RT3352_AsicTxAlcGetAutoAgcOffset( + IN PRTMP_ADAPTER pAd, + IN PCHAR pDeltaPwr, + IN PCHAR pTotalDeltaPwr, + IN PCHAR pAgcCompensate, + IN PCHAR pDeltaPowerByBbpR1) +{ + const TX_POWER_TUNING_ENTRY_STRUCT *TxPowerTuningTable = pAd->chipCap.TxPowerTuningTable_2G; + PTX_POWER_TUNING_ENTRY_STRUCT pTxPowerTuningEntry = NULL, pTxPowerTuningEntry2 = NULL; + static UCHAR LastChannel = 0; + BBP_R49_STRUC BbpR49; + UCHAR RFValue = 0; + UCHAR RFValue2 = 0; + UCHAR TmpValue = 0; + UCHAR TssiChannel = 0; + CHAR desiredTSSI = 0; + CHAR currentTSSI = 0; + CHAR room = 0; + CHAR TotalDeltaPower = 0; /* (non-positive number) including the transmit power controlled by the MAC and the BBP R1 */ + CHAR TuningTableIndex = 0; + CHAR TuningTableIndex2 = 0; + CHAR AntennaDeltaPwr = 0; + +#ifdef DOT11_N_SUPPORT + TssiChannel = pAd->CommonCfg.CentralChannel; +#else + TssiChannel = pAd->CommonCfg.Channel; +#endif /* DOT11_N_SUPPORT */ + + BbpR49.byte = 0; + + /* Locate the Internal Tx ALC tuning entry */ + if (pAd->TxPowerCtrl.bInternalTxALC == TRUE) + { + if ((pAd->Mlme.OneSecPeriodicRound % 4 == 0) && (*pDeltaPowerByBbpR1 == 0/* ??? */)) + { + desiredTSSI = RT3352_GetDesiredTSSI(pAd); + + if (desiredTSSI == -1) + { + goto LabelFail; + } + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49.byte); + currentTSSI = BbpR49.field.TSSI; + + if (pAd->TxPowerCtrl.bExtendedTssiMode == TRUE) /* Per-channel TSSI */ + { + if ((TssiChannel >= 1) && (TssiChannel <= 14)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: bExtendedTssiMode = %d, original desiredTSSI = %d, CentralChannel = %d, PerChTxPwrOffset = %d\n", + __FUNCTION__, + pAd->TxPowerCtrl.bExtendedTssiMode, + desiredTSSI, + TssiChannel, + pAd->TxPowerCtrl.PerChTxPwrOffset[TssiChannel])); + + desiredTSSI += pAd->TxPowerCtrl.PerChTxPwrOffset[TssiChannel]; + } + } + + if (desiredTSSI < 0x00) + { + desiredTSSI = 0x00; + } + else if (desiredTSSI > 0x1F) + { + desiredTSSI = 0x1F; + } + + if (LastChannel != TssiChannel) + { + DBGPRINT(RT_DEBUG_OFF, ("******************************************\n")); + DBGPRINT(RT_DEBUG_OFF, ("idxTxPowerTable reset to per-channel DAC!\n")); + pAd->TxPowerCtrl.idxTxPowerTable = pAd->TxPower[TssiChannel-1].Power; + DBGPRINT(RT_DEBUG_OFF, ("******************************************\n")); + } + + if ((pAd->chipCap.TxPowerMaxCompenStep == 4) || (pAd->chipCap.TxPowerMaxCompenStep == 8)) + { + pAd->chipCap.TxPowerTableMaxIdx = pAd->TxPower[TssiChannel-1].Power + + pAd->chipCap.TxPowerMaxCompenStep; + + DBGPRINT(RT_DEBUG_TRACE, ("--------------------------------------------\n")); + DBGPRINT(RT_DEBUG_TRACE, ("TxPowerTableMaxIdx = %d\n", pAd->chipCap.TxPowerTableMaxIdx)); + DBGPRINT(RT_DEBUG_TRACE, ("TxPowerMaxCompenStep = %d\n", pAd->chipCap.TxPowerMaxCompenStep)); + + room = (desiredTSSI >> 3); + + if (((desiredTSSI - room) > currentTSSI) && + (pAd->TxPowerCtrl.idxTxPowerTable + < pAd->chipCap.TxPowerTableMaxIdx)) + { + pAd->TxPowerCtrl.idxTxPowerTable++; + } + } + else if (pAd->chipCap.TxPowerMaxCompenStep == 0) + { + /* TxPowerMaxCompenStep == 0 means TSSI range control is disabled. */ + room = (desiredTSSI >> 3); + + if ((desiredTSSI - room) > currentTSSI) + { + pAd->TxPowerCtrl.idxTxPowerTable++; + } + } + else + { + DBGPRINT_ERR(("Wrong TxPowerMaxCompenStep value %u\n", pAd->chipCap.TxPowerMaxCompenStep)); + + return; + } + + if (desiredTSSI < currentTSSI) + { + pAd->TxPowerCtrl.idxTxPowerTable--; + } + + DBGPRINT(RT_DEBUG_TRACE, ("========================================\n")); + DBGPRINT(RT_DEBUG_TRACE, ("Channel-Power = %d\n", pAd->TxPower[TssiChannel-1].Power)); + DBGPRINT(RT_DEBUG_TRACE, ("idxTxPowerTable = %d\n", pAd->TxPowerCtrl.idxTxPowerTable)); + + TuningTableIndex = pAd->TxPowerCtrl.idxTxPowerTable; + + LastChannel = TssiChannel; + + if (TuningTableIndex < LOWERBOUND_TX_POWER_TUNING_ENTRY) + { + TuningTableIndex = LOWERBOUND_TX_POWER_TUNING_ENTRY; + } + + if (TuningTableIndex >= UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd)) + { + TuningTableIndex = UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd); + } + + /* Valid pAd->TxPowerCtrl.idxTxPowerTable: -30 ~ 61 */ + pTxPowerTuningEntry = &TxPowerTuningTable[TuningTableIndex + TX_POWER_TUNING_ENTRY_OFFSET]; + pAd->TxPowerCtrl.RF_TX_ALC = pTxPowerTuningEntry->RF_TX_ALC; + pAd->TxPowerCtrl.MAC_PowerDelta = pTxPowerTuningEntry->MAC_PowerDelta; + + DBGPRINT(RT_DEBUG_TRACE, ("TuningTableIndex = %d, pAd->TxPowerCtrl.RF_TX_ALC = %d, pAd->TxPowerCtrl.MAC_PowerDelta = %d\n", + TuningTableIndex, pAd->TxPowerCtrl.RF_TX_ALC, pAd->TxPowerCtrl.MAC_PowerDelta)); + + /* Tx power adjustment over RF */ + RFValue = pAd->TxPowerCtrl.RF_TX_ALC; + RT30xxWriteRFRegister(pAd, RF_R47, (UCHAR)RFValue); /* TX0_ALC */ + DBGPRINT(RT_DEBUG_TRACE, ("RF_R47 = 0x%02x ", RFValue)); + + /* Delta Power between Tx0 and Tx1 */ + if ((pAd->TxPower[TssiChannel-1].Power) > (pAd->TxPower[TssiChannel-1].Power2)) + { + AntennaDeltaPwr = ((pAd->TxPower[TssiChannel-1].Power) + - (pAd->TxPower[TssiChannel-1].Power2)); + TuningTableIndex2 = TuningTableIndex - AntennaDeltaPwr; + } + else if ((pAd->TxPower[TssiChannel-1].Power) < (pAd->TxPower[TssiChannel-1].Power2)) + { + AntennaDeltaPwr = ((pAd->TxPower[TssiChannel-1].Power2) + - (pAd->TxPower[TssiChannel-1].Power)); + TuningTableIndex2 = TuningTableIndex + AntennaDeltaPwr; + } + else + { + TuningTableIndex2 = TuningTableIndex; + } + + if (TuningTableIndex2 < LOWERBOUND_TX_POWER_TUNING_ENTRY) + { + TuningTableIndex2 = LOWERBOUND_TX_POWER_TUNING_ENTRY; + } + + if (TuningTableIndex2 >= UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd)) + { + TuningTableIndex2 = UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd); + } + + pTxPowerTuningEntry2 = &RT3352_TxPowerTuningTable[TuningTableIndex2 + TX_POWER_TUNING_ENTRY_OFFSET]; + + RFValue2 = pTxPowerTuningEntry2->RF_TX_ALC; + pAd->TxPowerCtrl.MAC_PowerDelta2 = pTxPowerTuningEntry2->MAC_PowerDelta; + + DBGPRINT(RT_DEBUG_TRACE, ("Channel DAC0 = 0x%02x\n", (pAd->TxPower[TssiChannel-1].Power))); + DBGPRINT(RT_DEBUG_TRACE, ("Channel DAC1 = 0x%02x\n", (pAd->TxPower[TssiChannel-1].Power2))); + DBGPRINT(RT_DEBUG_TRACE, ("AntennaDeltaPwr = 0x%02x\n", AntennaDeltaPwr)); + DBGPRINT(RT_DEBUG_TRACE, ("TuningTableIndex = %d\n", TuningTableIndex)); + DBGPRINT(RT_DEBUG_TRACE, ("TuningTableIndex2 = %d\n", TuningTableIndex2)); + DBGPRINT(RT_DEBUG_TRACE, ("RFValue = %u\n", RFValue)); + DBGPRINT(RT_DEBUG_TRACE, ("RFValue2 = %u\n", RFValue2)); + + RT30xxWriteRFRegister(pAd, RF_R48, RFValue2); /* TX1_ALC */ + DBGPRINT(RT_DEBUG_TRACE, ("RF_R48 = 0x%02x\n", RFValue2)); + + /* Tx power adjustment over MAC */ + TotalDeltaPower = pAd->TxPowerCtrl.MAC_PowerDelta; + pAd->TxPowerCtrl.TotalDeltaPower2 = pAd->TxPowerCtrl.MAC_PowerDelta2; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSI = %d, currentTSSI = %d, TuningTableIndex = %d, {RF_TX_ALC = %d, MAC_PowerDelta = %d}\n", + __FUNCTION__, + desiredTSSI, + currentTSSI, + TuningTableIndex, + pTxPowerTuningEntry->RF_TX_ALC, + pTxPowerTuningEntry->MAC_PowerDelta)); + } + } + +LabelFail: + + *pTotalDeltaPwr = TotalDeltaPower; +} + +/* The desired TSSI over CCK */ +extern CHAR desiredTSSIOverCCK[4]; + +/* The desired TSSI over OFDM */ +extern CHAR desiredTSSIOverOFDM[8]; + +/* The desired TSSI over HT */ +extern CHAR desiredTSSIOverHT[16]; + +/* The desired TSSI over HT using STBC */ +extern CHAR desiredTSSIOverHTUsingSTBC[8]; + + +VOID RT3352_AsicInitDesiredTSSITable( + IN PRTMP_ADAPTER pAd) +{ + UCHAR TSSIBase = 0; /* The TSSI over OFDM 54Mbps */ + USHORT TSSIStepOver2dot4G = 0; /* The TSSI value/step (0.5 dB/unit) */ + UCHAR RFValue = 0; + BBP_R49_STRUC BbpR49; + ULONG i = 0; + USHORT TxPower = 0, TxPowerOFDM54 = 0; + USHORT Value = 0; + CHAR BWPowerDelta = 0; + BOOLEAN bExtendedTssiMode = FALSE; + EEPROM_TX_PWR_OFFSET_STRUC TxPwrOffset = {{0}}; + + BbpR49.byte = 0; + + if (pAd->TxPowerCtrl.bInternalTxALC == FALSE) + { + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("---> %s\n", __FUNCTION__)); + + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_DELTA, Value); + + if ((Value & 0xFF) == 0xFF) /* 20M/40M BW Power Delta for 2.4GHz band */ + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: Don't considerate 20M/40M BW Delta Power since EEPROM is not calibrated.\n", __FUNCTION__)); + } + else + { + if ((Value & 0xC0) == 0xC0) + { + BWPowerDelta += (Value & 0x3F); /* increase 40M BW Tx power with the delta value */ + } + else if ((Value & 0xC0) == 0x80) + { + BWPowerDelta -= (Value & 0x3F); /* decrease 40M BW Tx power with the delta value */ + } + else + DBGPRINT(RT_DEBUG_TRACE, ("%s: 20/40M BW Delta Power is not enabled, Value = 0x%X\n", __FUNCTION__, Value)); + } + + RT28xx_EEPROM_READ16(pAd, EEPROM_TSSI_OVER_OFDM_54, Value); + TSSIBase = (Value & 0x001F); + + RT28xx_EEPROM_READ16(pAd, (EEPROM_TSSI_STEP_OVER_2DOT4G - 1), Value); + + if (((Value >> 8) & 0x80) == 0x80) /* Enable the extended TSSI mode */ + { + bExtendedTssiMode = TRUE; + } + else + { + bExtendedTssiMode = FALSE; + } + + if (bExtendedTssiMode == TRUE) /* Tx power offset for the extended TSSI mode */ + { + pAd->TxPowerCtrl.bExtendedTssiMode = TRUE; + + /* Get the per-channel Tx power offset */ + + RT28xx_EEPROM_READ16(pAd, (EEPROM_TX_POWER_OFFSET_OVER_CH_1 - 1), TxPwrOffset.word); + pAd->TxPowerCtrl.PerChTxPwrOffset[1] = (TxPwrOffset.field.Byte1 & 0x0F); /* Tx power offset over channel 1 */ + pAd->TxPowerCtrl.PerChTxPwrOffset[2] = (((TxPwrOffset.field.Byte1 & 0xF0) >> 4) & 0x0F); /* Tx power offset over channel 2 */ + + RT28xx_EEPROM_READ16(pAd, EEPROM_TX_POWER_OFFSET_OVER_CH_3, TxPwrOffset.word); + pAd->TxPowerCtrl.PerChTxPwrOffset[3] = (TxPwrOffset.field.Byte0 & 0x0F); /* Tx power offset over channel 3 */ + pAd->TxPowerCtrl.PerChTxPwrOffset[4] = (((TxPwrOffset.field.Byte0 & 0xF0) >> 4) & 0x0F); /* Tx power offset over channel 4 */ + pAd->TxPowerCtrl.PerChTxPwrOffset[5] = (TxPwrOffset.field.Byte1 & 0x0F); /* Tx power offset over channel 5 */ + pAd->TxPowerCtrl.PerChTxPwrOffset[6] = (((TxPwrOffset.field.Byte1 & 0xF0) >> 4) & 0x0F); /* Tx power offset over channel 6 */ + + RT28xx_EEPROM_READ16(pAd, EEPROM_TX_POWER_OFFSET_OVER_CH_7, TxPwrOffset.word); + pAd->TxPowerCtrl.PerChTxPwrOffset[7] = (TxPwrOffset.field.Byte0 & 0x0F); /* Tx power offset over channel 7 */ + pAd->TxPowerCtrl.PerChTxPwrOffset[8] = (((TxPwrOffset.field.Byte0 & 0xF0) >> 4) & 0x0F); /* Tx power offset over channel 8 */ + pAd->TxPowerCtrl.PerChTxPwrOffset[9] = (TxPwrOffset.field.Byte1 & 0x0F); /* Tx power offset over channel 9 */ + pAd->TxPowerCtrl.PerChTxPwrOffset[10] = (((TxPwrOffset.field.Byte1 & 0xF0) >> 4) & 0x0F); /* Tx power offset over channel 10 */ + + RT28xx_EEPROM_READ16(pAd, EEPROM_TX_POWER_OFFSET_OVER_CH_11, TxPwrOffset.word); + pAd->TxPowerCtrl.PerChTxPwrOffset[11] = (TxPwrOffset.field.Byte0 & 0x0F); /* Tx power offset over channel 11 */ + pAd->TxPowerCtrl.PerChTxPwrOffset[12] = (((TxPwrOffset.field.Byte0 & 0xF0) >> 4) & 0x0F); /* Tx power offset over channel 12 */ + pAd->TxPowerCtrl.PerChTxPwrOffset[13] = (TxPwrOffset.field.Byte1 & 0x0F); /* Tx power offset over channel 13 */ + pAd->TxPowerCtrl.PerChTxPwrOffset[14] = (((TxPwrOffset.field.Byte1 & 0xF0) >> 4) & 0x0F); /* Tx power offset over channel 14 */ + + /* 4-bit representation ==> 8-bit representation (2's complement) */ + + for (i = 1; i <= NUM_OF_CH_FOR_PER_CH_TX_PWR_OFFSET; i++) + { + if ((pAd->TxPowerCtrl.PerChTxPwrOffset[i] & 0x08) == 0x00) /* Positive number */ + { + pAd->TxPowerCtrl.PerChTxPwrOffset[i] = (pAd->TxPowerCtrl.PerChTxPwrOffset[i] & ~0xF8); + } + else /* 0x08: Negative number */ + { + pAd->TxPowerCtrl.PerChTxPwrOffset[i] = (pAd->TxPowerCtrl.PerChTxPwrOffset[i] | 0xF0); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: TxPwrOffset[1] = %d, TxPwrOffset[2] = %d, TxPwrOffset[3] = %d, TxPwrOffset[4] = %d\n", + __FUNCTION__, + pAd->TxPowerCtrl.PerChTxPwrOffset[1], + pAd->TxPowerCtrl.PerChTxPwrOffset[2], + pAd->TxPowerCtrl.PerChTxPwrOffset[3], + pAd->TxPowerCtrl.PerChTxPwrOffset[4])); + DBGPRINT(RT_DEBUG_TRACE, ("%s: TxPwrOffset[5] = %d, TxPwrOffset[6] = %d, TxPwrOffset[7] = %d, TxPwrOffset[8] = %d\n", + __FUNCTION__, + pAd->TxPowerCtrl.PerChTxPwrOffset[5], + pAd->TxPowerCtrl.PerChTxPwrOffset[6], + pAd->TxPowerCtrl.PerChTxPwrOffset[7], + pAd->TxPowerCtrl.PerChTxPwrOffset[8])); + DBGPRINT(RT_DEBUG_TRACE, ("%s: TxPwrOffset[9] = %d, TxPwrOffset[10] = %d, TxPwrOffset[11] = %d, TxPwrOffset[12] = %d\n", + __FUNCTION__, + pAd->TxPowerCtrl.PerChTxPwrOffset[9], + pAd->TxPowerCtrl.PerChTxPwrOffset[10], + pAd->TxPowerCtrl.PerChTxPwrOffset[11], + pAd->TxPowerCtrl.PerChTxPwrOffset[12])); + DBGPRINT(RT_DEBUG_TRACE, ("%s: TxPwrOffset[13] = %d, TxPwrOffset[14] = %d\n", + __FUNCTION__, + pAd->TxPowerCtrl.PerChTxPwrOffset[13], + pAd->TxPowerCtrl.PerChTxPwrOffset[14])); + } + else + { + pAd->TxPowerCtrl.bExtendedTssiMode = FALSE; + RTMPZeroMemory(pAd->TxPowerCtrl.PerChTxPwrOffset, sizeof (pAd->TxPowerCtrl.PerChTxPwrOffset)); + } + + RT28xx_EEPROM_READ16(pAd, (EEPROM_TSSI_STEP_OVER_2DOT4G - 1), TSSIStepOver2dot4G); + TSSIStepOver2dot4G = (0x000F & (TSSIStepOver2dot4G >> 8)); + + RT28xx_EEPROM_READ16(pAd, (EEPROM_OFDM_MCS6_MCS7 - 1), TxPowerOFDM54); + TxPowerOFDM54 = (0x000F & (TxPowerOFDM54 >> 8)); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: TSSIBase = %d, TSSIStepOver2dot4G = %d, TxPowerOFDM54 = %d\n", + __FUNCTION__, + TSSIBase, + TSSIStepOver2dot4G, + TxPowerOFDM54)); + + /* The desired TSSI over CCK */ + RT28xx_EEPROM_READ16(pAd, EEPROM_CCK_MCS0_MCS1, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xDE = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverCCK[MCS_0] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2)) + 6); + desiredTSSIOverCCK[MCS_1] = desiredTSSIOverCCK[MCS_0]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_CCK_MCS2_MCS3 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xDF = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverCCK[MCS_2] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2)) + 6); + desiredTSSIOverCCK[MCS_3] = desiredTSSIOverCCK[MCS_2]; + + /* Boundary verification: the desired TSSI value */ + for (i = 0; i < 4; i++) /* CCK: MCS 0 ~ MCS 3 */ + { + if (desiredTSSIOverCCK[i] < 0x00) + { + desiredTSSIOverCCK[i] = 0x00; + } + else if (desiredTSSIOverCCK[i] > 0x1F) + { + desiredTSSIOverCCK[i] = 0x1F; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverCCK[0] = %d, desiredTSSIOverCCK[1] = %d, desiredTSSIOverCCK[2] = %d, desiredTSSIOverCCK[3] = %d\n", + __FUNCTION__, + desiredTSSIOverCCK[0], + desiredTSSIOverCCK[1], + desiredTSSIOverCCK[2], + desiredTSSIOverCCK[3])); + + /* The desired TSSI over OFDM */ + RT28xx_EEPROM_READ16(pAd, EEPROM_OFDM_MCS0_MCS1, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE0 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverOFDM[MCS_0] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverOFDM[MCS_1] = desiredTSSIOverOFDM[MCS_0]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_OFDM_MCS2_MCS3 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE1 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverOFDM[MCS_2] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverOFDM[MCS_3] = desiredTSSIOverOFDM[MCS_2]; + RT28xx_EEPROM_READ16(pAd, EEPROM_OFDM_MCS4_MCS5, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE2 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverOFDM[MCS_4] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverOFDM[MCS_5] = desiredTSSIOverOFDM[MCS_4]; + desiredTSSIOverOFDM[MCS_6] = TSSIBase; + desiredTSSIOverOFDM[MCS_7] = TSSIBase; + + /* Boundary verification: the desired TSSI value */ + for (i = 0; i < 8; i++) /* OFDM: MCS 0 ~ MCS 7 */ + { + if (desiredTSSIOverOFDM[i] < 0x00) + { + desiredTSSIOverOFDM[i] = 0x00; + } + else if (desiredTSSIOverOFDM[i] > 0x1F) + { + desiredTSSIOverOFDM[i] = 0x1F; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverOFDM[0] = %d, desiredTSSIOverOFDM[1] = %d, desiredTSSIOverOFDM[2] = %d, desiredTSSIOverOFDM[3] = %d\n", + __FUNCTION__, + desiredTSSIOverOFDM[0], + desiredTSSIOverOFDM[1], + desiredTSSIOverOFDM[2], + desiredTSSIOverOFDM[3])); + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverOFDM[4] = %d, desiredTSSIOverOFDM[5] = %d, desiredTSSIOverOFDM[6] = %d, desiredTSSIOverOFDM[7] = %d\n", + __FUNCTION__, + desiredTSSIOverOFDM[4], + desiredTSSIOverOFDM[5], + desiredTSSIOverOFDM[6], + desiredTSSIOverOFDM[7])); + + /* The desired TSSI over HT */ + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_MCS0_MCS1, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE4 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHT[MCS_0] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_1] = desiredTSSIOverHT[MCS_0]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_MCS2_MCS3 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE5 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHT[MCS_2] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_3] = desiredTSSIOverHT[MCS_2]; + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_MCS4_MCS5, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE6 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHT[MCS_4] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_5] = desiredTSSIOverHT[MCS_4]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_MCS6_MCS7 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE7 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHT[MCS_6] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_7] = desiredTSSIOverHT[MCS_6] - 1; + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_MCS8_MCS9, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_HT_MCS9_MCS9(0xE8) = 0x%X\n", TxPower)); + desiredTSSIOverHT[MCS_8] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_9] = desiredTSSIOverHT[MCS_8]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_MCS10_MCS11 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_HT_MCS10_MCS11(0xE9) = 0x%X\n", TxPower)); + desiredTSSIOverHT[MCS_10] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_11] = desiredTSSIOverHT[MCS_10]; + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_MCS12_MCS13, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_HT_MCS12_MCS13(0xEA) = 0x%X\n", TxPower)); + desiredTSSIOverHT[MCS_12] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_13] = desiredTSSIOverHT[MCS_12]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_MCS14_MCS15 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_HT_MCS14_MCS15(0xEB) = 0x%X\n", TxPower)); + desiredTSSIOverHT[MCS_14] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_15] = desiredTSSIOverHT[MCS_14] - 1; + + /* Boundary verification: the desired TSSI value */ + for (i = 0; i < 16; i++) /* HT: MCS 0 ~ MCS 15 */ + { + if (desiredTSSIOverHT[i] < 0x00) + { + desiredTSSIOverHT[i] = 0x00; + } + else if (desiredTSSIOverHT[i] > 0x1F) + { + desiredTSSIOverHT[i] = 0x1F; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHT[0] = %d, desiredTSSIOverHT[1] = %d, desiredTSSIOverHT[2] = %d, desiredTSSIOverHT[3] = %d\n", + __FUNCTION__, + desiredTSSIOverHT[0], + desiredTSSIOverHT[1], + desiredTSSIOverHT[2], + desiredTSSIOverHT[3])); + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHT[4] = %d, desiredTSSIOverHT[5] = %d, desiredTSSIOverHT[6] = %d, desiredTSSIOverHT[7] = %d\n", + __FUNCTION__, + desiredTSSIOverHT[4], + desiredTSSIOverHT[5], + desiredTSSIOverHT[6], + desiredTSSIOverHT[7])); + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHT[8] = %d, desiredTSSIOverHT[9] = %d, desiredTSSIOverHT[10] = %d, desiredTSSIOverHT[11] = %d\n", + __FUNCTION__, + desiredTSSIOverHT[8], + desiredTSSIOverHT[9], + desiredTSSIOverHT[10], + desiredTSSIOverHT[11])); + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHT[12] = %d, desiredTSSIOverHT[13] = %d, desiredTSSIOverHT[14] = %d, desiredTSSIOverHT[15] = %d\n", + __FUNCTION__, + desiredTSSIOverHT[12], + desiredTSSIOverHT[13], + desiredTSSIOverHT[14], + desiredTSSIOverHT[15])); + + /* The desired TSSI over HT using STBC */ + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_USING_STBC_MCS0_MCS1, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xEC = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHTUsingSTBC[MCS_0] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHTUsingSTBC[MCS_1] = desiredTSSIOverHTUsingSTBC[MCS_0]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_USING_STBC_MCS2_MCS3 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xED = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHTUsingSTBC[MCS_2] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHTUsingSTBC[MCS_3] = desiredTSSIOverHTUsingSTBC[MCS_2]; + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_USING_STBC_MCS4_MCS5, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xEE = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHTUsingSTBC[MCS_4] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHTUsingSTBC[MCS_5] = desiredTSSIOverHTUsingSTBC[MCS_4]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_USING_STBC_MCS6_MCS7 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xEF = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHTUsingSTBC[MCS_6] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHTUsingSTBC[MCS_7] = desiredTSSIOverHTUsingSTBC[MCS_6]; + + /* Boundary verification: the desired TSSI value */ + for (i = 0; i < 8; i++) /* HT using STBC: MCS 0 ~ MCS 7 */ + { + if (desiredTSSIOverHTUsingSTBC[i] < 0x00) + { + desiredTSSIOverHTUsingSTBC[i] = 0x00; + } + else if (desiredTSSIOverHTUsingSTBC[i] > 0x1F) + { + desiredTSSIOverHTUsingSTBC[i] = 0x1F; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHTUsingSTBC[0] = %d, desiredTSSIOverHTUsingSTBC[1] = %d, desiredTSSIOverHTUsingSTBC[2] = %d, desiredTSSIOverHTUsingSTBC[3] = %d\n", + __FUNCTION__, + desiredTSSIOverHTUsingSTBC[0], + desiredTSSIOverHTUsingSTBC[1], + desiredTSSIOverHTUsingSTBC[2], + desiredTSSIOverHTUsingSTBC[3])); + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHTUsingSTBC[4] = %d, desiredTSSIOverHTUsingSTBC[5] = %d, desiredTSSIOverHTUsingSTBC[6] = %d, desiredTSSIOverHTUsingSTBC[7] = %d\n", + __FUNCTION__, + desiredTSSIOverHTUsingSTBC[4], + desiredTSSIOverHTUsingSTBC[5], + desiredTSSIOverHTUsingSTBC[6], + desiredTSSIOverHTUsingSTBC[7])); + + /* + | RF_R28[5:4] | RF_R27[4] | RF_R27[5] + | Adc5b_sel | Rf_tssi_sel | rf_tssi_en + --------------------+-------------------+-------------------+-------------- + Internal TSSI0 | 00 | 1 | 1 + Internal TSSI1 | 10 | 0 | 1 + External TSSI0 | 00 | 0 | 0 + External TSSI1 | 10 | 1 | 0 + + */ + + /* Internal TSSI0 */ + /* RFValue = (0x3 | 0x0<<2 | 0x1<<4 | 0x1 << 5); // tssi_gain0:x9, tssi_atten0:-17db, rf_tssi_sel=1, rf_tssi_en=1 */ + /* External TSSI0 */ + /* RFValue = (0x3 | 0x0<<2 | 0x0<<4 | 0x1 << 5); // tssi_gain0:x9, tssi_atten0:-17db, rf_tssi_sel=0, rf_tssi_en=1 */ + RFValue = (0x3 | 0x0<<2 | 0x3<<4);/* tssi_gain0:x9, tssi_atten0:-17db, rf_tssi_sel=0, rf_tssi_en=1 */ + /* Internal TSSI1 */ + /* RFValue = (0x3 | 0x0<<2 | 0x0<<4 | 0x1 << 5); // tssi_gain0:x9, tssi_atten0:-17db, rf_tssi_sel=0, rf_tssi_en=1 */ + RT30xxWriteRFRegister(pAd, RF_R27, RFValue); + + /* Internal TSSI0 */ + /* RFValue = (0x3 | 0x0<<2 | 0x2 << 4); // tssi_gain1:x9, tssi_atten1:-17db, Adc5b_sel=10 (Internal TSSI1) */ + RFValue = (0x3 | 0x0<<2);/* tssi_gain1:x9, tssi_atten1:-17db, Adc5b_sel=10 (Internal TSSI1) */ + /* Internal TSSI1 */ + /* RFValue = (0x3 | 0x0<<2 | 0x2 << 4); // tssi_gain1:x9, tssi_atten1:-17db, Adc5b_sel=10 (Internal TSSI1) */ + RT30xxWriteRFRegister(pAd, RF_R28, RFValue); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49.byte); + BbpR49.field.adc5_in_sel = 1; /* PSI */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R49, BbpR49.byte); + + DBGPRINT(RT_DEBUG_TRACE, ("<--- %s\n", __FUNCTION__)); +} +#endif /* RTMP_INTERNAL_TX_ALC */ +#endif /* RT3352 */ + +/* End of rt3352.c */ diff --git a/mt7620/src/chips/rt3883.c b/mt7620/src/chips/rt3883.c new file mode 100644 index 0000000..7c21fbb --- /dev/null +++ b/mt7620/src/chips/rt3883.c @@ -0,0 +1,2306 @@ +/* + *************************************************************************** + * 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: + rt3883.c + + Abstract: + Specific funcitons and configurations for RT3883 + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifdef RT3883 + +#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 RT3883_EeBuffer[EEPROM_SIZE] = { + 0x83, 0x38, 0x01, 0x00, 0x00, 0x0c, 0x43, 0x28, 0x83, 0x00, 0x83, 0x28, 0x14, 0x18, 0xff, 0xff, + 0xff, 0xff, 0x83, 0x28, 0x14, 0x18, 0x00, 0x00, 0x01, 0x00, 0x6a, 0xff, 0x00, 0x02, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0c, 0x43, 0x28, 0x83, 0x01, 0x00, 0x0c, + 0x43, 0x28, 0x83, 0x02, 0x33, 0x0a, 0xec, 0x00, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x20, 0x01, 0x55, 0x77, 0xa8, 0xaa, 0x8c, 0x88, 0xff, 0xff, 0x0a, 0x08, 0x08, 0x06, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x66, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, + 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xaa, 0xaa, 0x88, 0x66, 0xaa, 0xaa, + 0x88, 0x66, 0xaa, 0xaa, 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, + 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xaa, 0xaa, 0x88, 0x66, 0xaa, 0xaa, 0x88, 0x66, 0xaa, 0xaa, + 0x88, 0x66, 0xaa, 0xaa, 0x88, 0x66, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + } ; + + +FREQUENCY_ITEM FreqItems3883[] = +{ + /**************************************************/ + /* ISM : 2.4 to 2.483 GHz */ + /**************************************************/ + /*-CH---N-------R---K-----------*/ + /* R : , g band: pll_mode=01, pll_R=10*/ + {1, 241, 6, 2}, + {2, 241, 6, 7}, + {3, 242, 6, 2}, + {4, 242, 6, 7}, + {5, 243, 6, 2}, + {6, 243, 6, 7}, + {7, 244, 6, 2}, + {8, 244, 6, 7}, + {9, 245, 6, 2}, + {10, 245, 6, 7}, + {11, 246, 6, 2}, + {12, 246, 6, 7}, + {13, 247, 6, 2}, + {14, 248, 6, 4}, + + /**************************************************/ + /* 5 GHz*/ + /**************************************************/ + /* R : , g band: pll_mode=10, pll_R=00*/ + {36, 0x56, 8, 4}, + {38, 0x56, 8, 6}, + {40, 0x56, 8, 8}, + {44, 0x57, 8, 0}, + {46, 0x57, 8, 2}, + {48, 0x57, 8, 4}, + {52, 0x57, 8, 8}, + {54, 0x57, 8, 10}, + {56, 0x58, 8, 0}, + {60, 0x58, 8, 4}, + {62, 0x58, 8, 6}, + {64, 0x58, 8, 8}, + + {100, 0x5B, 8, 8}, + {102, 0x5B, 8, 10}, + {104, 0x5C, 8, 0}, + {108, 0x5C, 8, 4}, + {110, 0x5C, 8, 6}, + {112, 0x5C, 8, 8}, + {114, 0x5C, 8, 10}, + {116, 0x5D, 8, 0}, + {118, 0x5D, 8, 2}, + {120, 0x5D, 8, 4}, + {124, 0x5D, 8, 8}, + {126, 0x5D, 8, 10}, + {128, 0x5E, 8, 0}, + {132, 0x5E, 8, 4}, + {134, 0x5E, 8, 6}, + {136, 0x5E, 8, 8}, + {140, 0x5F, 8, 0}, + + {149, 0x5F, 8, 9}, + {151, 0x5F, 8, 11}, + {153, 0x60, 8, 1}, + {157, 0x60, 8, 5}, + {159, 0x60, 8, 7}, + {161, 0x60, 8, 9}, + {165, 0x61, 8, 1}, +/* {167, 0x61, 8, 3},*/ +/* {169, 0x61, 8, 5},*/ +/* {171, 0x61, 8, 7},*/ +/* {173, 0x61, 8, 9},*/ + {184, 0x52, 8, 0}, + {188, 0x52, 8, 4}, + {192, 0x52, 8, 8}, + {196, 0x53, 8, 0}, +}; +UCHAR NUM_OF_3883_CHNL = (sizeof(FreqItems3883) / sizeof(FREQUENCY_ITEM)); + +static REG_PAIR RT3883_RFRegTable[] = { + {RF_R00, 0xE0}, + {RF_R01, 0x03}, + {RF_R02, 0x50}, + {RF_R03, 0x20}, + {RF_R04, 0x00}, + {RF_R05, 0x00}, + {RF_R06, 0x40}, + {RF_R07, 0x00}, + {RF_R08, 0x5B}, + {RF_R09, 0x08}, + {RF_R10, 0xD3}, /* Gary, 2010-02-12 */ + {RF_R11, 0x48}, + {RF_R12, 0x1A}, /* Gary, 2011-03-10 */ + {RF_R13, 0x12}, + {RF_R14, 0x00}, + {RF_R15, 0x00}, + {RF_R16, 0x00}, +/* {RF_R17, 0x26}, */ + {RF_R18, 0x40}, + {RF_R19, 0x00}, + {RF_R20, 0x00}, + {RF_R21, 0x00}, + {RF_R22, 0x20}, + {RF_R23, 0xC0}, + {RF_R24, 0x00}, + {RF_R25, 0x00}, + {RF_R26, 0x00}, + {RF_R27, 0x00}, + {RF_R28, 0x00}, + {RF_R29, 0x00}, + {RF_R30, 0x10}, + {RF_R31, 0x80}, + {RF_R32, 0x80}, + {RF_R33, 0x00}, + {RF_R34, 0x20}, + {RF_R35, 0x00}, + {RF_R36, 0x00}, + {RF_R37, 0x00}, + {RF_R38, 0x86}, /* Gary, 2010-02-12 */ + {RF_R39, 0x23}, + {RF_R40, 0x00}, + {RF_R41, 0x00}, + {RF_R42, 0x00}, + {RF_R43, 0x00}, + {RF_R44, 0x93}, /* Gary, 2009-12-08 */ + {RF_R45, 0xBB}, + {RF_R46, 0x60}, + {RF_R47, 0x00}, + {RF_R48, 0x00}, + {RF_R49, 0x8E}, + {RF_R50, 0x86}, + {RF_R51, 0x51}, + {RF_R52, 0x05}, + {RF_R53, 0x76}, + {RF_R54, 0x76}, + {RF_R55, 0x76}, + {RF_R56, 0xDB}, + {RF_R57, 0x3E}, + {RF_R58, 0x00}, + {RF_R59, 0x00}, + {RF_R60, 0x00}, + {RF_R61, 0x00}, + {RF_R62, 0x00}, + {RF_R63, 0x00}, +}; + +static UCHAR RT3883_NUM_RF_REG_PARMS = (sizeof(RT3883_RFRegTable) / sizeof(REG_PAIR)); + + +static REG_PAIR RT3883_BBPRegTable[] = { + {BBP_R4, 0x50}, /* 3883 need to */ + {BBP_R47, 0x48}, /* ALC Functions change from 0x7 to 0x48 Baron suggest */ + + {BBP_R86, 0x46}, /* for peak throughput, Henry 2009-12-23 */ + {BBP_R88, 0x90}, /* for rt3883 middle range, Henry 2009-12-31 */ + + {BBP_R92, 0x02}, /* middle range issue, Rory @2008-01-28 */ + + {BBP_R103, 0xC0}, + {BBP_R104, 0x92}, + {BBP_R105, 0x34}, +#ifdef DOT11_N_SUPPORT + {BBP_R106, 0x12}, // 40M=2, 20M=2. Fix 20M SGI STBC problem +#endif /* DOT11_N_SUPPORT */ + {BBP_R120, 0x50}, /* for long range -2db, Gary 2010-01-22 */ + {BBP_R137, 0x0F}, /* Julian suggest make the RF output more stable */ + {BBP_R163, 0x9D}, /* Enable TxBf modes by default, Gary, 2010-06-02 */ + + {BBP_R179, 0x02}, /* Set ITxBF timeout to 0x9C40=1000msec */ + {BBP_R180, 0x00}, + {BBP_R182, 0x40}, + {BBP_R180, 0x01}, + {BBP_R182, 0x9C}, + + {BBP_R179, 0x00}, + + {BBP_R142, 0x04}, /* Reprogram the inband interface to put right values in RXWI */ + {BBP_R143, 0x3b}, + {BBP_R142, 0x06}, + {BBP_R143, 0xA0}, + {BBP_R142, 0x07}, + {BBP_R143, 0xA1}, + {BBP_R142, 0x08}, + {BBP_R143, 0xA2}, + {BBP_R148, 0xC8}, /* Gary, 2010-2-12 */ +}; + +static UCHAR RT3883_NUM_BBP_REG_PARMS = (sizeof(RT3883_BBPRegTable) / sizeof(REG_PAIR)); + + +static RTMP_REG_PAIR RT3883_MACRegTable[] = { + {TX_SW_CFG0, 0x402}, /* Gary,2009-9-21*/ + {TX_SW_CFG1, 0x0}, /* FIXME*/ + {TX_SW_CFG2, 0x40000}, /* FIXME*/ + {TX_TXBF_CFG_0, 0x8000FC21}, /* Force MCS0 for sounding response*/ + {TX_TXBF_CFG_3, 0x00009c40}, /* ETxBF Timeout = 1 sec = 0x9c40*(25 usec)*/ + +#ifdef RANGE_EXTEND + {HT_FBK_CFG1, 0xedcba980}, /* Fallback MCS8->MCS0 */ +#endif /* RANGE_EXTEND */ + {TX_FBK_CFG_3S_0, 0x12111008}, /* default value*/ + {TX_FBK_CFG_3S_1, 0x16151413}, /* default value*/ +}; +static UCHAR RT3883_NUM_MAC_REG_PARMS = (sizeof(RT3883_MACRegTable) / sizeof(RTMP_REG_PAIR)); + +static VOID NICInitRT3883RFRegisters(IN PRTMP_ADAPTER pAd) +{ + + /* Init RF calibration */ + /* Driver should toggle RF R02 bit7 before init RF registers */ + UINT8 RfReg = 0; + int i; + + /* Initialize RF register to default value */ + for (i = 0; i < RT3883_NUM_RF_REG_PARMS; i++) + { + RT30xxWriteRFRegister(pAd, RT3883_RFRegTable[i].Register, RT3883_RFRegTable[i].Value); + } + + if ((pAd->CommonCfg.CID & 0x0000000f) >= 0x00000005) + { + RT30xxWriteRFRegister(pAd, RF_R32, 0xD8); + RT30xxWriteRFRegister(pAd, RF_R33, 0x3B); + } + RT30xxWriteRFRegister(pAd, RF_R33, 0x3f); + + /*RF_R02: Resistor calibration, RF_R02 = RF_R30 (RT30xx) */ + RT30xxReadRFRegister(pAd, RF_R02, (PUCHAR)&RfReg); + RfReg &= ~(1 << 6); /* clear bit6=rescal_bp */ + RfReg |= 0x80; /* bit7=rescal_en */ + RT30xxWriteRFRegister(pAd, RF_R02, (UCHAR)RfReg); + /*DBGPRINT(RT_DEBUG_WARN,("SS \n")); */ + RTMPusecDelay(1000); + RfReg &= 0x7F; + RT30xxWriteRFRegister(pAd, RF_R02, (UCHAR)RfReg); + +} + + +/* +======================================================================== +Routine Description: + Initialize specific MAC registers. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +static VOID NICInitRT3883MacRegisters( + IN RTMP_ADAPTER *pAd) +{ + UINT32 IdReg; + + for(IdReg=0; IdRegword = 0; + pAntenna->field.RfIcType = RFIC_3853; + pAntenna->field.TxPath = 3; + pAntenna->field.RxPath = 3; +} + + +static VOID RT3883_RxSensitivityTuning( + IN struct _RTMP_ADAPTER *pAd) +{ + UINT8 bbp_val; + + bbp_val = 0x26 + GET_LNA_GAIN(pAd); +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, 0x0); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, bbp_val); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, 0x20); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, bbp_val); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, 0x40); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, bbp_val); + } + else +#endif /* RALINK_ATE */ + AsicBBPWriteWithRxChain(pAd, BBP_R66, bbp_val, RX_CHAIN_ALL); +} + +VOID RT3883_AsicGetTxPowerOffset( + IN PRTMP_ADAPTER pAd, + INOUT PULONG pTxPwr) +{ + CONFIGURATION_OF_TX_POWER_CONTROL_OVER_MAC CfgOfTxPwrCtrlOverMAC; + + NdisZeroMemory(&CfgOfTxPwrCtrlOverMAC, sizeof(CfgOfTxPwrCtrlOverMAC)); + + if (IS_RT3883(pAd)) + { + /* MAC 0x1314, 0x1318, 0x131C, 0x1320 and 1324 */ + CfgOfTxPwrCtrlOverMAC.NumOfEntries = MAX_TX_PWR_CONTROL_OVER_MAC_REGISTERS; + + 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_0_EXT; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].RegisterValue = ((pAd->Tx40MPwrCfgABand[0] & 0xf0f0f0f0) >> 4); + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].MACRegisterOffset = TX_PWR_CFG_1; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].RegisterValue = pAd->Tx40MPwrCfgABand[1]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].MACRegisterOffset = TX_PWR_CFG_1_EXT; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].RegisterValue = ((pAd->Tx40MPwrCfgABand[1] & 0xf0f0f0f0) >> 4); + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].MACRegisterOffset = TX_PWR_CFG_2; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].RegisterValue = pAd->Tx40MPwrCfgABand[2]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[5].MACRegisterOffset = TX_PWR_CFG_2_EXT; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[5].RegisterValue = ((pAd->Tx40MPwrCfgABand[2] & 0xf0f0f0f0) >> 4); + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[6].MACRegisterOffset = TX_PWR_CFG_3; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[6].RegisterValue = pAd->Tx40MPwrCfgABand[3]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[7].MACRegisterOffset = TX_PWR_CFG_3_EXT; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[7].RegisterValue = ((pAd->Tx40MPwrCfgABand[3] & 0xf0f0f0f0) >> 4); + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[8].MACRegisterOffset = TX_PWR_CFG_4; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[8].RegisterValue = pAd->Tx40MPwrCfgABand[4]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[9].MACRegisterOffset = TX_PWR_CFG_4_EXT; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[9].RegisterValue = ((pAd->Tx40MPwrCfgABand[4] & 0xf0f0f0f0) >> 4); + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[10].MACRegisterOffset = TX_PWR_CFG_5; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[10].RegisterValue = pAd->Tx40MPwrCfgABand[5]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[11].MACRegisterOffset = TX_PWR_CFG_6; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[11].RegisterValue = pAd->Tx40MPwrCfgABand[6]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[12].MACRegisterOffset = TX_PWR_CFG_7; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[12].RegisterValue = pAd->Tx40MPwrCfgABand[7]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[13].MACRegisterOffset = TX_PWR_CFG_8; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[13].RegisterValue = pAd->Tx40MPwrCfgABand[8]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[14].MACRegisterOffset = TX_PWR_CFG_9; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[14].RegisterValue = pAd->Tx40MPwrCfgABand[9]; + } + else + { + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].MACRegisterOffset = TX_PWR_CFG_0; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].RegisterValue = pAd->Tx40MPwrCfgGBand[0]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].MACRegisterOffset = TX_PWR_CFG_0_EXT; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].RegisterValue = ((pAd->Tx40MPwrCfgGBand[0] & 0xf0f0f0f0) >> 4); + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].MACRegisterOffset = TX_PWR_CFG_1; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].RegisterValue = pAd->Tx40MPwrCfgGBand[1]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].MACRegisterOffset = TX_PWR_CFG_1_EXT; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].RegisterValue = ((pAd->Tx40MPwrCfgGBand[1] & 0xf0f0f0f0) >> 4); + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].MACRegisterOffset = TX_PWR_CFG_2; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].RegisterValue = pAd->Tx40MPwrCfgGBand[2]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[5].MACRegisterOffset = TX_PWR_CFG_2_EXT; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[5].RegisterValue = ((pAd->Tx40MPwrCfgGBand[2] & 0xf0f0f0f0) >> 4); + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[6].MACRegisterOffset = TX_PWR_CFG_3; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[6].RegisterValue = pAd->Tx40MPwrCfgGBand[3]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[7].MACRegisterOffset = TX_PWR_CFG_3_EXT; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[7].RegisterValue = ((pAd->Tx40MPwrCfgGBand[3] & 0xf0f0f0f0) >> 4); + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[8].MACRegisterOffset = TX_PWR_CFG_4; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[8].RegisterValue = pAd->Tx40MPwrCfgGBand[4]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[9].MACRegisterOffset = TX_PWR_CFG_4_EXT; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[9].RegisterValue = ((pAd->Tx40MPwrCfgGBand[4] & 0xf0f0f0f0) >> 4); + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[10].MACRegisterOffset = TX_PWR_CFG_5; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[10].RegisterValue = pAd->Tx40MPwrCfgGBand[5]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[11].MACRegisterOffset = TX_PWR_CFG_6; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[11].RegisterValue = pAd->Tx40MPwrCfgGBand[6]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[12].MACRegisterOffset = TX_PWR_CFG_7; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[12].RegisterValue = pAd->Tx40MPwrCfgGBand[7]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[13].MACRegisterOffset = TX_PWR_CFG_8; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[13].RegisterValue = pAd->Tx40MPwrCfgGBand[8]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[14].MACRegisterOffset = TX_PWR_CFG_9; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[14].RegisterValue = pAd->Tx40MPwrCfgGBand[9]; + } + } + 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_0_EXT; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].RegisterValue = ((pAd->Tx20MPwrCfgABand[0] & 0xf0f0f0f0) >> 4); + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].MACRegisterOffset = TX_PWR_CFG_1; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].RegisterValue = pAd->Tx20MPwrCfgABand[1]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].MACRegisterOffset = TX_PWR_CFG_1_EXT; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].RegisterValue = ((pAd->Tx20MPwrCfgABand[1] & 0xf0f0f0f0) >> 4); + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].MACRegisterOffset = TX_PWR_CFG_2; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].RegisterValue = pAd->Tx20MPwrCfgABand[2]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[5].MACRegisterOffset = TX_PWR_CFG_2_EXT; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[5].RegisterValue = ((pAd->Tx20MPwrCfgABand[2] & 0xf0f0f0f0) >> 4); + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[6].MACRegisterOffset = TX_PWR_CFG_3; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[6].RegisterValue = pAd->Tx20MPwrCfgABand[3]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[7].MACRegisterOffset = TX_PWR_CFG_3_EXT; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[7].RegisterValue = ((pAd->Tx20MPwrCfgABand[3] & 0xf0f0f0f0) >> 4); + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[8].MACRegisterOffset = TX_PWR_CFG_4; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[8].RegisterValue = pAd->Tx20MPwrCfgABand[4]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[9].MACRegisterOffset = TX_PWR_CFG_4_EXT; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[9].RegisterValue = ((pAd->Tx20MPwrCfgABand[4] & 0xf0f0f0f0) >> 4); + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[10].MACRegisterOffset = TX_PWR_CFG_5; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[10].RegisterValue = pAd->Tx20MPwrCfgABand[5]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[11].MACRegisterOffset = TX_PWR_CFG_6; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[11].RegisterValue = pAd->Tx20MPwrCfgABand[6]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[12].MACRegisterOffset = TX_PWR_CFG_7; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[12].RegisterValue = pAd->Tx20MPwrCfgABand[7]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[13].MACRegisterOffset = TX_PWR_CFG_8; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[13].RegisterValue = pAd->Tx20MPwrCfgABand[8]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[14].MACRegisterOffset = TX_PWR_CFG_9; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[14].RegisterValue = pAd->Tx20MPwrCfgABand[9]; + } + else + { + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].MACRegisterOffset = TX_PWR_CFG_0; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].RegisterValue = pAd->Tx20MPwrCfgGBand[0]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].MACRegisterOffset = TX_PWR_CFG_0_EXT; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].RegisterValue = ((pAd->Tx20MPwrCfgGBand[0] & 0xf0f0f0f0) >> 4); + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].MACRegisterOffset = TX_PWR_CFG_1; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].RegisterValue = pAd->Tx20MPwrCfgGBand[1]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].MACRegisterOffset = TX_PWR_CFG_1_EXT; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].RegisterValue = ((pAd->Tx20MPwrCfgGBand[1] & 0xf0f0f0f0) >> 4); + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].MACRegisterOffset = TX_PWR_CFG_2; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].RegisterValue = pAd->Tx20MPwrCfgGBand[2]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[5].MACRegisterOffset = TX_PWR_CFG_2_EXT; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[5].RegisterValue = ((pAd->Tx20MPwrCfgGBand[2] & 0xf0f0f0f0) >> 4); + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[6].MACRegisterOffset = TX_PWR_CFG_3; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[6].RegisterValue = pAd->Tx20MPwrCfgGBand[3]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[7].MACRegisterOffset = TX_PWR_CFG_3_EXT; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[7].RegisterValue = ((pAd->Tx20MPwrCfgGBand[3] & 0xf0f0f0f0) >> 4); + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[8].MACRegisterOffset = TX_PWR_CFG_4; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[8].RegisterValue = pAd->Tx20MPwrCfgGBand[4]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[9].MACRegisterOffset = TX_PWR_CFG_4_EXT; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[9].RegisterValue = ((pAd->Tx20MPwrCfgGBand[4] & 0xf0f0f0f0) >> 4); + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[10].MACRegisterOffset = TX_PWR_CFG_5; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[10].RegisterValue = pAd->Tx20MPwrCfgGBand[5]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[11].MACRegisterOffset = TX_PWR_CFG_6; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[11].RegisterValue = pAd->Tx20MPwrCfgGBand[6]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[12].MACRegisterOffset = TX_PWR_CFG_7; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[12].RegisterValue = pAd->Tx20MPwrCfgGBand[7]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[13].MACRegisterOffset = TX_PWR_CFG_8; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[13].RegisterValue = pAd->Tx20MPwrCfgGBand[8]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[14].MACRegisterOffset = TX_PWR_CFG_9; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[14].RegisterValue = pAd->Tx20MPwrCfgGBand[9]; + } + } + NdisCopyMemory(pTxPwr, (UCHAR *)&CfgOfTxPwrCtrlOverMAC, sizeof(CfgOfTxPwrCtrlOverMAC)); + } +} + +static VOID RT3883_ChipBBPAdjust( + IN RTMP_ADAPTER *pAd) +{ + UINT32 Value; + UCHAR byteValue = 0; + UCHAR r66_val; + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && + (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + /*(pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == 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); + + /* request by Gary 20070208 for middle and long range G/A Band*/ + r66_val = (pAd->CommonCfg.Channel > 14) ? 0x48 : 0x38; + AsicBBPWriteWithRxChain(pAd, BBP_R66, r66_val, RX_CHAIN_ALL); + + 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, ("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.AddHTInfo.AddHtInfo.ExtChanOffset == 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); + + /* request by Gary 20070208 for middle and long range A/G Band*/ + r66_val = (pAd->CommonCfg.Channel > 14) ? 0x48 : 0x38; + AsicBBPWriteWithRxChain(pAd, BBP_R66, r66_val, RX_CHAIN_ALL); + + 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, ("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); + + /* 20 MHz bandwidth*/ + /* request by Gary 20070208*/ + r66_val = (pAd->CommonCfg.Channel > 14) ? 0x40 : 0x38; + AsicBBPWriteWithRxChain(pAd, BBP_R66, r66_val, RX_CHAIN_ALL); + + 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); + +#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 */ + } + + if (pAd->CommonCfg.Channel > 14) + { /* request by Gary 20070208 for middle and long range A Band*/ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, 0x1D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, 0x1D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, 0x1D); + /* Disable CCK packet detection in 5G band */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x00); + /*RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x1D);*/ + } + else + { /* request by Gary 20070208 for middle and long range G band*/ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, 0x2D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, 0x2D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, 0x2D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A); + /*RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x2D);*/ + } +} + + +#ifdef CONFIG_STA_SUPPORT +static VOID RT3883_NetDevNickNameInit( + IN struct _RTMP_ADAPTER *pAd) +{ + snprintf((PSTRING) pAd->nickname, sizeof(pAd->nickname), "RT3883STA"); +} + + +static UCHAR RT3883_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; + else /* A band */ + R66 = 0x20 + (lanGain * 5) /3; + + if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) + R66 += 0x10; + + if (OrigR66Value != R66) + AsicBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + + return R66; +} +#endif /* CONFIG_STA_SUPPORT */ + + +static VOID RT3883_ChipAGCInit( + IN PRTMP_ADAPTER pAd, + IN UCHAR BandWidth) +{ + UCHAR R66; + CHAR lanGain = GET_LNA_GAIN(pAd); + + if (pAd->LatchRfRegs.Channel <= 14) /* BG band*/ + R66 = (UCHAR)(0x2E + lanGain); + else /*A band*/ + R66 = (UCHAR)(0x20 + (lanGain * 5) / 3); + + AsicBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + + +} + + +// RT3883_AsicSetFreqOffset - set Frequency Offset register +void RT3883_AsicSetFreqOffset( + IN PRTMP_ADAPTER pAd, + IN ULONG freqOffset) +{ + UCHAR diff; + UCHAR RFValue, RFValue2 = 0; + + // Set RF offset RF_R17=RF_R23 (RT30xx) + RT30xxReadRFRegister(pAd, RF_R17, (PUCHAR)&RFValue); + if ((UCHAR)pAd->RfFreqOffset == RFValue) + return; + + //DBGPRINT(2, ("offset = %lx\n", freqOffset)); + RFValue2 = (RFValue & 0x80) | freqOffset; + + if (RFValue2 > RFValue) + { + for (diff = 1; diff <= (RFValue2 - RFValue); diff++) + RT30xxWriteRFRegister(pAd, RF_R17, (UCHAR)(RFValue + diff)); + } + else + { + for (diff = 1; diff <= (RFValue - RFValue2); diff++) + RT30xxWriteRFRegister(pAd, RF_R17, (UCHAR)(RFValue - diff)); + } +} + + +/* + ========================================================================== + Description: + + Load RF sleep-mode setup + + ========================================================================== + */ +static VOID RT3883LoadRFSleepModeSetup( + IN PRTMP_ADAPTER pAd) +{ + UCHAR RFValue; + + /* RF_BLOCK_en. RF R1 register Bit 0 to 0 */ + RT30xxReadRFRegister(pAd, RF_R01, &RFValue); + RFValue &= (~0x01); + RT30xxWriteRFRegister(pAd, RF_R01, RFValue); + + /* VCO_IC, R6[7:6]=[11] */ + RT30xxReadRFRegister(pAd, RF_R06, &RFValue); + RFValue &= (~0xC0); + RT30xxWriteRFRegister(pAd, RF_R06, RFValue); + + /* charge pump current control (cp_ic) RF R22[7:5] = [111] */ + RT30xxReadRFRegister(pAd, RF_R22, &RFValue); + RFValue &= (~0x20); + RT30xxWriteRFRegister(pAd, RF_R22, RFValue); + + /* RX_CTB_en, RF R46[5]=[1] */ + RT30xxReadRFRegister(pAd, RF_R46, &RFValue); + RFValue &= (~0x20); + RT30xxWriteRFRegister(pAd, RF_R46, RFValue); + + /* LDO pll_vc RF_R20[3:1] = [000] */ + RT30xxReadRFRegister(pAd, RF_R20, &RFValue); + RFValue |= 0xEE; + RT30xxWriteRFRegister(pAd, RF_R20, RFValue); + +} + + +/* + ========================================================================== + Description: + + Reverse RF sleep-mode setup + + ========================================================================== + */ +static VOID RT3883ReverseRFSleepModeSetup( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN FlgIsInitState) +{ + UCHAR RFValue; + + /* RF_BLOCK_en, RF R1 register Bit 0 to 1 */ + RT30xxReadRFRegister(pAd, RF_R01, &RFValue); + RFValue |= 0x01; + RT30xxWriteRFRegister(pAd, RF_R01, RFValue); + + /* VCO_IC, R6[7:6]=[11] */ + RT30xxReadRFRegister(pAd, RF_R06, &RFValue); + RFValue |= 0xC0; + RT30xxWriteRFRegister(pAd, RF_R06, RFValue); + + /* charge pump current control (cp_ic) RF R22[7:5] = [111] */ + RT30xxReadRFRegister(pAd, RF_R22, &RFValue); + RFValue |= 0x20; + RT30xxWriteRFRegister(pAd, RF_R22, RFValue); + + /* RX_CTB_en, RF R46[5]=[1] */ + RT30xxReadRFRegister(pAd, RF_R46, &RFValue); + RFValue |= 0x20; + RT30xxWriteRFRegister(pAd, RF_R46, RFValue); + + /* LDO pll_vc RF_R20[3:1] = [000] */ + RT30xxReadRFRegister(pAd, RF_R20, &RFValue); + RFValue = (RFValue & (~0xEE)); + RT30xxWriteRFRegister(pAd, RF_R20, RFValue); + + /* VCO tuning code readback RF_R03[7]=1 */ + /*RT30xxWriteRFRegister(pAd, RF_R08, 0x80); */ +} + + +static VOID RT3883HaltAction( + IN PRTMP_ADAPTER pAd) +{ + UINT32 TxPinCfg = 0x00050F0F; + + /* */ + /* Turn off LNA_PE or TRSW_POL */ + /* */ +#ifdef RTMP_EFUSE_SUPPORT + if (pAd->bUseEfuse) + TxPinCfg &= 0xFFFBF0F0; /* bit18 off */ + else +#endif /* RTMP_EFUSE_SUPPORT */ + TxPinCfg &= 0xFFFFF0F0; + /*RT30xxWriteRFRegister(pAd, RF_R08, (UCHAR)0x00); */ + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); +} + + +/* + ======================================================================== + + 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: RT3883 EEPROM V0.1 + + ======================================================================== +*/ +VOID RTMPRT3883ReadTxPwrPerRate( + IN PRTMP_ADAPTER pAd) +{ + UCHAR D0, D1, D2, D3; + USHORT value, value2; + int i; + + DBGPRINT(RT_DEBUG_TRACE, ("Txpower per Rate\n")); + /* 2.4G @20M 1M/2M/5.5M/11M/6M/9M/12M/18M */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_CCK_OFDM, value); /* EEPROM offset 0x140h */ + D0 = value & 0xF; /* 1M/2M */ + D1 = (value >> 4) & 0xF; /* 5.5M/11M */ + D2 = (value >> 8) & 0xF; /* 6M/9M */ + D3 = (value >> 12) & 0xF; /* 12M/18M */ + + value = (D1 << 12) | (D1 << 8) | (D0 << 4) | D0; /* bit 15:8 -> 5.5M/11M; bit 7:0 -> 1M/2M */ + value2 = (D3 << 12) | (D3 << 8) | (D2 << 4) | D2; /* bit 15:8 -> 12M/18M; bit 7:0 -> 6M/9M */ + + pAd->Tx20MPwrCfgGBand[0] = (value2 << 16) | value; /* TX_PWR_CFG_0, MAC 0x1314 */ + + /* 2.4G @40M 6M/9M/12M/18M */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_OFDM_2_4G, value2); /* EEPROM 150h */ + D0 = value2 & 0xF; /* Reserved */ + D1 = (value2 >> 4) & 0xF; /* Reserved */ + D2 = (value2 >> 8) & 0xF; /* 6M/9M */ + D3 = (value2 >> 12) & 0xF; /* 12M/18M */ + value2 = (D3 << 12) | (D3 << 8) | (D2 << 4) | D2; /* bit 15:8 -> 12M/18M; bit 7:0 -> 6M/9M */ + + pAd->Tx40MPwrCfgGBand[0] = (value2 << 16) | value; /* bit 15:0 is reserved, set to default value */ + + /* 5G @20M 6M/9M/12M/18M */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_OFDM_5G, value2); /* EEPROM 160h */ + D0 = value2 & 0xF; /* Reserved */ + D1 = (value2 >> 4) & 0xF; /* Reserved */ + D2 = (value2 >> 8) & 0xF; /* 6M/9M */ + D3 = (value2 >> 12) & 0xF; /* 12M/18M */ + value2 = (D3 << 12) | (D3 << 8) | (D2 << 4) | D2; /* bit 15:8 -> 12M/18M; bit 7:0 -> 6M/9M */ + + pAd->Tx20MPwrCfgABand[0] = (value2 << 16) | value; /* bit 15:0 is reserved, set to default value */ + + /* 5G @40M 6M/9M/12M/18M */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_OFDM_5G, value2); /* EEPROM 170h */ + D0 = value2 & 0xF; /* Reserved */ + D1 = (value2 >> 4) & 0xF; /* Reserved */ + D2 = (value2 >> 8) & 0xF; /* 6M/9M */ + D3 = (value2 >> 12) & 0xF; /* 12M/18M */ + value2 = (D3 << 12) | (D3 << 8) | (D2 << 4) | D2; /* bit 15:8 -> 12M/18M; bit 7:0 -> 6M/9M */ + + pAd->Tx40MPwrCfgABand[0] = (value2 << 16) | value; /* bit 15:0 is reserved, set to default value */ + + /* 2.4G @20M 24M/36M/48M */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_CCK_OFDM + 2, value); /* EEPROM 142h */ + D0 = value & 0xF; /* 24M/36M */ + D1 = (value >> 4) & 0xF; /* 48M */ + D2 = (value >> 8) & 0xF; /* 54M */ + D3 = (value >> 12) & 0xF; /* Reserved */ + value = (D1 << 12) | (D1 << 8) | (D0 << 4) | D0; /* bit 15:8 -> 48M; bit 7:0 -> 24M/36M */ + + pAd->Tx20MPwrCfgGBand[1] = value; /* TX_PWR_CFG_1, MAC 0x1318 */ + + /* 2.4G @40M 24M/36M/48M */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_OFDM_2_4G + 2, value); /* EEPROM 152h */ + D0 = value & 0xF; /* 24M/36M */ + D1 = (value >> 4) & 0xF; /* 48M */ + D2 = (value >> 8) & 0xF; /* 54M */ + D3 = (value >> 12) & 0xF; /* Reserved */ + value = (D1 << 12) | (D1 << 8) | (D0 << 4) | D0; /* bit 15:8 -> 48M; bit 7:0 -> 24M/36M */ + + pAd->Tx40MPwrCfgGBand[1] = value; /* TX_PWR_CFG_1, MAC 0x1318 */ + + /* 5G @20M 24M/36M/48M */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_OFDM_5G + 2, value); /* EEPROM 162h */ + D0 = value & 0xF; /* 24M/36M */ + D1 = (value >> 4) & 0xF; /* 48M */ + D2 = (value >> 8) & 0xF; /* 54M */ + D3 = (value >> 12) & 0xF; /* Reserved */ + value = (D1 << 12) | (D1 << 8) | (D0 << 4) | D0; /* bit 15:8 -> 48M; bit 7:0 -> 24M/36M */ + + pAd->Tx20MPwrCfgABand[1] = value; /* TX_PWR_CFG_1, MAC 0x1318 */ + + /* 5G @20M 24M/36M/48M */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_OFDM_5G + 2, value); /* EEPROM 172h */ + D0 = value & 0xF; /* 24M/36M */ + D1 = (value >> 4) & 0xF; /* 48M */ + D2 = (value >> 8) & 0xF; /* 54M */ + D3 = (value >> 12) & 0xF; /* Reserved */ + value = (D1 << 12) | (D1 << 8) | (D0 << 4) | D0; /* bit 15:8 -> 48M; bit 7:0 -> 24M/36M */ + + pAd->Tx40MPwrCfgABand[1] = value; /* TX_PWR_CFG_1, MAC 0x1318 */ + + /* 2.4G @20M, MCS0,1,2,3 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G, value); /* EEPROM 144h */ + D0 = value & 0xF; /* MCS 0,1 */ + D1 = (value >> 4) & 0xF; /* MCS 2,3 */ + D2 = (value >> 8) & 0xF; /* MCS 4,5 */ + D3 = (value >> 12) & 0xF; /* MCS 6 */ + value = (D1 << 12) | (D1 << 8) | (D0 << 4) | D0; /* bit 15:8 -> MCS 2,3; bit 7:0 -> MCS 0,1 */ + + pAd->Tx20MPwrCfgGBand[1] |= (value << 16); + + /* 2.4G @40M, MCS0,1,2,3 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G, value); /* EEPROM 154h */ + D0 = value & 0xF; /* MCS 0,1 */ + D1 = (value >> 4) & 0xF; /* MCS 2,3 */ + D2 = (value >> 8) & 0xF; /* MCS 4,5 */ + D3 = (value >> 12) & 0xF; /* MCS 6 */ + value = (D1 << 12) | (D1 << 8) | (D0 << 4) | D0; /* bit 15:8 -> MCS 2,3; bit 7:0 -> MCS 0,1 */ + + pAd->Tx40MPwrCfgGBand[1] |= (value << 16); + + /* 5G @20M, MCS0,1,2,3 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G, value); /* EEPROM 164h */ + D0 = value & 0xF; /* MCS 0, 1 */ + D1 = (value >> 4) & 0xF; /* MCS 2,3 */ + D2 = (value >> 8) & 0xF; /* MCS 4,5 */ + D3 = (value >> 12) & 0xF; /* MCS 6 */ + value = (D1 << 12) | (D1 << 8) | (D0 << 4) | D0; /* bit 15:8 -> MCS 2,3; bit 7:0 -> MCS 0,1 */ + + pAd->Tx20MPwrCfgABand[1] |= (value << 16); + + /* 5G @40M, MCS0,1,2,3 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G, value); /* EEPROM 174h */ + D0 = value & 0xF; /* MCS 0,1 */ + D1 = (value >> 4) & 0xF; /* MCS 2,3 */ + D2 = (value >> 8) & 0xF; /* MCS 4,5 */ + D3 = (value >> 12) & 0xF; /* MCS 6 */ + value = (D1 << 12) | (D1 << 8) | (D0 << 4) | D0; /* bit 15:8 -> MCS 2,3; bit 7:0 -> MCS 0,1 */ + + pAd->Tx40MPwrCfgABand[1] |= (value << 16); + + /* 2.4G @20M, MCS 4, 5, 6, 7, 8, 9, 10, 11 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + 1, value); /* EEPROM 145h */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + 3, value2); /* EEPROM 147h */ + D0 = value & 0xF; /* MCS 4,5 */ + D1 = (value >> 4) & 0xF; /* MCS 6 */ + D2 = (value >> 8) & 0xF; /* MCS 7 */ + D3 = (value >> 12) & 0xF; /* MCS 8,9 */ + value = (D1 << 12) | (D1 << 8) | (D0 << 4) | D0; /* bit 15:8 -> MCS 6; bit 7:0 -> MCS 4,5 */ + + D0 = value2 & 0xF; /* MCS 10,11 */ + value2 = (D0 << 12) | (D0 << 8) | (D3 << 4) | D3; /* bit 15:8 -> MCS 10,11; bit 7:0 -> MCS 8,9 */ + + pAd->Tx20MPwrCfgGBand[2] = (value2 << 16) | value; + + /* 2.4G @40M, MCS 4, 5, 6, 7, 8, 9, 10, 11 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 1, value); /* EEPROM 155h */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 3, value2); /* EEPROM 157h */ + D0 = value & 0xF; /* MCS 4,5 */ + D1 = (value >> 4) & 0xF; /* MCS 6 */ + D2 = (value >> 8) & 0xF; /* MCS 7 */ + D3 = (value >> 12) & 0xF; /* MCS 8,9 */ + value = (D1 << 12) | (D1 << 8) | (D0 << 4) | D0; /* bit 15:8 -> MCS 6; bit 7:0 -> MCS 4,5 */ + + D0 = value2 & 0xF; /* MCS 10,11 */ + value2 = (D0 << 12) | (D0 << 8) | (D3 << 4) | D3; /* bit 15:8 -> MCS 10,11; bit 7:0 -> MCS 8,9 */ + + pAd->Tx40MPwrCfgGBand[2] = (value2 << 16) | value; + + /* 5G @20M, MCS 4, 5, 6, 7, 8, 9, 10, 11 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 1, value); /* EEPROM 165h */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 3, value2); /* EEPROM 167h */ + D0 = value & 0xF; /* MCS 4,5 */ + D1 = (value >> 4) & 0xF; /* MCS 6 */ + D2 = (value >> 8) & 0xF; /* MCS 7 */ + D3 = (value >> 12) & 0xF; /* MCS 8,9 */ + value = (D1 << 12) | (D1 << 8) | (D0 << 4) | D0; /* bit 15:8 -> MCS 6; bit 7:0 -> MCS 4,5 */ + + D0 = value2 & 0xF; /* MCS 10,11 */ + value2 = (D0 << 12) | (D0 << 8) | (D3 << 4) | D3; /* bit 15:8 -> MCS 10,11; bit 7:0 -> MCS 8,9 */ + + pAd->Tx20MPwrCfgABand[2] = (value2 << 16) | value; + + /* 5G @40M, MCS 4, 5, 6, 7, 8, 9, 10, 11 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 1, value); /* EEPROM 175h */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 3, value2); /* EEPROM 177h */ + D0 = value & 0xF; /* MCS 4,5 */ + D1 = (value >> 4) & 0xF; /* MCS 6 */ + D2 = (value >> 8) & 0xF; /* MCS 7 */ + D3 = (value >> 12) & 0xF; /* MCS 8,9 */ + value = (D1 << 12) | (D1 << 8) | (D0 << 4) | D0; /* bit 15:8 -> MCS 6; bit 7:0 -> MCS 4,5 */ + + D0 = value2 & 0xF; /* MCS 10,11 */ + value2 = (D0 << 12) | (D0 << 8) | (D3 << 4) | D3; /* bit 15:8 -> MCS 10,11; bit 7:0 -> MCS 8,9 */ + + pAd->Tx40MPwrCfgABand[2] = (value2 << 16) | value; + + /* 2.4G @20M, MCS 12, 13, 14, STBC 0,1,2,3 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + 3, value); /* EEPROM 147h */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + 8, value2); /* EEPROM 14Ch */ + D0 = value & 0xF; /* MCS 10,11 */ + D1 = (value >> 4) & 0xF; /* MCS 12,13 */ + D2 = (value >> 8) & 0xF; /* MCS 14 */ + D3 = (value >> 12) & 0xF; /* MCS 15 */ + value = (D2 << 12) | (D2 << 8) | (D1 << 4) | D1; /* bit 15:8 -> MCS 14; bit 7:0 -> MCS 12,13 */ + + D0 = value2 & 0xF; /* STBC MCS 0,1 */ + D1 = (value2 >> 4) & 0xF; /* STBC MCS 2,3 */ + D2 = (value2 >> 8) & 0xF; /* STBC MCS 4,5 */ + D3 = (value2 >> 12) & 0xF; /* STBC MCS 6 */ + value2 = (D1 << 12) | (D1 << 8) |(D0 << 4) | D0; /* bit 15:8 STBC MCS 2,3; bit 7:0 -> STBC MCS 0,1 */ + + pAd->Tx20MPwrCfgGBand[3] = (value2 << 16) | value; + + /* 2.4G @40M, MCS 12, 13, 14, STBC 0,1,2,3 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 3, value); /* EEPROM 157h */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 8, value2); /* EEPROM 15Ch */ + D0 = value & 0xF; /* MCS 10,11 */ + D1 = (value >> 4) & 0xF; /* MCS 12,13 */ + D2 = (value >> 8) & 0xF; /* MCS 14 */ + D3 = (value >> 12) & 0xF; /* MCS 15 */ + value = (D2 << 12) | (D2 << 8) | (D1 << 4) | D1; /* bit 15:8 -> MCS 14; bit 7:0 -> MCS 12,13 */ + + D0 = value2 & 0xF; /* STBC MCS 0,1 */ + D1 = (value2 >> 4) & 0xF; /* STBC MCS 2,3 */ + D2 = (value2 >> 8) & 0xF; /* STBC MCS 4,5 */ + D3 = (value2 >> 12) & 0xF; /* STBC MCS 6 */ + value2 = (D1 << 12) | (D1 << 8) | (D0 << 4) | D0; /* bit 15:8 -> STBC MCS 2,3; bit 7:0 -> STBC MCS 0,1 */ + pAd->Tx40MPwrCfgGBand[3] = (value2 << 16) | value; + + /* 5G @20M, MCS 12, 13, 14, STBC 0,1,2,3 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 3, value); /* EEPROM 167h */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 8, value2); /* EEPROM 16Ch */ + D0 = value & 0xF; /* MCS 10,11 */ + D1 = (value >> 4) & 0xF; /* MCS 12,13 */ + D2 = (value >> 8) & 0xF; /* MCS 14 */ + D3 = (value >> 12) & 0xF; /* MCS 15 */ + value = (D2 << 12) | (D2 << 8) | (D1 << 4) | D1; /* bit 15:8 -> MCS 14; bit 7:0 -> MCS 12,13 */ + + D0 = value2 & 0xF; /* STBC MCS 0,1 */ + D1 = (value2 >> 4) & 0xF; /* STBC MCS 2,3 */ + D2 = (value2 >> 8) & 0xF; /* STBC MCS 4,5 */ + D3 = (value2 >> 12) & 0xF; /* STBC MCS 6 */ + value2 = (D1 << 12) | (D1 << 8) | (D0 << 4) | D0; /* bit 15:8 -> STBC MCS 2,3; bit 7:0 -> STBC MCS 0,1 */ + pAd->Tx20MPwrCfgABand[3] = (value2 << 16) | value; + + /* 5G @40M, MCS 12, 13, 14, STBC 0,1,2,3 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 3, value); /* EEPROM 177h */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 8, value2); /* EEPROM 17Ch */ + D0 = value & 0xF; /* MCS 10,11 */ + D1 = (value>>4) & 0xF; /* MCS 12,13 */ + D2 = (value>>8) & 0xF; /* MCS 14 */ + D3 = (value>>12) & 0xF; /* MCS 15 */ + value = (D2 << 12) | (D2 << 8) | (D1 << 4) | D1; /* bit 15:8 -> MCS 14; bit 7:0 -> MCS 12,13 */ + + D0 = value2 & 0xF; /* STBC MCS 0,1 */ + D1 = (value2 >> 4) & 0xF; /* STBC MCS 2,3 */ + D2 = (value2 >> 8) & 0xF; /* STBC MCS 4,5 */ + D3 = (value2 >> 12) & 0xF; /* STBC MCS 6 */ + value2 = (D1 << 12) |(D1 << 8) | (D0 << 4) | D0; /* bit 15:8 -> STBC MCS 2,3; bit 7:0 -> STBC MCS 0,1 */ + pAd->Tx40MPwrCfgABand[3] = (value2 << 16) | value; + + /* 2.4G @20M, STBC 4,5,6 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + 9, value); /* EEPROM 14Dh */ + D0 = value & 0xF; /* STBC MCS 4,5 */ + D1 = (value >> 4) & 0xF; /* STBC MCS 6 */ + D2 = (value >> 8) & 0xF; /* STBC MCS 7 */ + D3 = (value >> 12) & 0xF; /* Reserved */ + value = (D1 << 12) | (D1 << 8) | (D0 << 4) | D0; /* bit 15:8 -> STBC MCS 6; bit 7:0 -> STBC MCS 4,5 */ + pAd->Tx20MPwrCfgGBand[4] = value & 0x0000ffff; + + /* 2.4G @40M, STBC 4,5,6 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 9, value); /* EEPROM 15Dh */ + D0 = value & 0xF; /* STBC MCS 4,5 */ + D1 = (value >> 4) & 0xF; /* STBC MCS 6 */ + D2 = (value >> 8) & 0xF; /* STBC MCS 7 */ + D3 = (value >> 12) & 0xF; /* Reserved */ + value = (D1 << 12) | (D1 << 8) | (D0 << 4) | D0; /* bit 15:8 -> STBC MCS 6; bit 7:0 -> STBC MCS 4,5 */ + pAd->Tx40MPwrCfgGBand[4] = value & 0x0000ffff; + + /* 5G @20M, STBC 4,5,6 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 9, value); /* EEPROM 16Dh */ + D0 = value & 0xF; /* STBC MCS 4,5 */ + D1 = (value >> 4) & 0xF; /* STBC MCS 6 */ + D2 = (value >> 8) & 0xF; /* STBC MCS 7 */ + D3 = (value >> 12) & 0xF; /* Reserved */ + value = (D1 << 12) | (D1 << 8) | (D0 << 4) | D0; /* bit 15:8 -> STBC MCS 6; bit 7:0 -> STBC MCS 4,5 */ + pAd->Tx20MPwrCfgABand[4] = value & 0x0000ffff; + + /* 5G @40M, STBC 4,5,6 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 9, value); /* EEPROM 17Dh */ + D0 = value & 0xF; /* STBC MCS 4,5 */ + D1 = (value >> 4) & 0xF; /* STBC MCS 6 */ + D2 = (value >> 8) & 0xF; /* STBC MCS 7 */ + D3 = (value >> 12) & 0xF; /* Reserved */ + value = (D1 << 12) | (D1 << 8) | (D0 << 4) | D0; /* bit 15:8 -> STBC MCS 6; bit 7:0 -> STBC MCS 4,5 */ + pAd->Tx40MPwrCfgABand[4] = value & 0x0000ffff; + + + /* 2.4G @20M, MCS 16,17,18,19,20,21,22 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + 5, value); /* EEPROM 149h */ + D0 = value & 0xF; /* MCS 16,17 */ + D1 = (value >> 4) & 0xF; /* MCS 18,19 */ + D2 = (value >> 8) & 0xF; /* MCS 20,21 */ + D3 = (value >> 12) & 0xF; /* MCS 22 */ + + /* Bit 11:8 -> MCS 16,17; Bit 7:4 -> MCS 16,17; bit 3:0 -> MCS 16,17 */ + value = (D0 << 8) | (D0 << 4) | D0; + /* Bit 27:24 MCS -> 18,19; Bit 23:20 MCS -> MCS 18,19; bit 19:16 -> MCS 18,19 */ + value2 = (D1 << 8) | (D1 << 4) | D1; + pAd->Tx20MPwrCfgGBand[5] = ((value2 << 16) | value) & 0x0fff0fff; + + /* Bit 11:8 -> MCS 20,21; Bit 7:4 -> MCS 20,21; bit 3:0 -> MCS 20,21 */ + value = (D2 << 8) | (D2 << 4) | D2; + /* Bit 27:24 -> MCS 22; Bit 23:20 -> MCS 22; bit 19:16 -> MCS 22 */ + value2 = (D3 << 8) | (D3 << 4) | D3; + pAd->Tx20MPwrCfgGBand[6] = ((value2 << 16) | value) & 0x0fff0fff; + + /* 2.4G @40M, MCS 16,17,18,19,20,21,22 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 5, value); /* EEPROM 159h */ + D0 = value & 0xF; /* MCS 16,17 */ + D1 = (value >> 4) & 0xF; /* MCS 18,19 */ + D2 = (value >> 8) & 0xF; /* MCS 20,21 */ + D3 = (value >> 12) & 0xF; /* MCS 22 */ + + /* Bit 11:8 MCS -> 16,17; Bit 7:4 MCS -> MCS 16,17; bit 3:0 -> MCS 16,17 */ + value = (D0 << 8) | (D0 << 4) | D0; + /* Bit 27:24 MCS -> 18,19; Bit 23:20 MCS -> MCS 18,19; bit 19:16 -> MCS 18,19 */ + value2 = (D1 << 8) | (D1 << 4) |D1; + pAd->Tx40MPwrCfgGBand[5] = ((value2 << 16) | value) & 0x0fff0fff; + + /* Bit 11:8 -> MCS 20,21; Bit 7:4 -> MCS 20,21; bit 3:0 -> MCS 20,21 */ + value = (D2 << 8) | (D2 << 4) | D2; + /* Bit 27:24 -> MCS 22; Bit 23:20 -> MCS 22; bit 19:16 -> MCS 22 */ + value2 = (D3 << 8) | (D3 << 4) | D3; + pAd->Tx40MPwrCfgGBand[6] = ((value2 << 16) | value) & 0x0fff0fff; + + /* 5G @20M, MCS 16,17,18,19,20,21,22 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 5, value); /* EEPROM 169h */ + D0 = value & 0xF; /* MCS 16,17 */ + D1 = (value >> 4) & 0xF; /* MCS 18,19 */ + D2 = (value >> 8) & 0xF; /* MCS 20,21 */ + D3 = (value >> 12) & 0xF; /* MCS 22 */ + + /* Bit 11:8 MCS -> 16,17; Bit 7:4 MCS -> MCS 16,17; bit 3:0 -> MCS 16,17 */ + value = (D0 << 8) | (D0 << 4) | D0; + /* Bit 27:24 MCS -> 18,19; Bit 23:20 MCS -> MCS 18,19; bit 19:16 -> MCS 18,19 */ + value2 = (D1 << 8) | (D1 << 4) | D1; + pAd->Tx20MPwrCfgABand[5] = ((value2 << 16) | value) & 0x0fff0fff; + + /* Bit 11:8 -> MCS 20,21; Bit 7:4 -> MCS 20,21; bit 3:0 -> MCS 20,21 */ + value = (D2 << 8) | (D2 << 4) | D2; + /* Bit 27:24 -> MCS 22; Bit 23:20 -> MCS 22; bit 19:16 -> MCS 22 */ + value2 = (D3 << 8) | (D3 << 4) | D3; + pAd->Tx20MPwrCfgABand[6] = ((value2 << 16) | value) & 0x0fff0fff; + + /* 5G @40M, MCS 16,17,18,19,20,21,22 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 5, value); /* EEPROM 179h */ + D0 = value & 0xF; /* MCS 16,17 */ + D1 = (value >> 4) & 0xF; /* MCS 18,19 */ + D2 = (value >> 8) & 0xF; /* MCS 20,21 */ + D3 = (value >> 12) & 0xF; /* MCS 22 */ + + /* Bit 11:8 MCS -> 16,17; Bit 7:4 MCS -> MCS 16,17; bit 3:0 -> MCS 16,17 */ + value = (D0 << 8) | (D0 << 4) | D0; + /* Bit 27:24 MCS -> 18,19; Bit 23:20 MCS -> MCS 18,19; bit 19:16 -> MCS 18,19 */ + value2 = (D1 << 8) | (D1 << 4) | D1; + pAd->Tx40MPwrCfgABand[5] = ((value2 << 16) | value) & 0x0fff0fff; + + /* Bit 11:8 -> MCS 20,21; Bit 7:4 -> MCS 20,21; bit 3:0 -> MCS 20,21 */ + value = (D2 << 8) | (D2 << 4) | D2; + /* Bit 27:24 -> MCS 22; Bit 23:20 -> MCS 22; bit 19:16 -> MCS 22 */ + value2 = (D3 << 8) | (D3 << 4) | D3; + pAd->Tx40MPwrCfgABand[6] = ((value2 << 16) | value) & 0x0fff0fff; + + /* 2.4G @20M, MCS 7, OFDM 54M */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_CCK_OFDM + 3, value); /* EEPROM 143h */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + 2, value2); /* EEPROM 146h */ + D0 = value & 0xF; /* OFDM 54M */ + D1 = (value >> 4) & 0xF; /* Reserved */ + value = (D0 << 8) | (D0 << 4) | D0; + + D0 = value2 & 0xF; /* MCS 7 */ + value2 = (D0 << 8) | (D0 << 4) | D0; + + pAd->Tx20MPwrCfgGBand[7] = (((value2 << 16) | value) & 0x0fff0fff); + + /* 2.4G @40M, MCS 7, OFDM 54M */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_OFDM_2_4G + 3, value); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 2, value2); + /* convert TxPwr from RT3883 format to original format for firmware */ + D0 = value & 0xF; D1 = (value>>4) & 0xF; D2 = (value>>8) & 0xF; D3 = (value>>12) & 0xF; + value = (D0<<8) | (D0<<4) | D0; /* OFDM 54M */ + + D0 = value2 & 0xF; D1 = (value2>>4) & 0xF; D2 = (value2>>8) & 0xF; D3 = (value2>>12) & 0xF; + value2 = (D0<<8) | (D0<<4) | D0; /* MCS 7 */ + + pAd->Tx40MPwrCfgGBand[7] = (((value2 << 16) | value) & 0x0fff0fff); + + /* 5G @20M, MCS 7, OFDM 54M */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_OFDM_5G + 3, value); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 2, value2); + /* convert TxPwr from RT3883 format to original format for firmware */ + D0 = value & 0xF; D1 = (value>>4) & 0xF; D2 = (value>>8) & 0xF; D3 = (value>>12) & 0xF; + value = (D0<<8) | (D0<<4) | D0; /* OFDM 54M */ + + D0 = value2 & 0xF; D1 = (value2>>4) & 0xF; D2 = (value2>>8) & 0xF; D3 = (value2>>12) & 0xF; + value2 = (D0<<8) | (D0<<4) | D0; /* MCS 7 */ + + pAd->Tx20MPwrCfgABand[7] = (((value2 << 16) | value) & 0x0fff0fff); + + /* 5G @40M, MCS 7 OFDM 54M */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_OFDM_5G + 3, value); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 2, value2); + /* convert TxPwr from RT3883 format to original format for firmware */ + D0 = value & 0xF; D1 = (value>>4) & 0xF; D2 = (value>>8) & 0xF; D3 = (value>>12) & 0xF; + value = (D0<<8) | (D0<<4) | D0; /* OFDM 54M */ + + D0 = value2 & 0xF; D1 = (value2>>4) & 0xF; D2 = (value2>>8) & 0xF; D3 = (value2>>12) & 0xF; + value2 = (D0<<8) | (D0<<4) | D0; /* MCS 7 */ + + pAd->Tx40MPwrCfgABand[7] = (((value2 << 16) | value) & 0x0fff0fff); + + /* 2.4G @20M, MCS 15, MCS 23 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + 4, value); /* EEPROM 148h */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + 6, value2); /* EEPROM 14Ah */ + D0 = value & 0xF; /* MCS 14 */ + D1 = (value >> 4) & 0xF; /* MCS 15 */ + value = (D1 << 8) | (D1 << 4) | D1; + + D2 = (value2 >> 8) & 0xF; /* MCS 23 */ + value2 = (D2 << 8) | (D2 << 4) | D2; + + pAd->Tx20MPwrCfgGBand[8] = (((value2 << 16) | value) & 0x0fff0fff); + + /* 2.4G @40M, MCS 7, OFDM 54M */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 4, value); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 6, value2); + D0 = value & 0xF; /* MCS 14 */ + D1 = (value >> 4) & 0xF; /* MCS 15 */ + value = (D1 << 8) | (D1 << 4) | D1; + + D2 = (value2 >> 8) & 0xF; /* MCS 23 */ + value2 = (D2 << 8) | (D2 << 4) | D2; + + pAd->Tx40MPwrCfgGBand[8] = (((value2 << 16) | value) & 0x0fff0fff); + + /* 5G @40M, MCS 15, MCS 23 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 4, value); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 6, value2); + D0 = value & 0xF; /* MCS 14 */ + D1 = (value >> 4) & 0xF; /* MCS 15 */ + value = (D1 << 8) | (D1 << 4) | D1; + + D2 = (value2 >> 8) & 0xF; /* MCS 23 */ + value2 = (D2 << 8) | (D2 << 4) | D2; + + pAd->Tx20MPwrCfgABand[8] = (((value2 << 16) | value) & 0x0fff0fff); + + /* 5G @40M, MCS 15, MCS 23 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 4, value); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 6, value2); + D0 = value & 0xF; /* MCS 14 */ + D1 = (value >> 4) & 0xF; /* MCS 15 */ + value = (D1 << 8) | (D1 << 4) | D1; + + D2 = (value2 >> 8) & 0xF; /* MCS 23 */ + value2 = (D2 << 8) | (D2 << 4) | D2; + + pAd->Tx40MPwrCfgABand[8] = (((value2 << 16) | value) & 0x0fff0fff); + + /* 2.4G @20M, STBC MCS 7 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + 10, value); + /* convert TxPwr from RT3883 format to original format for firmware */ + D0 = value & 0xF; D1 = (value>>4) & 0xF; D2 = (value>>8) & 0xF; D3 = (value>>12) & 0xF; + + value = (D0<<8) | (D0<<4) | D0; /* STBC MCS 7 */ + pAd->Tx20MPwrCfgGBand[9] = (value & 0x00000fff); + + /* 2.4G @40M, STBC MCS 7 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 10, value); + /* convert TxPwr from RT3883 format to original format for firmware */ + D0 = value & 0xF; D1 = (value>>4) & 0xF; D2 = (value>>8) & 0xF; D3 = (value>>12) & 0xF; + + value = (D0<<8) | (D0<<4) | D0; /* STBC MCS 7 */ + pAd->Tx40MPwrCfgGBand[9] = (value & 0x00000fff); + + /* 5G @20M, STBC MCS 7 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 10, value); + /* convert TxPwr from RT3883 format to original format for firmware */ + D0 = value & 0xF; D1 = (value>>4) & 0xF; D2 = (value>>8) & 0xF; D3 = (value>>12) & 0xF; + + value = (D0<<8) | (D0<<4) | D0; /* STBC MCS 7 */ + pAd->Tx20MPwrCfgABand[9] = (value & 0x00000fff); + + /* 5G @40M, STBC MCS 7 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 10, value); + /* convert TxPwr from RT3883 format to original format for firmware */ + D0 = value & 0xF; D1 = (value>>4) & 0xF; D2 = (value>>8) & 0xF; D3 = (value>>12) & 0xF; + + value = (D0<<8) | (D0<<4) | D0; /* STBC MCS 7 */ + pAd->Tx40MPwrCfgABand[9] = (value & 0x00000fff); + + for (i = 0; i < MAX_TXPOWER_ARRAY_SIZE; i++) { + DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 2.4G band, %d = %lx \n", i, pAd->Tx20MPwrCfgGBand[i])); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("40MHz BW, 2.4G band, %d = %lx \n", i, pAd->Tx40MPwrCfgGBand[i])); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 5G band, %d = %lx \n", i, pAd->Tx20MPwrCfgABand[i])); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("40MHz BW, 5G band, %d = %lx \n", i, pAd->Tx40MPwrCfgABand[i])); + } + + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0, pAd->Tx40MPwrCfgABand[0]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_1, pAd->Tx40MPwrCfgABand[1]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_2, pAd->Tx40MPwrCfgABand[2]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_3, pAd->Tx40MPwrCfgABand[3]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_4, pAd->Tx40MPwrCfgABand[4]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_5, pAd->Tx40MPwrCfgABand[5]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_6, pAd->Tx40MPwrCfgABand[6]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_7, pAd->Tx40MPwrCfgABand[7]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_8, pAd->Tx40MPwrCfgABand[8]); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_9, pAd->Tx40MPwrCfgABand[9]); + + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0_EXT, (pAd->Tx40MPwrCfgABand[0] & 0xf0f0f0f0) >> 4); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_1_EXT, (pAd->Tx40MPwrCfgABand[1] & 0xf0f0f0f0) >> 4); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_2_EXT, (pAd->Tx40MPwrCfgABand[2] & 0xf0f0f0f0) >> 4); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_3_EXT, (pAd->Tx40MPwrCfgABand[3] & 0xf0f0f0f0) >> 4); + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_4_EXT, (pAd->Tx40MPwrCfgABand[4] & 0xf0f0f0f0) >> 4); +} + + +/* + ======================================================================== + + Routine Description: + Read initial channel power parameters from EEPROM + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPRT3883ReadChannelPwr( + IN PRTMP_ADAPTER pAd) +{ + UCHAR i, choffset; + EEPROM_TX_PWR_STRUC Power; + EEPROM_TX_PWR_STRUC Power2; + EEPROM_TX_PWR_STRUC Power3; + + /* + 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 0x00 (0) ~ 0x1F (31) +*/ + + /* 0. 11b/g, ch1 - ch 14 */ + for (i = 0; i < 7; i++) + { + 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); + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX3_PWR_OFFSET + i * 2, Power3.word); + pAd->TxPower[i * 2].Channel = i * 2 + 1; + pAd->TxPower[i * 2 + 1].Channel = i * 2 + 2; + + if ((Power.field.Byte0 > 31) || (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 > 31) || (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 ((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 ((Power3.field.Byte0 > 31) || (Power3.field.Byte0 < 0)) + pAd->TxPower[i * 2].Power3 = DEFAULT_RF_TX_POWER; + else + pAd->TxPower[i * 2].Power3 = Power3.field.Byte0; + + if ((Power3.field.Byte1 > 31) || (Power3.field.Byte1 < 0)) + pAd->TxPower[i * 2 + 1].Power3 = DEFAULT_RF_TX_POWER; + else + pAd->TxPower[i * 2 + 1].Power3 = Power3.field.Byte1; + } + + /* 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 + 0].Power3 = 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 + 1].Power3 = 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; + pAd->TxPower[3 * i + choffset + 2].Power3 = 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); */ + 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); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX3_PWR_OFFSET + i * 2, Power3.word); + + if ((Power.field.Byte0 <= 31) && (Power.field.Byte0 >= 0)) + pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0; + + if ((Power.field.Byte1 <= 31) && (Power.field.Byte1 >= 0)) + pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1; + + if ((Power2.field.Byte0 <= 31) && (Power2.field.Byte0 >= 0)) + pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0; + + if ((Power2.field.Byte1 <= 31) && (Power2.field.Byte1 >= 0)) + pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1; + + if ((Power3.field.Byte0 <= 31) && (Power3.field.Byte0 >= 0)) + pAd->TxPower[i * 2 + choffset + 0].Power3 = Power3.field.Byte0; + + if ((Power3.field.Byte1 <= 31) && (Power3.field.Byte1 >= 0)) + pAd->TxPower[i * 2 + choffset + 1].Power3 = Power3.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 + 0].Power3 = 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 + 1].Power3 = 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 * i + choffset + 2].Power3 = 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; + pAd->TxPower[3 * 5 + choffset + 0].Power3 = 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); */ + 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); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX3_PWR_OFFSET + (choffset - 14) + i * 2, Power3.word); + + if ((Power.field.Byte0 <= 31) && (Power.field.Byte0 >= 0)) + pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0; + + if ((Power.field.Byte1 <= 31) && (Power.field.Byte1 >= 0)) + pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1; + + if ((Power2.field.Byte0 <= 31) && (Power2.field.Byte0 >= 0)) + pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0; + + if ((Power2.field.Byte1 <= 31) && (Power2.field.Byte1 >= 0)) + pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1; + + if ((Power3.field.Byte0 <= 31) && (Power3.field.Byte0 >= 0)) + pAd->TxPower[i * 2 + choffset + 0].Power3 = Power3.field.Byte0; + + if ((Power3.field.Byte1 <= 31) && (Power3.field.Byte1 >= 0)) + pAd->TxPower[i * 2 + choffset + 1].Power3 = Power3.field.Byte1; + } + + /* 3. U-NII upper band: 149, 151, 153; 157, 159, 161; 165 (including central frequency in BW 40MHz) */ + /* 3.1 Fill up channel */ + choffset = 14 + 12 + 16; + for (i = 0; i < 2; 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 + 0].Power3 = 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 + 1].Power3 = 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 * i + choffset + 2].Power3 = DEFAULT_RF_TX_POWER; + } + pAd->TxPower[3 * 2 + choffset + 0].Channel = 165; + pAd->TxPower[3 * 2 + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * 2 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * 2 + choffset + 0].Power3 = DEFAULT_RF_TX_POWER; + + /* 3.2 Fill up power */ + for (i = 0; i < 4; 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); */ + 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); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX3_PWR_OFFSET + (choffset - 14) + i * 2, Power3.word); + + if ((Power.field.Byte0 <= 31) && (Power.field.Byte0 >= 0)) + pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0; + + if ((Power.field.Byte1 <= 31) && (Power.field.Byte1 >= 0)) + pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1; + + if ((Power2.field.Byte0 <= 31) && (Power2.field.Byte0 >= 0)) + pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0; + + if ((Power2.field.Byte1 <= 31) && (Power2.field.Byte1 >= 0)) + pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1; + + if ((Power3.field.Byte0 <= 31) && (Power3.field.Byte0 >= 0)) + pAd->TxPower[i * 2 + choffset + 0].Power3 = Power3.field.Byte0; + + if ((Power3.field.Byte1 <= 31) && (Power3.field.Byte1 >= 0)) + pAd->TxPower[i * 2 + choffset + 1].Power3 = Power3.field.Byte1; + } + + /* 4. Print and Debug */ + choffset = 14 + 12 + 16 + 7; +} + + +/* ATE will also call this function to set GPIO, channel=36 to set low and channel=1 to set high */ +VOID RTMPRT3883ABandSel( + IN UCHAR Channel) +{ + UINT32 value; + + + /*set GPIO2(gpio#25) to GPIO mode */ + value = le32_to_cpu(*(volatile u32 *)(0xb0000014)); + value &= ~(1 << 2); + *((volatile uint32_t *)(0xb0000014)) = cpu_to_le32(value); + + /*config gpio#25 direction to output */ + value = le32_to_cpu(*(volatile u32 *)(0xb000064c)); + value |= (1 << 1); + *((volatile uint32_t *)(0xb000064c)) = cpu_to_le32(value); + + if (Channel > 14) + { + /*5G band: clear gpio#25 to 0 */ + *((volatile uint32_t *)(0xb0000658)) = cpu_to_le32(0x2); + } + else + { + /*2.4G band: set gpio#25 to 1 */ + *((volatile uint32_t *)(0xb0000654)) = cpu_to_le32(0x2); + } +} + + +static VOID RT3883_AsicEeBufferInit( + IN RTMP_ADAPTER *pAd) +{ + //extern UCHAR *EeBuffer; + +#ifdef RTMP_FLASH_SUPPORT + /* pAd->eebuf = RT3883_EeBuffer;*/ + /* EeBuffer = RT3883_EeBuffer;*/ +#endif /* RTMP_FLASH_SUPPORT */ + +} + + +static VOID RT3883_ChipSwitchChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel, + IN BOOLEAN bScan) +{ + int index, i; + CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER, TxPwer3 = 0, lanGain; + UINT32 mac_val; + UINT32 TxPinCfg; + UINT8 RFValue = 0, BbpValue = 0;; + + /* Search Tx power value*/ + /* + 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; + TxPwer3 = pAd->TxPower[index].Power3; + break; + } + } + + if (index == MAX_NUM_OF_CHANNELS) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Can't find the Channel#%d \n", __FUNCTION__, Channel)); + } + + RTMPRT3883ABandSel(Channel); + for (index = 0; index < NUM_OF_3883_CHNL; index++) + { + if (Channel == FreqItems3883[index].Channel) + { + /* RF_R06 for A-Band L:0x80 M:0x80 H:0x40 (Gary, 2010-06-02) */ + if (pAd->CommonCfg.Channel <= 14) + RFValue = 0x40; + else + { + if (pAd->CommonCfg.Channel <132) + RFValue = 0x80; + else + RFValue = 0x40; + } + RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RFValue); + + /* Programming channel parameters*/ + RT30xxWriteRFRegister(pAd, RF_R08, FreqItems3883[index].N); + RT30xxWriteRFRegister(pAd, RF_R09, FreqItems3883[index].K); + + RFValue = (Channel <= 14) ? 0x46 : 0x48; + RT30xxWriteRFRegister(pAd, RF_R11, (UCHAR)RFValue); + + /* Gary, 2011-03-10 */ + RFValue = (Channel <= 14) ? 0x1a : 0x52; + RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue); + + RT30xxWriteRFRegister(pAd, RF_R13, 0x12); + + /* Tx/Rx Stream setting*/ + RT30xxReadRFRegister(pAd, RF_R01, (PUCHAR)&RFValue); + RFValue &= 0x03; /*clear bit[7~2]*/ + RFValue |= 0xFC; /* default 3Tx 3Rx*/ + if (pAd->Antenna.field.TxPath == 1) + RFValue &= ~(0x5 << 5); + else if (pAd->Antenna.field.TxPath == 2) + RFValue &= ~(0x1 << 7); + else if (pAd->Antenna.field.TxPath == 3) /*wayne_note: 090826 need to consider TxPath=3, for 3883 case*/ + RFValue &= ~(0x0 << 7); + + if (pAd->Antenna.field.RxPath == 1) + RFValue &= ~(0x5 << 4); + else if (pAd->Antenna.field.RxPath == 2) + RFValue &= ~(0x1 << 6); + else if (pAd->Antenna.field.RxPath == 3) /*wayne_note: 090826 need to consider TxPath=3, for 3883 case*/ + RFValue &= ~(0x0 << 6); + RT30xxWriteRFRegister(pAd, RF_R01, (UCHAR)RFValue); + + RT3883_AsicSetFreqOffset(pAd, pAd->RfFreqOffset); + + /* Different default setting for A/BG bands*/ + RT30xxReadRFRegister(pAd, RF_R30, (PUCHAR)&RFValue); + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + RFValue &= ~(0x06); /* 20MBW Bit[2:1]=0,0*/ + else + RFValue |= 0x06; + RT30xxWriteRFRegister(pAd, RF_R30, (UCHAR)RFValue); + + RFValue = (Channel <= 14) ? 0xA0 : 0x80; + RT30xxWriteRFRegister(pAd, RF_R31, (UCHAR)RFValue); + + RFValue = ((pAd->CommonCfg.BBPCurrentBW == BW_40) ? 0x80 : 0xd8); + RT30xxWriteRFRegister(pAd, RF_R32, RFValue); + + RFValue = (Channel <= 14) ? 0x3C : 0x20; + RT30xxWriteRFRegister(pAd, RF_R34, (UCHAR)RFValue); + + /* loopback RF_BS*/ + RT30xxReadRFRegister(pAd, RF_R36, (PUCHAR)&RFValue); + RFValue &= ~(0x1 << 7); + if (Channel <= 14) + RT30xxWriteRFRegister(pAd, RF_R36, (UCHAR)(RFValue | (0x1 << 7))); + else + RT30xxWriteRFRegister(pAd, RF_R36, (UCHAR)RFValue); + + /* RF_R39 for A-Band L:0x36 M:0x32 H:0x30 (Gary, 2010-02-12)*/ + if (pAd->CommonCfg.Channel <= 14) + RFValue = 0x23; + else + { + if (pAd->CommonCfg.Channel < 100) + RFValue = 0x36; + else if (pAd->CommonCfg.Channel < 132) + RFValue = 0x32; + else + RFValue = 0x30; + /* RT30xxWriteRFRegister(pAd, RF_R39, (UCHAR)RFValue); */ + } +#ifdef TXBF_SUPPORT + if (pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn || pAd->CommonCfg.ETxBfEnCond) + RFValue |= 0x40; +#endif /* TXBF_SUPPORT */ + RT30xxWriteRFRegister(pAd, RF_R39, (UCHAR)RFValue); + + /* loopback RF_BS*/ + RFValue = (Channel <= 14) ? 0x93 : 0x9b; /* Gary, 2010-02-12*/ + RT30xxWriteRFRegister(pAd, RF_R44, (UCHAR)RFValue); + + /* RF_R45 for A-Band L:0xEB M:0xB3 H:0x9B (Gary, 2010-02-12)*/ + if (pAd->CommonCfg.Channel <= 14) + RFValue = 0xBB; + else + { + if (pAd->CommonCfg.Channel <100) + RFValue = 0xEB; + else if(pAd->CommonCfg.Channel <132) + RFValue = 0xB3; + else + RFValue = 0x9B; + } + RT30xxWriteRFRegister(pAd, RF_R45, (UCHAR)RFValue); + + RFValue = (Channel <= 14) ? 0x8e : 0x8a; +#ifdef TXBF_SUPPORT + if ((pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn) || (pAd->CommonCfg.ETxBfEnCond)) + RFValue |= 0x20; +#endif /* TXBF_SUPPORT */ + RT30xxWriteRFRegister(pAd, RF_R49, (UCHAR)RFValue); + + RT30xxWriteRFRegister(pAd, RF_R50, 0x86); + + /* tx_mx1_ic*/ + RT30xxReadRFRegister(pAd, RF_R51, (PUCHAR)&RFValue); + RFValue = (Channel <= 14) ? 0x75 : 0x51; + RT30xxWriteRFRegister(pAd, RF_R51, (UCHAR)RFValue); + + RT30xxReadRFRegister(pAd, RF_R52, (PUCHAR)&RFValue); + RFValue = (Channel <= 14) ? 0x45 : 0x05; + RT30xxWriteRFRegister(pAd, RF_R52, (UCHAR)RFValue); + + for (i = 0; i < MAX_NUM_OF_CHANNELS; i++) + { + CHAR power[3], ant_idx, delta; + + if (Channel != pAd->TxPower[i].Channel) + continue; + + power[0]= pAd->TxPower[i].Power; + power[1]= pAd->TxPower[i].Power2; + power[2]= pAd->TxPower[i].Power3; + + if ((pAd->NicConfig2.field.DynamicTxAgcControl == 1) && + (power[0] <= 0x1b) && (power[1] <= 0x1b) && (power[2] <= 0x1b)) + { + pAd->bTxPwrRangeExt = TRUE; + delta = 4; + } + else + { + pAd->bTxPwrRangeExt = FALSE; + delta = 0; + } + + for ( ant_idx = 0; ant_idx < 3; ant_idx++) { + power[ant_idx] += delta; + if (Channel > 14) + power[ant_idx] = TX_PWR_TO_RF_REG(power[ant_idx]); + } + + RT30xxWriteRFRegister(pAd, RF_R53, power[0]); + RT30xxWriteRFRegister(pAd, RF_R54, power[1]); + RT30xxWriteRFRegister(pAd, RF_R55, power[2]); + + /* tx0, tx1 (0.1db)*/ + BbpValue = (pAd->TxPower[index].Power >> 5) | ((pAd->TxPower[index].Power2 & 0xE0) >> 1); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R109, BbpValue); + + /* tx2 (0.1db)*/ + BBP_IO_READ8_BY_REG_ID(pAd, BBP_R110, &BbpValue); + BbpValue = ((pAd->TxPower[index].Power3 & 0xE0) >> 1) | (BbpValue & 0x0F); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R110, BbpValue); + + break; + } + + RT30xxReadRFRegister(pAd, RF_R57, (PUCHAR)&RFValue); + RFValue = (Channel <= 14) ? 0x6E : 0x3E; + RT30xxWriteRFRegister(pAd, RF_R57, (UCHAR)RFValue); + + /* Enable RF tuning, this must be in the last, RF_R03=RF_R07 (RT30xx)*/ + RT30xxReadRFRegister(pAd, RF_R03, (PUCHAR)&RFValue); + RFValue = RFValue | 0x80; /* bit 7=vcocal_en*/ + RT30xxWriteRFRegister(pAd, RF_R03, (UCHAR)RFValue); + + RTMPusecDelay(2000); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, (PUCHAR)&RFValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R49, RFValue & 0xfe); /* clear update flag*/ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, (PUCHAR)&RFValue); + + /* latch channel for future usage.*/ + pAd->LatchRfRegs.Channel = Channel; + +#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 */ + ) + { + ITxBFLoadLNAComp(pAd); + ITxBFDividerCalibration(pAd, 2, 0, NULL); + } +#endif /* TXBF_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("RT3883: SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", + Channel, pAd->RfIcType, + TxPwer, TxPwer2, + pAd->Antenna.field.TxPath, + FreqItems3883[index].N, + FreqItems3883[index].K, + FreqItems3883[index].R)); + break; + } + } + + /* Change BBP setting during siwtch from a->g, g->a*/ + lanGain = GET_LNA_GAIN(pAd); + if (Channel <= 14) + { + BbpValue = 0x37 - lanGain; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, BbpValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, BbpValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, BbpValue); + + BbpValue = (pAd->CommonCfg.RxStream > 1) ? 0x46 : 0; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, BbpValue); + + /* Rx High power VGA offset for LNA select*/ + if (pAd->NicConfig2.field.ExternalLNAForG) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R83, 0x8A); + + /* 5G band selection PIN, bit1 and bit2 are complement*/ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &mac_val); + mac_val &= (~0x6); + mac_val |= (0x04); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, mac_val); + + /* Turn off unused PA or LNA when only 1T/1R, 2T/2R */ + TxPinCfg = 0x32050F0A; + if (pAd->Antenna.field.TxPath == 1) + TxPinCfg &= (~0x0300000D); + else if (pAd->Antenna.field.TxPath == 2) + TxPinCfg &= (~0x03000005); + + if (pAd->Antenna.field.RxPath == 1) + TxPinCfg &= (~0x30000C00); + else if (pAd->Antenna.field.RxPath == 2) + TxPinCfg &= (~0x30000000); + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + + RtmpUpdateFilterCoefficientControl(pAd, Channel); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - lanGain)); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - lanGain)); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - lanGain)); + + /* Henry 2009-12-16 */ + BbpValue = (pAd->CommonCfg.RxStream > 1) ? 0x46 : 0; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86,BbpValue); + + /* Set the BBP_R82/BBP_R83 value here */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x82); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R83, 0x9A); + + /* Rx High power VGA offset for LNA select*/ + BbpValue = pAd->NicConfig2.field.ExternalLNAForA ? 0x46 : 0x50; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, BbpValue); + + /* 5G band selection PIN, bit1 and bit2 are complement*/ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &mac_val); + mac_val &= (~0x6); + mac_val |= (0x02); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, mac_val); + + /* Turn off unused PA or LNA when only 1T/1R, 2T/2R */ + TxPinCfg = 0x31050F05; + if (pAd->Antenna.field.TxPath == 1) + TxPinCfg &= (~0x0300000E); + else if (pAd->Antenna.field.TxPath == 2) + TxPinCfg &= (~0x0300000A); + + if (pAd->Antenna.field.RxPath == 1) + TxPinCfg &= (~0x30000C00); + else if (pAd->Antenna.field.RxPath == 2) + TxPinCfg &= (~0x30000000); + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + } + + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R105, 0x34); + else + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R105, 0x04); + + /* R66 should be set according to Channel and use 20MHz when scanning*/ + /*AsicBBPWriteWithRxChain(pAd, BBP_R66, (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); +} + + +VOID RT3883_CWC_AsicSet( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN bCwc) +{ + UINT32 MacReg, rty_val, xifs_val; + + if (bCwc == 0) + { /* CwC Off */ + rty_val = 0x1f0f; + xifs_val = 0x1010; + } + else if (bCwc == 1) + { + /* CwC On */ + rty_val = 0x3f3f; + xifs_val = 0x0e0e; + } + else + return; + + RTMP_IO_READ32(pAd, TX_RTY_CFG, &MacReg); + MacReg &= 0xffff0000; + MacReg |= rty_val; + RTMP_IO_WRITE32(pAd, TX_RTY_CFG, MacReg); + + RTMP_IO_READ32(pAd, XIFS_TIME_CFG, &MacReg); + MacReg &= 0xffff0000; + MacReg |= xifs_val; + RTMP_IO_WRITE32(pAd, XIFS_TIME_CFG, MacReg); + +} + + +VOID RT3883_CWC_ProtectAdjust( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pSetMask, + IN USHORT *pOperationMode) +{ + int macIdx; + BOOLEAN bNoRTS = FALSE; + + + if (pAd->FlgCWC == 1) /* enable cwc -> disable RTS/CTS */ + return; + + if ((pAd->FlgCWC == 2) && + (pAd->MacTab.Size == 1) && + ((pAd->MacTab.fAnyStationIsLegacy == FALSE) && (pAd->MacTab.fAnyStationBadAtheros == FALSE)) + ) + { + /* + Depends on Gary's request, + 1. only one 11n STA(non-A STA) is connected + 2. MCS is 22 ~ 23 + just let it go! + */ + for (macIdx = 0; macIdx < MAX_LEN_OF_MAC_TABLE; macIdx++) + { + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[macIdx]; + + if (!IS_ENTRY_CLIENT(pEntry)) + continue; + + /* Well, I think the first one will be our target, because we only have one valid station connect to us */ + if (pEntry->HTPhyMode.field.MCS >= 22 && pEntry->HTPhyMode.field.MCS <= 23) + bNoRTS = TRUE; + + /* DBGPRINT(RT_DEBUG_WARN, ("MCS = %d\n", pEntry->HTPhyMode.field.MCS)); */ + break; + } + + if ((bNoRTS == FALSE) && (pAd->BATable.numDoneOriginator)) + { + /* We may need to go original case here if the NoRTS is FALSE */ + *pSetMask |= ALLN_SETPROTECT; + *pOperationMode = 8; + RT3883_CWC_AsicSet(pAd, 0); + /* DBGPRINT(RT_DEBUG_WARN, ("RTS/CTS protection ON\n")); */ + } + else + { + RT3883_CWC_AsicSet(pAd, 1); + /* DBGPRINT(RT_DEBUG_WARN, ("RTS/CTS protection OFF\n")); */ + } + } +} + + +#ifdef CONFIG_AP_SUPPORT +int RT3883_ext_pkt_len( + IN UCHAR *pOutBuffer, + IN ULONG FrameLen, + IN UCHAR *RalinkSpecificIe, + IN UCHAR IeLen) +{ + ULONG totalLen, appendLen; + + totalLen = FrameLen; + while(totalLen < 150) + { + appendLen = 0; + MakeOutgoingFrame(pOutBuffer+totalLen, &appendLen, + IeLen, RalinkSpecificIe, + END_OF_ARGS); + totalLen += appendLen; + } + + return totalLen - FrameLen; +} +#endif /* CONFIG_AP_SUPPORT */ + + +/* +======================================================================== +Routine Description: + Initialize RT3883. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RT3883_Init( + IN PRTMP_ADAPTER pAd) +{ + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + + + /* + Init chip capabilities + */ + pChipCap->SnrFormula = SNR_FORMULA2; + pChipCap->FlgIsHwWapiSup = TRUE; + pChipCap->VcoPeriod = 10; + pChipCap->FlgIsVcoReCalMode = VCO_CAL_MODE_2; + pChipCap->FlgIsHwAntennaDiversitySup = FALSE; +#ifdef STREAM_MODE_SUPPORT + pChipCap->FlgHwStreamMode = TRUE; +#endif /* STREAM_MODE_SUPPORT */ +#ifdef TXBF_SUPPORT + pChipCap->FlgHwTxBfCap = TRUE; +#endif /* TXBF_SUPPORT */ +#ifdef FIFO_EXT_SUPPORT + pChipCap->FlgHwFifoExtCap = TRUE; +#endif /* FIFO_EXT_SUPPORT */ + + pChipCap->RfReg17WtMethod= RF_REG_WT_METHOD_STEP_ON; + + pChipCap->MaxNumOfRfId = 63; + pChipCap->pRFRegTable = RT3883_RFRegTable; + + pChipCap->MaxNumOfBbpId = 200; + pChipCap->pBBPRegTable = RT3883_BBPRegTable; + pChipCap->bbpRegTbSize = RT3883_NUM_BBP_REG_PARMS; + + pChipCap->MaxNss = 3; + pChipCap->TXWISize = 16; + pChipCap->RXWISize = 20; +#ifdef RTMP_FLASH_SUPPORT + pChipCap->eebuf = RT3883_EeBuffer; +#endif /* RTMP_FLASH_SUPPORT */ + +#ifdef NEW_MBSSID_MODE + pChipCap->MBSSIDMode = MBSSID_MODE1; +#else + pChipCap->MBSSIDMode = MBSSID_MODE0; +#endif /* NEW_MBSSID_MODE */ + + + RTMP_DRS_ALG_INIT(pAd, RATE_ALG_GRP); + + /* + Following function configure beacon related parameters + in pChipCap + FlgIsSupSpecBcnBuf / BcnMaxHwNum / + WcidHwRsvNum / BcnMaxHwSize / BcnBase[] + */ +#ifdef SPECIFIC_BCN_BUF_SUPPORT + RtmpChipBcnSpecInit(pAd); +#else + RtmpChipBcnInit(pAd); +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ + + /* + init operator + */ + + /* BBP adjust */ + pChipOps->ChipBBPAdjust = RT3883_ChipBBPAdjust; +#ifdef CONFIG_STA_SUPPORT + pChipOps->ChipAGCAdjust = RT3883_ChipAGCAdjust; +#endif /* CONFIG_STA_SUPPORT */ + + /* Channel */ + pChipOps->ChipSwitchChannel = RT3883_ChipSwitchChannel; + pChipOps->ChipAGCInit = RT3883_ChipAGCInit; + pChipOps->AsicAdjustTxPower = AsicAdjustTxPower; + + pChipOps->AsicMacInit = NICInitRT3883MacRegisters; + pChipOps->AsicBbpInit = NICInitRT3883BbpRegisters; + pChipOps->AsicRfInit = NICInitRT3883RFRegisters; + pChipOps->AsicRfTurnOn = NULL; + + pChipOps->AsicHaltAction = RT3883HaltAction; + pChipOps->AsicRfTurnOff = RT3883LoadRFSleepModeSetup; + pChipOps->AsicReverseRfFromSleepMode = RT3883ReverseRFSleepModeSetup; + pChipOps->AsicResetBbpAgent = NULL; + + /* MAC */ + + /* EEPROM */ + pChipOps->NICInitAsicFromEEPROM = NULL; + + /* Antenna */ + pChipOps->AsicAntennaDefaultReset = RT3883_AsicAntennaDefaultReset; + + /* Frequence Calibration */ + + /* TX ALC */ + pChipOps->InitDesiredTSSITable = NULL; + pChipOps->ATETssiCalibration = NULL; + pChipOps->ATETssiCalibrationExtend = NULL; + pChipOps->AsicTxAlcGetAutoAgcOffset = NULL; + pChipOps->ATEReadExternalTSSI = NULL; + pChipOps->TSSIRatio = NULL; + + /* Others */ +#ifdef CONFIG_STA_SUPPORT + pChipOps->NetDevNickNameInit = RT3883_NetDevNickNameInit; +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CARRIER_DETECTION_SUPPORT + pAd->chipCap.carrier_func = TONE_RADAR_V2; + pChipOps->ToneRadarProgram = ToneRadarProgram_v2; +#endif /* CARRIER_DETECTION_SUPPORT */ + + /* Chip tuning */ + pChipOps->RxSensitivityTuning = RT3883_RxSensitivityTuning; + pChipOps->AsicTxAlcGetAutoAgcOffset = AsicGetAutoAgcOffsetForExternalTxAlc; + pChipOps->AsicGetTxPowerOffset = RT3883_AsicGetTxPowerOffset; + + +/* Following callback functions already initiailized in RtmpChipOpsEepromHook( ) */ + /* 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); +*/ + /* MCU related callback functions */ +/* + 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); +*/ + +/* + Following callback functions already initiailized in RtmpChipOpsHook() + 1. Power save related +*/ +#ifdef GREENAP_SUPPORT + pChipOps->EnableAPMIMOPS = EnableAPMIMOPSv2; + pChipOps->DisableAPMIMOPS = DisableAPMIMOPSv2; +#endif /* GREENAP_SUPPORT */ + +} + + +#endif /* RT3883 */ + diff --git a/mt7620/src/chips/rt5350.c b/mt7620/src/chips/rt5350.c new file mode 100644 index 0000000..1779c46 --- /dev/null +++ b/mt7620/src/chips/rt5350.c @@ -0,0 +1,2113 @@ +/* + *************************************************************************** + * 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: + rt5350.c + + Abstract: + Specific funcitons and variables for RT5350 + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifdef RT5350 + +#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 RT5350_EeBuffer[EEPROM_SIZE] = { + 0x52, 0x33, 0x01, 0x01, 0x00, 0x0c, 0x43, 0x30, 0x52, 0x88, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 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, 0x33, 0x52, 0x77, 0x00, 0x0c, 0x43, 0x33, 0x52, 0x66, 0x22, 0x0c, 0x20, 0x00, + 0xff, 0xff, 0x2f, 0x01, 0x55, 0x77, 0xa8, 0xaa, 0x8c, 0x88, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x10, 0x10, + 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x14, 0x14, 0x14, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x66, 0x66, + 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, + 0x88, 0x66, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + } ; + +REG_PAIR RT5350_RFRegTable[] = { + {RF_R00, 0xF0}, + {RF_R01, 0x23}, + {RF_R02, 0x50}, + {RF_R03, 0x08}, + {RF_R04, 0x49}, + {RF_R05, 0x10}, + {RF_R06, 0xE0}, + {RF_R07, 0x00}, + {RF_R08, 0xF1}, + {RF_R09, 0x02}, + {RF_R10, 0x53}, + {RF_R11, 0x4A}, + {RF_R12, 0x46}, + {RF_R13, 0x9F}, + {RF_R14, 0x00}, + {RF_R15, 0x00}, + {RF_R16, 0xC0}, /* for 40M spur reduction */ +/* {RF_R17, 0x1A}, */ + {RF_R18, 0x03}, + {RF_R19, 0x00}, + {RF_R20, 0x00}, + {RF_R21, 0x00}, + {RF_R22, 0x20}, + {RF_R23, 0x00}, + {RF_R24, 0x00}, + {RF_R25, 0x80}, + {RF_R26, 0x00}, + {RF_R27, 0x03}, + {RF_R28, 0x00}, + {RF_R29, 0xD0}, /* optimize for H/W diversity, do not use 0x10 */ + {RF_R30, 0x10}, + {RF_R31, 0x80}, + {RF_R32, 0x80}, + {RF_R33, 0x00}, + {RF_R34, 0x07}, + {RF_R35, 0x12}, + {RF_R36, 0x00}, + {RF_R37, 0x08}, + {RF_R38, 0x85}, + {RF_R39, 0x1B}, + {RF_R40, 0x0B}, + {RF_R41, 0xBB}, + {RF_R42, 0xD5}, + {RF_R43, 0x9B}, + {RF_R44, 0x0C}, + {RF_R45, 0xA6}, + {RF_R46, 0x73}, + {RF_R47, 0x00}, + {RF_R48, 0x10}, + {RF_R49, 0x80}, + {RF_R50, 0x00}, + {RF_R51, 0x00}, + {RF_R52, 0x38}, + {RF_R53, 0x00}, + {RF_R54, 0x38}, + {RF_R55, 0x43}, + {RF_R56, 0x82}, + {RF_R57, 0x00}, + {RF_R58, 0x39}, + {RF_R59, 0x0B}, + {RF_R60, 0x45}, + {RF_R61, 0xD1}, + {RF_R62, 0x00}, + {RF_R63, 0x00}, +}; + +UCHAR RT5350_RF59[] = { /* based on different 2.4G channels */ + 0x0B, + 0x0B, + 0x0B, + 0x0B, + 0x0B, + 0x0B, + 0x0B, + 0x0A, + 0x0A, + 0x09, + 0x08, + 0x07, + 0x07, + 0x06 +}; + +UCHAR RT5350_NUM_RF_REG_PARMS = (sizeof(RT5350_RFRegTable) / sizeof(REG_PAIR)); + + +REG_PAIR RT5350_BBPRegTable[] = { + {BBP_R4, 0x50}, // 2883 need to + //The new 8-b ADC applies to the following projects: RT3352/RT3593/RT3290/RT5390 and the coming new projects. + //BB REG: R31: 0x08. ( bit4:2 ADC buffer current: 010, bit1:0 ADC current: 00 (40uA)). + {BBP_R31, 0x08}, //gary recommend for ACE + {BBP_R47, 0x48}, // ALC Functions change from 0x7 to 0x48 Baron suggest +// turn on find AGC cause QA have Rx problem 2009-10-26 in 3883 + {BBP_R65, 0x2C}, // fix rssi issue + {BBP_R66, 0x38}, // Also set this default value to pAd->BbpTuning.R66CurrentValue at initial + {BBP_R68, 0x0B}, // Gary 2009-05-14: for all platform + {BBP_R69, 0x12}, + {BBP_R70, 0xa}, // BBP_R70 will change to 0x8 in ApStartUp and LinkUp for rt2860C, otherwise value is 0xa + {BBP_R73, 0x13}, + {BBP_R75, 0x46}, + {BBP_R76, 0x28}, + {BBP_R77, 0x59}, + {BBP_R78, 0x0E}, + {BBP_R80, 0x08}, // requested by Gary for high power + {BBP_R81, 0x37}, + {BBP_R82, 0x62}, + {BBP_R83, 0x7A}, + {BBP_R84, 0x9a}, + {BBP_R86, 0x38}, // middle range issue, Rory @2008-01-28 + {BBP_R91, 0x04}, // middle range issue, Rory @2008-01-28 + {BBP_R92, 0x02}, // middle range issue, Rory @2008-01-28 + + {BBP_R103, 0xC0}, + {BBP_R104, 0x92}, + {BBP_R105, 0x3C}, + {BBP_R106, 0x03}, + {BBP_R128, 0x12}, + {BBP_R120, 0x50}, // for long range -2db, Gary 2010-01-22 + {BBP_R137, 0x0F}, // julian suggest make the RF output more stable + {BBP_R163, 0xBD}, // Enable saving of Explicit and Implicit profiles + + {BBP_R179, 0x02}, // Set ITxBF timeout to 0x9C40=1000msec + {BBP_R180, 0x00}, + {BBP_R182, 0x40}, + {BBP_R180, 0x01}, + {BBP_R182, 0x9C}, + {BBP_R179, 0x00}, + + {BBP_R142, 0x04}, // Reprogram the inband interface to put right values in RXWI + {BBP_R143, 0x3b}, + {BBP_R142, 0x06}, + {BBP_R143, 0xA0}, + {BBP_R142, 0x07}, + {BBP_R143, 0xA1}, + {BBP_R142, 0x08}, + {BBP_R143, 0xA2}, + + {BBP_R148, 0xC8}, // Gary, 2010-02-12 +}; + +UCHAR RT5350_NUM_BBP_REG_PARMS = (sizeof(RT5350_BBPRegTable) / sizeof(REG_PAIR)); + + +RTMP_REG_PAIR RT5350_MACRegTable[] = { + {TX_SW_CFG0, 0x404}, // 2010-07-20 +}; + +UCHAR RT5350_NUM_MAC_REG_PARMS = (sizeof(RT5350_MACRegTable) / sizeof(RTMP_REG_PAIR)); + + +#ifdef RTMP_INTERNAL_TX_ALC +TX_POWER_TUNING_ENTRY_STRUCT RT5350_TxPowerTuningTable[] = +{ +// idxTxPowerTable Tx power control over RF Tx power control over MAC +//(zero-based array) { RF_R49[5:0]: Tx0 ALC}, {MAC 0x1314~0x1320} +/* 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 */ {0x20, 0}, +/* 63 */ {0x21, 0}, +/* 64 */ {0x22, 0}, +/* 65 */ {0x23, 0}, +/* 66 */ {0x24, 0}, +/* 67 */ {0x25, 0}, +/* 68 */ {0x26, 0}, +/* 69 */ {0x27, 0}, +/* 70 */ {0x26, 1}, +/* 71 */ {0x27, 1}, +/* 72 */ {0x26, 2}, +/* 73 */ {0x27, 2}, +/* 74 */ {0x26, 3}, +/* 75 */ {0x27, 3}, +/* 76 */ {0x26, 4}, +/* 77 */ {0x27, 4}, +/* 78 */ {0x26, 5}, +/* 79 */ {0x27, 5}, +/* 80 */ {0x26, 6}, +/* 81 */ {0x27, 6}, +/* 82 */ {0x26, 7}, +/* 83 */ {0x27, 7}, +/* 84 */ {0x26, 8}, +/* 85 */ {0x27, 8}, +/* 86 */ {0x26, 9}, +/* 87 */ {0x27, 9}, +/* 88 */ {0x26, 10}, +/* 89 */ {0x27, 10}, +/* 90 */ {0x26, 11}, +/* 91 */ {0x27, 11}, +}; + +static TssiDeltaInfo TSSI_Set[15]; +static TssiDeltaInfo TSSI_x; +static UCHAR TSSI_ref; + +UINT32 RT5350_desiredTSSIOverCCK[4] = {0}; + +// The desired TSSI over OFDM +UINT32 RT5350_desiredTSSIOverOFDM[8] = {0}; + +// The desired TSSI over HT +UINT32 RT5350_desiredTSSIOverHT[16] = {0}; +UINT32 RT5350_desiredTSSIOverHT40[16] = {0}; + +UINT32 RT5350_GetDesiredTSSI( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBbpR49); + +UINT32 TSSIRatioDot85( + IN INT32 delta_power); + +UINT32 TSSIRatioDot7( + IN INT32 delta_power); + +VOID RT5350_ChipAGCInit( + IN PRTMP_ADAPTER pAd, + IN UCHAR BandWidth); +#endif // RTMP_INTERNAL_TX_ALC // + + + + +/* +======================================================================== +Routine Description: + Initialize RT5350. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RT5350_Init( + IN PRTMP_ADAPTER pAd) +{ + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + + /* ??? */ + pAd->RfIcType = RFIC_3320; + + /* init capability */ + pChipCap->MaxNumOfRfId = 63; + pChipCap->MaxNumOfBbpId = 255; + pChipCap->pRFRegTable = RT5350_RFRegTable; + pChipCap->pBBPRegTable = RT5350_BBPRegTable; + pChipCap->bbpRegTbSize = RT5350_NUM_BBP_REG_PARMS; + pChipCap->SnrFormula = SNR_FORMULA2; + pChipCap->RfReg17WtMethod = RF_REG_WT_METHOD_STEP_ON; + + pChipCap->FlgIsHwWapiSup = TRUE; + pChipCap->FlgIsVcoReCalMode = VCO_CAL_MODE_2; + + if ((pAd->MACVersion & 0xffff) > 0x0102) + pChipCap->FlgIsHwAntennaDiversitySup = TRUE; + else + pChipCap->FlgIsHwAntennaDiversitySup = FALSE; + +#ifdef NEW_MBSSID_MODE + pChipCap->MBSSIDMode = MBSSID_MODE1; +#else + pChipCap->MBSSIDMode = MBSSID_MODE0; +#endif /* NEW_MBSSID_MODE */ + + + /* init operator */ + pChipOps->AsicRfInit = NICInitRT5350RFRegisters; + pChipOps->AsicBbpInit = NICInitRT5350BbpRegisters; + pChipOps->AsicMacInit = NICInitRT5350MacRegisters; + pChipOps->RxSensitivityTuning = RT5350_RxSensitivityTuning; +#ifdef CONFIG_STA_SUPPORT + pChipOps->ChipAGCAdjust = RT5350_ChipAGCAdjust; +#endif // CONFIG_STA_SUPPORT // + pChipOps->ChipBBPAdjust = RT5350_ChipBBPAdjust; + pChipOps->ChipSwitchChannel = RT5350_ChipSwitchChannel; + pChipOps->AsicAdjustTxPower = AsicAdjustTxPower; + pChipCap->TXWISize = 16; + pChipCap->RXWISize = 16; +#ifdef RTMP_FLASH_SUPPORT + pChipCap->eebuf = RT5350_EeBuffer; +#endif /* RTMP_FLASH_SUPPORT */ + + pChipOps->AsicGetTxPowerOffset = AsicGetTxPowerOffset; + +#ifdef RTMP_INTERNAL_TX_ALC + pChipCap->TxAlcTxPowerUpperBound_2G = 61; + pChipCap->TxPowerMaxCompenStep = 4; /* default 2dB (one step is 0.5dB) */ + pChipCap->TxPowerTableMaxIdx = 0; + pChipCap->TxPowerTuningTable_2G = RT5350_TxPowerTuningTable; + pChipOps->InitDesiredTSSITable = RT5350_InitDesiredTSSITable; + pChipOps->AsicTxAlcGetAutoAgcOffset = RT5350_AsicTxAlcGetAutoAgcOffset; +#endif /* RTMP_INTERNAL_TX_ALC */ + + /* + 5350 have other MAC registers to extra compensate + Tx power for OFDM 54, HT MCS 7 and STBC MCS 7 + */ + pChipOps->AsicExtraPowerOverMAC = RT5350_AsicExtraPowerOverMAC; + + + pChipOps->SetRxAnt = RT5350SetRxAnt; + pAd->Mlme.bEnableAutoAntennaCheck = FALSE; /* 1T1R only */ + + +#ifdef CARRIER_DETECTION_SUPPORT + pAd->chipCap.carrier_func = TONE_RADAR_V2; + pChipOps->ToneRadarProgram = ToneRadarProgram_v2; +#endif /* CARRIER_DETECTION_SUPPORT */ + + pChipOps->ChipAGCInit = RT5350_ChipAGCInit; + + RtmpChipBcnSpecInit(pAd); +} + + +/* +======================================================================== +Routine Description: + Initialize specific MAC registers. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID NICInitRT5350MacRegisters( + IN PRTMP_ADAPTER pAd) +{ + UINT32 IdReg; + + + for(IdReg=0; IdRegRfFreqOffset & 0x7F; // bit7 = 0 + RT30xxReadRFRegister(pAd, RF_R17, &RfValue1); + if (RFValue != RfValue1) + RT30xxWriteRFRegister(pAd, RF_R17, (UCHAR)RFValue); + + // Initialize RF register to default value + for (i = 0; i < RT5350_NUM_RF_REG_PARMS; i++) + { + RT30xxWriteRFRegister(pAd, RT5350_RFRegTable[i].Register, RT5350_RFRegTable[i].Value); + } + + + //Gary: Boot up bit7=1 + RT30xxReadRFRegister(pAd, RF_R02, (PUCHAR)&RfReg); + RfReg &= ~(1 << 6); // clear bit6=rescal_bp + RfReg |= 0x80; // bit7=rescal_en + RT30xxWriteRFRegister(pAd, RF_R02, (UCHAR)RfReg); + RTMPusecDelay(1000); + RfReg &= 0x7F; + RT30xxWriteRFRegister(pAd, RF_R02, (UCHAR)RfReg); + + /* Gary: 20100827 for 11B-only mode */ + if (pAd->CommonCfg.PhyMode == PHY_11B) + RT30xxWriteRFRegister(pAd, RF_R55, (UCHAR)0x47); +} + + +VOID RT5350SetRxAnt( + IN PRTMP_ADAPTER pAd, + IN UCHAR Ant) +{ + UINT8 BBPValue = 0; + + /* + main antenna: BBP_R152 bit7=1 + aux antenna: BBP_R152 bit7=0 + */ + 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 = 0x00; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R154, BBPValue); + + if (Ant == 0) + { + /* fix to main antenna */ + /* do not care BBP R153, R155, R253 */ + BBPValue = 0x23; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R152, BBPValue); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: switch to main antenna\n", __FUNCTION__)); + } + else + { + /* fix to aux antenna */ + /* do not care BBP R153, R155, R253 */ + BBPValue = 0xa3; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R152, BBPValue); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: switch to aux antenna\n", __FUNCTION__)); + } +} + + +VOID RT5350_RxSensitivityTuning( + IN PRTMP_ADAPTER pAd) +{ + UCHAR R66; + + + R66 = 0x26 + GET_LNA_GAIN(pAd); +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { +#ifdef RTMP_RBUS_SUPPORT + // TODO: we need to add MACVersion Check here!!!! +#if defined(RT5350) + if (IS_RT5350(pAd)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, 0x0); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); + } + else +#endif // defined(RT5350) // +#endif // RTMP_RBUS_SUPPORT // + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); + } + else +#endif // RALINK_ATE // + { + AsicBBPWriteWithRxChain(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)), RX_CHAIN_ALL); + } + DBGPRINT(RT_DEBUG_TRACE,("turn off R17 tuning, restore to 0x%02x\n", R66)); +} + + +#ifdef CONFIG_STA_SUPPORT +UCHAR RT5350_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 + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + R66 = lanGain * 2 + 0x1C; + else + R66 = lanGain * 2 + 0x24; + } + else + { //A band + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + { + R66 = 0x32 + (lanGain * 5) / 3; + if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) + R66 += 0x10; + } + else + { + R66 = 0x3A + (lanGain * 5) / 3; + if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) + R66 += 0x10; + } + } + + if (OrigR66Value != R66) + AsicBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + + return R66; +} +#endif // CONFIG_STA_SUPPORT // + + +VOID RT5350_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.AddHTInfo.AddHtInfo.ExtChanOffset == 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); + + if (pAd->CommonCfg.Channel > 14) + { // request by Gary 20070208 for middle and long range A Band + AsicBBPWriteWithRxChain(pAd, BBP_R66, 0x48, RX_CHAIN_ALL); + } + else + { // request by Gary 20070208 for middle and long range G Band +#if defined(RT5350) + UCHAR R66; + if (IS_RT5350(pAd)) + { + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + R66 = GET_LNA_GAIN(pAd)*2 + 0x1C; + else + R66 = GET_LNA_GAIN(pAd)*2 + 0x24; + AsicBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + } +#endif // RT5350 // + } + // + 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); + } + 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, 0x13); + } + + 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.AddHTInfo.AddHtInfo.ExtChanOffset == 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); + + if (pAd->CommonCfg.Channel > 14) + { // request by Gary 20070208 for middle and long range A Band + AsicBBPWriteWithRxChain(pAd, BBP_R66, 0x48, RX_CHAIN_ALL); + } + else + { // request by Gary 20070208 for middle and long range G band +#if defined(RT5350) + if (IS_RT5350(pAd)) + { + UCHAR R66; + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + R66 = GET_LNA_GAIN(pAd)*2 + 0x1C; + else + R66 = GET_LNA_GAIN(pAd)*2 + 0x24; + AsicBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + } +#endif // RT5350 // + } + + + 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); + } + 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, 0x13); + } + 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); + + // 20 MHz bandwidth + if (pAd->CommonCfg.Channel > 14) + { // request by Gary 20070208 + AsicBBPWriteWithRxChain(pAd, BBP_R66, 0x40, RX_CHAIN_ALL); + } + else + { // request by Gary 20070208 + //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, 0x30); + // request by Brian 20070306 +#if defined(RT5350) + if (IS_RT5350(pAd)) + { + UCHAR R66; + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + R66 = GET_LNA_GAIN(pAd)*2 + 0x1C; + else + R66 = GET_LNA_GAIN(pAd)*2 + 0x24; + AsicBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + } +#endif // RT5350 // + } + + 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); + } + 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, 0x13); + } + +#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 // + } +} + + +VOID RT5350_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 + + /* + 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, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel)); + } + +#ifdef RT305x + // The RF programming sequence is difference between 3xxx and 2xxx + if (((pAd->MACVersion == 0x28720200) +#ifdef RT5350 + || IS_RT5350(pAd) +#endif // RT5350 // + )) + { + /* modify by WY for Read RF Reg. error */ + + for (index = 0; index < NUM_OF_3020_CHNL; index++) + { + if (Channel == FreqItems3020[index].Channel) + { +#ifdef RT5350 + Value = (*((volatile u32 *)(RALINK_SYSCTL_BASE + 0x10))); + + // Programming channel parameters + if(Value & (1<<20)) { //Xtal=40M + RT30xxWriteRFRegister(pAd, RF_R08, FreqItems3020[index].N); + RT30xxWriteRFRegister(pAd, RF_R09, FreqItems3020[index].K); + RFValue = 0x9F; + }else { + RT30xxWriteRFRegister(pAd, RF_R08, FreqItems3020_Xtal20M[index].N); + RT30xxWriteRFRegister(pAd, RF_R09, FreqItems3020_Xtal20M[index].K); + RFValue = 0x1F; + } + RT30xxWriteRFRegister(pAd, RF_R13, (UCHAR)RFValue); + RFValue = 0x4A; + RT30xxWriteRFRegister(pAd, RF_R11, (UCHAR)RFValue); + + for (i = 0; i < MAX_NUM_OF_CHANNELS; i++) { + if (Channel != pAd->TxPower[i].Channel) + continue; + + /* Bit<7:6>=1:0, TX0 DAC By EEPROM Channel setting */ + RFValue = pAd->TxPower[i].Power & 0x3F; // clesr bit7:6 + RFValue |= 0x80; // bit7:6 = 1:0 + + RT30xxWriteRFRegister(pAd, RF_R49, (UCHAR)RFValue); + break; + } + + RFValue = 0x46; + RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue); + + + RT30xxReadRFRegister(pAd, RF_R30, (PUCHAR)&RFValue); + if ((pAd->CommonCfg.BBPCurrentBW == BW_40) +#ifdef COC_SUPPORT + && (pAd->CoC_sleep == 0) +#endif + ) + RFValue |= 0x06; // 40MBW tx_h20M=1,rx_h20M=1 + else + RFValue &= ~(0x06); // 20MBW tx_h20M=0,rx_h20M=0 + RT30xxWriteRFRegister(pAd, RF_R30, (UCHAR)RFValue); + + if(pAd->CommonCfg.PhyMode == PHY_11B) + RFValue = 0xC0; + else + RFValue = 0x80; + RT30xxWriteRFRegister(pAd, RF_R32, (UCHAR)RFValue); + + RFValue = 0x00; + RT30xxWriteRFRegister(pAd, RF_R53, (UCHAR)RFValue); + + RFValue = 0x43; + RT30xxWriteRFRegister(pAd, RF_R55, (UCHAR)RFValue); + + RFValue = 0x82; + RT30xxWriteRFRegister(pAd, RF_R56, (UCHAR)RFValue); + + RT30xxReadRFRegister(pAd, RF_R03, (PUCHAR)&RFValue); + RFValue = RFValue | 0x80; // bit 7=vcocal_en + RT30xxWriteRFRegister(pAd, RF_R03, (UCHAR)RFValue); + + RTMPusecDelay(2000); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, (PUCHAR)&RFValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R49, RFValue & 0xfe); // clear update flag + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, (PUCHAR)&RFValue); + + // latch channel for future usage. + pAd->LatchRfRegs.Channel = Channel; +#endif // RT5350 // + +#ifdef RT5350 + if (IS_RT5350(pAd)) + RFValue = 0; /* RF_R24 is reserved bits */ +#endif // RT5350 // + + + if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40) +#ifdef GREENAP_SUPPORT + && (pAd->ApCfg.bGreenAPActive == 0) +#endif // GREENAP_SUPPORT // + ) + { +#ifdef RT5350 + if (IS_RT5350(pAd)) + RFValue = 0; /* RF_R24 is reserved bits */ +#endif // RT5350 // + } + RT30xxWriteRFRegister(pAd, RF_R24, RFValue); + + // Rx filter + if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40) +#ifdef GREENAP_SUPPORT + && (pAd->ApCfg.bGreenAPActive == 0) +#endif // GREENAP_SUPPORT // + ) + { +#ifdef RT5350 + if (IS_RT5350(pAd)) + RT30xxWriteRFRegister(pAd, RF_R31, 0x80); //FIXME: I don't know the RF_R31 for BW40 case +#endif // RT5350 // + } + else + { +#ifdef RT5350 + if (IS_RT5350(pAd)) + RT30xxWriteRFRegister(pAd, RF_R31, 0x80); +#endif // RT5350 // + } + +#if defined (RT5350) + if (IS_RT5350(pAd)) + { + // Enable RF tuning, this must be in the last, RF_R03=RF_R07 (RT30xx) + RT30xxReadRFRegister(pAd, RF_R03, (PUCHAR)&RFValue); + RFValue = RFValue | 0x80; // bit 7=vcocal_en + RT30xxWriteRFRegister(pAd, RF_R03, (UCHAR)RFValue); + + RTMPusecDelay(2000); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, (PUCHAR)&RFValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R49, RFValue & 0xfe); // clear update flag + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, (PUCHAR)&RFValue); + + // Antenna + RT30xxReadRFRegister(pAd, RF_R01, (PUCHAR)&RFValue); + RFValue &= 0x03; //clear bit[7~2] + RFValue |= 0x3C; // default 2Tx 2Rx + + if (pAd->Antenna.field.TxPath == 1) + RFValue &= ~(0x1 << 5); + + if (pAd->Antenna.field.RxPath == 1) + RFValue &= ~(0x1 << 4); + + RT30xxWriteRFRegister(pAd, RF_R01, (UCHAR)RFValue); + } +#endif // RT5350 // + + // latch channel for future usage. + pAd->LatchRfRegs.Channel = Channel; + + break; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", + Channel, + pAd->RfIcType, + TxPwer, + TxPwer2, + pAd->Antenna.field.TxPath, + FreqItems3020[index].N, + FreqItems3020[index].K, + FreqItems3020[index].R)); + } + else +#endif // RT305x // + { + switch (pAd->RfIcType) + { + default: + DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d : unknown RFIC=%d\n", + Channel, pAd->RfIcType)); + break; + } + } + + // Change BBP setting during siwtch from a->g, g->a + if (Channel <= 14) + { + ULONG TxPinCfg = 0x00050F0A;//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))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x38); // Gary 2010-07-21 + + // Rx High power VGA offset for LNA select + { + if (pAd->NicConfig2.field.ExternalLNAForG) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + } + +#if defined (RT5350) + if (IS_RT5350(pAd)) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R83, 0x7a); + } +#endif // RT5350 // + + // 5G band selection PIN, bit1 and bit2 are complement + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x04); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + { + // 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); + + /* different RF R59 for different central channel 20100827 */ + RT30xxWriteRFRegister(pAd, RF_R59, (UCHAR)RT5350_RF59[Channel-1]); + + RtmpUpdateFilterCoefficientControl(pAd, Channel); + } + else + { + ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505 + UINT8 bbpValue; + + 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))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x38); // Gary 2010-07-21 + + /* Set the BBP_R82 value here */ + bbpValue = 0xF2; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, bbpValue); + + // Rx High power VGA offset for LNA select + if (pAd->NicConfig2.field.ExternalLNAForA) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + // 5G band selection PIN, bit1 and bit2 are complement + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x02); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + // Turn off unused PA or LNA when only 1T or 1R + { + // 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); + } + + // R66 should be set according to Channel and use 20MHz when scanning + /*AsicBBPWriteWithRxChain(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)), 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); +} + + +VOID RT5350_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); + + DBGPRINT(RT_DEBUG_TRACE, ("Offset = 0x13D4, TxPwr = 0x%08X, Offset = 0x13DC, TxPwr = 0x%08X\n", + (UINT)ExtraPwrOverTxPwrCfg7, + (UINT)ExtraPwrOverTxPwrCfg9)); +} + + +#ifdef RTMP_INTERNAL_TX_ALC +VOID RT5350_AsicTxAlcGetAutoAgcOffset( + IN PRTMP_ADAPTER pAd, + IN PCHAR pDeltaPwr, + IN PCHAR pTotalDeltaPwr, + IN PCHAR pAgcCompensate, + IN PCHAR pDeltaPowerByBbpR1) +{ + CHAR TotalDeltaPower = 0; + BBP_R49_STRUC BbpR49; + UINT32 desiredTSSI = 0, currentTSSI = 0, room_up = 0, room_down = 0; + const TX_POWER_TUNING_ENTRY_STRUCT *TxPowerTuningTable = pAd->chipCap.TxPowerTuningTable_2G; + PTX_POWER_TUNING_ENTRY_STRUCT pTxPowerTuningEntry = NULL; + UCHAR RFValue = 0; + CHAR DeltaPwr = 0, TuningTableIndex = 0; + BOOLEAN bKeepRF = FALSE; + + BbpR49.byte = 0; + + /* TX power compensation for temperature variation based on TSSI. try every 4 second */ + if (pAd->Mlme.OneSecPeriodicRound % 4 == 0) + { + desiredTSSI = RT5350_GetDesiredTSSI(pAd, &BbpR49.byte); + room_down = (desiredTSSI >> 5); + room_up = (desiredTSSI >> 2); + currentTSSI = BbpR49.byte * 10000; + + DBGPRINT(RT_DEBUG_TRACE, ("DesiredTSSI = %d, CurrentTSSI = %d (Range: %d ~ %d, BBP_R49=0x%X)\n", + desiredTSSI, currentTSSI, desiredTSSI-room_up, + desiredTSSI+room_down, BbpR49.byte)); + + if (desiredTSSI-room_up > currentTSSI) + { + pAd->TxPowerCtrl.idxTxPowerTable++; + } + else if (desiredTSSI+room_down < currentTSSI) + { + pAd->TxPowerCtrl.idxTxPowerTable--; + } + else + { + bKeepRF = TRUE; + } + + /* To reduce the time for TSSI compensated to target value */ + TuningTableIndex = pAd->TxPowerCtrl.idxTxPowerTable +#ifdef DOT11_N_SUPPORT + + pAd->TxPower[pAd->CommonCfg.CentralChannel-1].Power; +#else + + pAd->TxPower[pAd->CommonCfg.Channel-1].Power; +#endif /* DOT11_N_SUPPORT */ + + if (TuningTableIndex < LOWERBOUND_TX_POWER_TUNING_ENTRY) + { + TuningTableIndex = LOWERBOUND_TX_POWER_TUNING_ENTRY; + } + + if (TuningTableIndex >= UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd)) + { + TuningTableIndex = UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd); + } + + /* Valid TuningTableIndex: -30 ~ 61 */ + pTxPowerTuningEntry = &TxPowerTuningTable[TuningTableIndex + TX_POWER_TUNING_ENTRY_OFFSET]; + pAd->TxPowerCtrl.RF_TX_ALC = pTxPowerTuningEntry->RF_TX_ALC; + pAd->TxPowerCtrl.MAC_PowerDelta = pTxPowerTuningEntry->MAC_PowerDelta; + + if (bKeepRF == FALSE) + { + /* Tx power adjustment over RF is needed */ + RT30xxReadRFRegister(pAd, RF_R49, (PUCHAR)(&RFValue)); /* TX0_ALC */ + RFValue &= ~0x3F; /* clear RF_R49[5:0] */ + RFValue |= pAd->TxPowerCtrl.RF_TX_ALC; + + /* The valid range of the RF R49 (<5:0>tx0_alc<5:0>) is 0x00~0x27 */ + if ((RFValue & 0x3F) > 0x27) + { + RFValue = ((RFValue & ~0x3F) | 0x27); + } + RT30xxWriteRFRegister(pAd, RF_R49, (UCHAR)RFValue); /* TX0_ALC */ + DBGPRINT(RT_DEBUG_TRACE, ("RF_R49 = 0x%X ", RFValue)); + } + + /* Tx power adjustment over MAC */ + TotalDeltaPower = pAd->TxPowerCtrl.MAC_PowerDelta; + + DBGPRINT(RT_DEBUG_TRACE, ("Current index of TuningTable = %d {RF_TX_ALC = 0x%X, MAC_PowerDelta = %d}\n", + (TuningTableIndex + TX_POWER_TUNING_ENTRY_OFFSET), + pAd->TxPowerCtrl.RF_TX_ALC, + pAd->TxPowerCtrl.MAC_PowerDelta)); + } + + *pDeltaPwr = DeltaPwr; + *pTotalDeltaPwr = TotalDeltaPower; +} + + +INT32 TSSIDelta2PowDelta(UINT32 TSSI_x_10000, UINT32 TSSI_ref) +{ + UINT32 ratio_x; + INT32 power_delta; + + ratio_x = TSSI_x_10000 / TSSI_ref; + + if (ratio_x <= 1903) { + DBGPRINT(RT_DEBUG_TRACE, ("TSSIRatio2Delta: ratio_x(%d) is ourt range(7 ~ -8)\n", ratio_x)); + power_delta = -8; + } + else if (ratio_x <= 2315) + power_delta = -8; + else if (ratio_x <= 2815) + power_delta = -7; + else if (ratio_x <= 3424) + power_delta = -6; + else if (ratio_x <= 4164) + power_delta = -5; + else if (ratio_x <= 5065) + power_delta = -4; + else if (ratio_x <= 6160) + power_delta = -3; + else if (ratio_x <= 7491) + power_delta = -2; + else if (ratio_x <= 9111) + power_delta = -1; + else if (ratio_x <= 11081) + power_delta = 0; + else if (ratio_x <= 13476) + power_delta = 1; + else if (ratio_x <= 16390) + power_delta = 2; + else if (ratio_x <= 19933) + power_delta = 3; + else if (ratio_x <= 24242) + power_delta = 4; + else if (ratio_x <= 29483) + power_delta = 5; + else if (ratio_x <= 35857) + power_delta = 6; + else if (ratio_x <= 43609) + power_delta = 7; + else { + DBGPRINT(RT_DEBUG_TRACE, ("TSSIRatio2Delta: ratio_x(%d) is ourt range(7 ~ -8)\n", ratio_x)); + power_delta = 7; + } + + DBGPRINT(RT_DEBUG_TRACE, ("TSSIRatio2Delta: TSSI_x_10000=%u, TSSI_ref=%u ratio_x=%u power_delta=%d\n", TSSI_x_10000, TSSI_ref, ratio_x, power_delta)); + + return power_delta; +} + + +UINT32 TSSIRatioDot85(INT32 delta_power) +{ + UINT32 ratio = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("---> %s\n", __FUNCTION__)); + + switch(delta_power) + { + case -12: + ratio = 955; + break; + case -11: + ratio = 1161; + break; + case -10: + ratio = 1413; + break; + case -9: + ratio = 1718; + break; + case -8: + ratio = 2089; + break; + case -7: + ratio = 2541; + break; + case -6: + ratio = 3090; + break; + case -5: + ratio = 3758; + break; + case -4: + ratio = 4571; + break; + case -3: + ratio = 5559; + break; + case -2: + ratio = 6761; + break; + case -1: + ratio = 8222; + break; + case 0: + ratio = 10000; + break; + case 1: + ratio = 12162; + break; + case 2: + ratio = 14791; + break; + case 3: + ratio = 17989; + break; + case 4: + ratio = 21878; + break; + case 5: + ratio = 26607; + break; + case 6: + ratio = 32359; + break; + case 7: + ratio = 39355; + break; + case 8: + ratio = 47863; + break; + case 9: + ratio = 58210; + break; + case 10: + ratio = 70795; + break; + case 11: + ratio = 86099; + break; + case 12: + ratio = 104713; + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("Invalid delta_power %d\n", delta_power)); + break; + + } + + return ratio; +} + + +UINT32 TSSIRatioDot7(INT32 delta_power) +{ + UINT32 ratio = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("---> %s\n", __FUNCTION__)); + + switch(delta_power) + { + case -12: + ratio = 1445; + break; + case -11: + ratio = 1698; + break; + case -10: + ratio = 1995; + break; + case -9: + ratio = 2344; + break; + case -8: + ratio = 2754; + break; + case -7: + ratio = 3236; + break; + case -6: + ratio = 3802; + break; + case -5: + ratio = 4467; + break; + case -4: + ratio = 5248; + break; + case -3: + ratio = 6166; + break; + case -2: + ratio = 7244; + break; + case -1: + ratio = 8511; + break; + case 0: + ratio = 10000; + break; + case 1: + ratio = 11749; + break; + case 2: + ratio = 13804; + break; + case 3: + ratio = 16218; + break; + case 4: + ratio = 19055; + break; + case 5: + ratio = 22387; + break; + case 6: + ratio = 26303; + break; + case 7: + ratio = 30903; + break; + case 8: + ratio = 36308; + break; + case 9: + ratio = 42658; + break; + case 10: + ratio = 50119; + break; + case 11: + ratio = 58884; + break; + case 12: + ratio = 69183; + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("Invalid delta_power %d\n", delta_power)); + break; + + } + + return ratio; +} + + +VOID RT5350_InitDesiredTSSITable( + IN PRTMP_ADAPTER pAd) +{ + USHORT TSSIBase = 0;/* The TSSI over OFDM 54Mbps */ + USHORT TSSIDelta = 0;/* The TSSI value/step (0.5 dB/unit) */ + UCHAR RFValue = 0; + UCHAR BbpR47 = 0; + UINT32 i = 0; + USHORT TxPower = 0, TxPowerOFDM54 = 0; + USHORT TSSIParm=0; + UCHAR TSSIGain=0; + UCHAR TSSIAttenuation=0; + USHORT E2PValue = 0; + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + USHORT Value = 0; + CHAR BWPowerDelta = 0; + + if (pAd->TxPowerCtrl.bInternalTxALC == FALSE) + { + DBGPRINT(RT_DEBUG_OFF, ("pAd->TxPowerCtrl.bInternalTxALC == FALSE !\n")); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("---> %s\n", __FUNCTION__)); + + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_DELTA, Value); + + if ((Value & 0xFF) == 0xFF) /* 20/40M BW Power Delta */ + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: 20/40M BW Delta Power is disabled since EEPROM is not calibrated.\n", __FUNCTION__)); + } + else + { + if ((Value & 0xC0) == 0xC0) + { + BWPowerDelta += (Value & 0x3F); /* increase 40M BW TX power with the delta value */ + } + else if ((Value & 0xC0) == 0x80) + { + BWPowerDelta -= (Value & 0x3F); /* decrease 40M BW TX power with the delta value */ + } + else + DBGPRINT(RT_DEBUG_TRACE, ("%s: 20/40M BW Delta Power is not enabled, Value = 0x%X\n", __FUNCTION__, Value)); + } + + /* initialize the ratio used in non-linear TSSI */ + RT28xx_EEPROM_READ16(pAd, (EEPROM_TSSI_STEP_OVER_2DOT4G - 1), E2PValue); + + /* + Bit 2 of EEPROM 0x77 is 1, + updated internal TSSI ratio table + (slope is 0.7 instead of 0.85) is selected. + */ + if (((E2PValue >> 8) & 0x04) == 0x04) + { + pChipOps->TSSIRatio = TSSIRatioDot7; + DBGPRINT(RT_DEBUG_OFF, ("%s : slope of TSSI is 0.7\n", __FUNCTION__)); + } + else + { + pChipOps->TSSIRatio = TSSIRatioDot85; + DBGPRINT(RT_DEBUG_OFF, ("%s : slope of TSSI is 0.85\n", __FUNCTION__)); + } + + RT28xx_EEPROM_READ16(pAd, EEPROM_TSSI_OVER_OFDM_54, TSSIBase); + TSSI_ref = TSSIBase = (TSSIBase & 0x003F); + + RT28xx_EEPROM_READ16(pAd, EEPROM_TSSI_OVER_OFDM_54, TSSIDelta); + TSSI_Set[1].delta = ((TSSIDelta >> 8) & 0xF);/* channel 1 TSSI delta */ + TSSI_Set[2].delta = ((TSSIDelta >> 12) & 0xF);/* channel 2 TSSI delta */ + + RT28xx_EEPROM_READ16(pAd, EEPROM_TSSI_DELTA_CH3_CH4, TSSIDelta); + TSSI_Set[3].delta = ((TSSIDelta >> 0) & 0xF);/* channel 3 TSSI delta */ + TSSI_Set[4].delta = ((TSSIDelta >> 4) & 0xF);/* channel 4 TSSI delta */ + TSSI_Set[5].delta = ((TSSIDelta >> 8) & 0xF);/* channel 5 TSSI delta */ + TSSI_Set[6].delta = ((TSSIDelta >> 12) & 0xF);/* channel 6 TSSI delta */ + + RT28xx_EEPROM_READ16(pAd, EEPROM_TSSI_DELTA_CH7_CH8, TSSIDelta); + TSSI_Set[7].delta = ((TSSIDelta >> 0) & 0xF);/* channel 7 TSSI delta */ + TSSI_Set[8].delta = ((TSSIDelta >> 4) & 0xF);/* channel 8 TSSI delta */ + TSSI_Set[9].delta = ((TSSIDelta >> 8) & 0xF);/* channel 9 TSSI delta */ + TSSI_Set[10].delta = ((TSSIDelta >> 12) & 0xF);/* channel 10 TSSI delta */ + + RT28xx_EEPROM_READ16(pAd, EEPROM_TSSI_DELTA_CH11_CH12, TSSIDelta); + TSSI_Set[11].delta = ((TSSIDelta >> 0) & 0xF);/*channel 11 TSSI delta */ + TSSI_Set[12].delta = ((TSSIDelta >> 4) & 0xF);/* channel 12 TSSI delta */ + TSSI_Set[13].delta = ((TSSIDelta >> 8) & 0xF);/* channel 13 TSSI delta */ + TSSI_Set[14].delta = ((TSSIDelta >> 12) & 0xF);/* channel 14 TSSI delta */ + + for(i=1;i<15;i++) + { + DBGPRINT(RT_DEBUG_OFF, ("Channel %d TSSI delta=%d\n", i, TSSI_Set[i].delta)); + } + + TSSI_x.delta = TSSI_Set[pAd->CommonCfg.Channel].delta; + + RT28xx_EEPROM_READ16(pAd, (EEPROM_OFDM_MCS6_MCS7 - 1), TxPowerOFDM54); + TxPowerOFDM54 = (0x000F & (TxPowerOFDM54 >> 8)); + + DBGPRINT(RT_DEBUG_OFF, ("TSSIBase(0x6E) = %X, TxPowerOFDM54 = %X\n", TSSIBase, TxPowerOFDM54)); + + /* The desired TSSI over CCK */ + RT28xx_EEPROM_READ16(pAd, EEPROM_CCK_MCS0_MCS1, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_CCK_MCS0_MCS1(0xDE) = 0x%X\n", TxPower)); + RT5350_desiredTSSIOverCCK[MCS_0] = TSSIBase * RTMP_CHIP_ASIC_GET_TSSI_RATIO(pAd, TxPower - TxPowerOFDM54 + 3 + TSSI_x.delta); + RT5350_desiredTSSIOverCCK[MCS_1] = RT5350_desiredTSSIOverCCK[MCS_0]; + + RT28xx_EEPROM_READ16(pAd, (EEPROM_CCK_MCS2_MCS3 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_CCK_MCS2_MCS3(0xDF) = 0x%X\n", TxPower)); + RT5350_desiredTSSIOverCCK[MCS_2] = TSSIBase * RTMP_CHIP_ASIC_GET_TSSI_RATIO(pAd, TxPower - TxPowerOFDM54 + 3 + TSSI_x.delta); + RT5350_desiredTSSIOverCCK[MCS_3] = RT5350_desiredTSSIOverCCK[MCS_2]; + + /* Boundary verification: the desired TSSI value */ + for (i = 0; i < 4; i++)/* CCK: MCS 0 ~ MCS 3 */ + { + if(RT5350_desiredTSSIOverCCK[i] > 0x7C*10000) + { + RT5350_desiredTSSIOverCCK[i] = 0x7C*10000; + } + DBGPRINT(RT_DEBUG_TRACE, ("RT5350_desiredTSSIOverCCK[%d] = %d\n", i, RT5350_desiredTSSIOverCCK[i])); + } + + /* The desired TSSI over OFDM */ + RT28xx_EEPROM_READ16(pAd, EEPROM_OFDM_MCS0_MCS1, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_OFDM_MCS0_MCS1(0xE0) = 0x%X\n", TxPower)); + RT5350_desiredTSSIOverOFDM[MCS_0] = (TSSIBase * RTMP_CHIP_ASIC_GET_TSSI_RATIO(pAd, TxPower - TxPowerOFDM54 + TSSI_x.delta)); + RT5350_desiredTSSIOverOFDM[MCS_1] = RT5350_desiredTSSIOverOFDM[MCS_0]; + + + RT28xx_EEPROM_READ16(pAd, (EEPROM_OFDM_MCS2_MCS3-1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_OFDM_MCS2_MCS3(0xE1) = 0x%X\n", TxPower)); + RT5350_desiredTSSIOverOFDM[MCS_2] = (TSSIBase * RTMP_CHIP_ASIC_GET_TSSI_RATIO(pAd, TxPower - TxPowerOFDM54 + TSSI_x.delta)); + RT5350_desiredTSSIOverOFDM[MCS_3] = RT5350_desiredTSSIOverOFDM[MCS_2]; + + RT28xx_EEPROM_READ16(pAd, EEPROM_OFDM_MCS4_MCS5, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_OFDM_MCS4_MCS5(0xE2) = 0x%X\n", TxPower)); + RT5350_desiredTSSIOverOFDM[MCS_4] = (TSSIBase * RTMP_CHIP_ASIC_GET_TSSI_RATIO(pAd, TxPower - TxPowerOFDM54 + TSSI_x.delta)); + RT5350_desiredTSSIOverOFDM[MCS_5] = RT5350_desiredTSSIOverOFDM[MCS_4]; + + RT28xx_EEPROM_READ16(pAd, EEPROM_OFDM_MCS6_MCS7-1, TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_OFDM_MCS6_MCS7(0xE3) = 0x%X\n", TxPower)); + RT5350_desiredTSSIOverOFDM[MCS_6] = (TSSIBase * RTMP_CHIP_ASIC_GET_TSSI_RATIO(pAd, 0)); + RT5350_desiredTSSIOverOFDM[MCS_7] = RT5350_desiredTSSIOverOFDM[MCS_6]; + + /* Boundary verification: the desired TSSI value */ + for (i = 0; i < 8; i++)/* OFDM: MCS 0 ~ MCS 7 */ + { + if (RT5350_desiredTSSIOverOFDM[i] > 0x7C*10000) + { + RT5350_desiredTSSIOverOFDM[i] = 0x7C*10000; + } + DBGPRINT(RT_DEBUG_TRACE, ("RT5350_desiredTSSIOverOFDM[%d] = %d\n", i, RT5350_desiredTSSIOverOFDM[i])); + } + + /* The desired TSSI over HT */ + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_MCS0_MCS1, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_HT_MCS0_MCS1(0xE4) = 0x%X\n", TxPower)); + RT5350_desiredTSSIOverHT[MCS_0] = (TSSIBase * RTMP_CHIP_ASIC_GET_TSSI_RATIO(pAd, TxPower - TxPowerOFDM54 + TSSI_x.delta)); + RT5350_desiredTSSIOverHT[MCS_1] = RT5350_desiredTSSIOverHT[MCS_0]; + RT5350_desiredTSSIOverHT40[MCS_0] = (TSSIBase * RTMP_CHIP_ASIC_GET_TSSI_RATIO(pAd, TxPower - TxPowerOFDM54 + TSSI_x.delta + BWPowerDelta)); + RT5350_desiredTSSIOverHT40[MCS_1] = RT5350_desiredTSSIOverHT40[MCS_0]; + + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_MCS2_MCS3-1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_HT_MCS2_MCS3(0xE5) = 0x%X\n", TxPower)); + RT5350_desiredTSSIOverHT[MCS_2] = (TSSIBase * RTMP_CHIP_ASIC_GET_TSSI_RATIO(pAd, TxPower - TxPowerOFDM54 + TSSI_x.delta)); + RT5350_desiredTSSIOverHT[MCS_3] = RT5350_desiredTSSIOverHT[MCS_2]; + RT5350_desiredTSSIOverHT40[MCS_2] = (TSSIBase * RTMP_CHIP_ASIC_GET_TSSI_RATIO(pAd, TxPower - TxPowerOFDM54 + TSSI_x.delta + BWPowerDelta)); + RT5350_desiredTSSIOverHT40[MCS_3] = RT5350_desiredTSSIOverHT40[MCS_2]; + + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_MCS4_MCS5, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_HT_MCS4_MCS5(0xE6) = 0x%X\n", TxPower)); + RT5350_desiredTSSIOverHT[MCS_4] = (TSSIBase * RTMP_CHIP_ASIC_GET_TSSI_RATIO(pAd, TxPower - TxPowerOFDM54 + TSSI_x.delta)); + RT5350_desiredTSSIOverHT[MCS_5] = RT5350_desiredTSSIOverHT[MCS_4]; + RT5350_desiredTSSIOverHT40[MCS_4] = (TSSIBase * RTMP_CHIP_ASIC_GET_TSSI_RATIO(pAd, TxPower - TxPowerOFDM54 + TSSI_x.delta + BWPowerDelta)); + RT5350_desiredTSSIOverHT40[MCS_5] = TSSIBase * RTMP_CHIP_ASIC_GET_TSSI_RATIO(pAd, TxPower - TxPowerOFDM54 + TSSI_x.delta - 1 + BWPowerDelta); + + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_MCS6_MCS7-1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_HT_MCS6_MCS7(0xE7) = 0x%X\n", TxPower)); + RT5350_desiredTSSIOverHT[MCS_6] = (TSSIBase * RTMP_CHIP_ASIC_GET_TSSI_RATIO(pAd, TxPower - TxPowerOFDM54 + TSSI_x.delta)); + RT5350_desiredTSSIOverHT[MCS_7] = RT5350_desiredTSSIOverHT[MCS_6]; + RT5350_desiredTSSIOverHT40[MCS_6] = TSSIBase * RTMP_CHIP_ASIC_GET_TSSI_RATIO(pAd, TxPower - TxPowerOFDM54 + TSSI_x.delta - 1 + BWPowerDelta); + RT5350_desiredTSSIOverHT40[MCS_7] = RT5350_desiredTSSIOverHT40[MCS_6]; + + /* Boundary verification: the desired TSSI value */ + for (i = 0; i < 8; i++)/* HT: MCS 0 ~ MCS 7 */ + { + if (RT5350_desiredTSSIOverHT[i] > 0x7C*10000) + { + RT5350_desiredTSSIOverHT[i] = 0x7C*10000; + } + + if (RT5350_desiredTSSIOverHT40[i] > 0x7C*10000) + { + RT5350_desiredTSSIOverHT40[i] = 0x7C*10000; + } + + DBGPRINT(RT_DEBUG_OFF, ("desiredTSSIOverHT[%d] = %d\n", i, RT5350_desiredTSSIOverHT[i])); + DBGPRINT(RT_DEBUG_OFF, ("desiredTSSIOverHT40[%d] = %d\n", i, RT5350_desiredTSSIOverHT40[i])); + } + + /* STBC is not supported by 1T1R chipset */ + RT28xx_EEPROM_READ16(pAd, EEPROM_TSSI_GAIN_ATTENUATION, TSSIParm); + + /* if EEPROM 0x76 is 0xFF or 0x00, sw will ignore the EEPROM & use sw default value */ + if (TSSIParm==0x00 || TSSIParm==0xFF) + { + /* tssi_gain<1:0>: + * 11: 12db + * 10: 9.5db + * 01: 6db (default) + * 00: 0db + * tssi_atten<3:2>: + * 00: -16db + * 01: -19db + * 10: -21 (default) + * 11: -23 + */ + RFValue = (0x3 | 0x0<<2); + } + else + { + TSSIGain = (TSSIParm & 0x3); + TSSIAttenuation = (TSSIParm >> 2) & 0x3; + RFValue |= TSSIGain; + RFValue |= (TSSIAttenuation << 2); + } + + RT30xxWriteRFRegister(pAd, RF_R27, RFValue); + + RFValue = 0x0; + RT30xxWriteRFRegister(pAd, RF_R28, RFValue); + + RT30xxReadRFRegister(pAd, RF_R29, &RFValue); + RFValue = 0x0; + RT30xxWriteRFRegister(pAd, RF_R29, RFValue); + + /* ADC6_on=1, TSSI_MODE=2(new averaged TSSI mode) */ + BbpR47 = (0x2<<3 | 0x1 << 7); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BbpR47); + + /* Initialize the index of the internal Tx ALC table */ + pAd->TxPowerCtrl.idxTxPowerTable = pAd->TxPower[pAd->CommonCfg.Channel].Power; + +} + + +UCHAR CCK_Rate2MCS( + IN PRTMP_ADAPTER pAd) +{ + UCHAR mcs = 0, dot11b_rate; + + + UCHAR BbpR47 = 0; + UCHAR TssiInfo1 = 0; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpR47); + BbpR47 &= ~0x3; + BbpR47 |= 1; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BbpR47 ); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &TssiInfo1); + dot11b_rate = (TssiInfo1 >> 4) & 0xF; // tssi_report[13:12]=11b rate + + switch(dot11b_rate) { + case 8: + mcs = 0; /* Long preamble CCK 1Mbps */ + break; + case 9: + mcs = 1; /* Long preamble CCK 2Mbps */ + break; + case 10: + mcs = 2; /* Long preamble CCK 5.5Mbps */ + break; + case 11: + mcs = 3; /* Long preamble CCK 11Mbps */ + break; + default: + mcs = 0; + }; + + return mcs; +} + + +UCHAR OFDM_Rate2MCS( + IN PRTMP_ADAPTER pAd) +{ + UCHAR mcs = 0, ofdm_rate; + + + UCHAR BbpR47 = 0; + UCHAR TssiInfo1 = 0; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpR47); + BbpR47 &= ~0x3; + BbpR47 |= 1; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BbpR47 ); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &TssiInfo1); + ofdm_rate = (TssiInfo1 >> 4) & 0xF; //rssi_15:12]=ofdm_rate + + switch (ofdm_rate) { + case 0xb: + mcs = 0; /* 6Mbps Rate */ + break; + case 0xf: + mcs = 1; /* 9Mbps Rate */ + break; + case 0xa: + mcs = 2; /* 12Mbps Rate */ + break; + case 0xe: + mcs = 3; /* 18Mbps Rate */ + break; + case 0x9: + mcs = 4; /* 24Mbps Rate */ + break; + case 0xd: + mcs = 5; /* 36Mbps Rate */ + break; + case 0x8: + mcs = 6; /* 48Mbps Rate */ + break; + case 0xc: + mcs = 7; /* 54Mbps Rate */ + break; + default: + mcs = 6; + }; + + return mcs; +} + + +/* + ========================================================================== + Description: + Get the desired TSSI based on the latest packet + + Arguments: + pAd + pBbpR49 + + Return Value: + The desired TSSI + ========================================================================== + */ +UINT32 RT5350_GetDesiredTSSI( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBbpR49) +{ + UINT32 desiredTSSI = 0; + UCHAR MCS = 0; + UCHAR BbpR47 = 0; + UCHAR TssiInfo0 = 0; + UCHAR TssiInfo1 = 0; + UCHAR TssiInfo2 = 0; + UCHAR i; + UCHAR BBP_Bandwidth = 0; + UCHAR ofdm_rate = 0, dot11b_rate = 0; + + BBP_Bandwidth = pAd->CommonCfg.BBPCurrentBW; + + /* Get TSSI_INFO */ + for (i=0;i<100;i++) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpR47); + + if (!(BbpR47 & (1<<2))) + { + /* self-cleared when the TSSI_INFO is updated */ + /* Get TSSI_INFO0 = tssi_report[7:0] */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpR47); + BbpR47 &= ~0x3; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BbpR47 ); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &TssiInfo0); + + /* If TSSI reading is not within 0x0~0x7C, then treated it as 0. */ + if (TssiInfo0 > 0x7C) + { + DBGPRINT(RT_DEBUG_TRACE, ("TSSI: BBP_R49=%X is native value\n", TssiInfo0)); + *pBbpR49 = TssiInfo0 = 0; + } + else + { + *pBbpR49 = TssiInfo0; + } + + /* Get TSSI_INFO1 = tssi_report[15:8] */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpR47); + BbpR47 &= ~0x3; + BbpR47 |= 1; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BbpR47 ); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &TssiInfo1); + + switch (TssiInfo1 & 0x03) + { + case 0: /* CCK */ + dot11b_rate = (TssiInfo1 >> 4) & 0xF; /* tssi_report[13:12]=11b rate */ + + switch(dot11b_rate) + { + case 8: + MCS = 0; /* Long preamble CCK 1Mbps */ + break; + case 9: + MCS = 1; /* Long preamble CCK 2Mbps */ + break; + case 10: + MCS = 2; /* Long preamble CCK 5.5Mbps */ + break; + case 11: + MCS = 3; /* Long preamble CCK 11Mbps */ + break; + default: + MCS = 0; + break; + } + desiredTSSI = RT5350_desiredTSSIOverCCK[MCS]; + DBGPRINT(RT_DEBUG_INFO, ("CCK: desiredTSSI = %d, MCS = %d\n", desiredTSSI, MCS)); + break; + + case 1: /* OFDM */ + ofdm_rate = (TssiInfo1 >> 4) & 0xF; /* rssi_15:12]=ofdm_rate */ + + switch (ofdm_rate) + { + case 0xb: + MCS = 0; /* 6Mbps Rate */ + break; + case 0xf: + MCS = 1; /* 9Mbps Rate */ + break; + case 0xa: + MCS = 2; /* 12Mbps Rate */ + break; + case 0xe: + MCS = 3; /* 18Mbps Rate */ + break; + case 0x9: + MCS = 4; /* 24Mbps Rate */ + break; + case 0xd: + MCS = 5; /* 36Mbps Rate */ + break; + case 0x8: + MCS = 6; /* 48Mbps Rate */ + break; + case 0xc: + MCS = 7; /* 54Mbps Rate */ + break; + default: + MCS = 6; + break; + }; + desiredTSSI = RT5350_desiredTSSIOverOFDM[MCS]; + DBGPRINT(RT_DEBUG_INFO, ("OFDM: desiredTSSI = %d, MCS = %d\n", desiredTSSI, MCS)); + break; + + case 2: /* HT */ + DBGPRINT(RT_DEBUG_INFO, ("mixed mode or green-field mode\n")); + + /* Get TSSI_INFO2 = tssi_report[23:16] */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpR47); + BbpR47 &= ~0x3; + BbpR47 |= 1<<1; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BbpR47 ); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &TssiInfo2); + MCS = TssiInfo2 & 0x7F; /* tssi_report[22:16]=MCS */ + if ((BBP_Bandwidth == BW_40) + && ((MCS == 5) || (MCS == 6) || (MCS == 7))) + { + desiredTSSI = RT5350_desiredTSSIOverHT40[MCS]; + } + else + desiredTSSI = RT5350_desiredTSSIOverHT[MCS]; + + DBGPRINT(RT_DEBUG_INFO, ("HT: desiredTSSI = %d, MCS = %d\n", desiredTSSI, MCS)); + break; + } + break; + } + } + + /* clear TSSI_UPDATE_REQ first */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpR47); + BbpR47 &= ~0x7; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BbpR47 ); + + /* write 1 to enable TSSI_INFO update */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpR47); + BbpR47 |= (1<<2); /* TSSI_UPDATE_REQ */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BbpR47 ); + + return desiredTSSI; +} +#endif /* RTMP_INTERNAL_TX_ALC */ + + +VOID RT5350_ChipAGCInit( + IN PRTMP_ADAPTER pAd, + IN UCHAR BandWidth) +{ + UCHAR R66 = 0x30; + + if (pAd->LatchRfRegs.Channel <= 14) + { // BG band + R66 = 0x2E + GET_LNA_GAIN(pAd); + AsicBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + } + else + { //A band + if (BandWidth == BW_20) + R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3); +#ifdef DOT11_N_SUPPORT + else + R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3); +#endif // DOT11_N_SUPPORT // + AsicBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + } + +} + +#endif // RT5350 // + +/* End of rt5350.c */ diff --git a/mt7620/src/chips/rt6352.c b/mt7620/src/chips/rt6352.c new file mode 100644 index 0000000..ccc9f42 --- /dev/null +++ b/mt7620/src/chips/rt6352.c @@ -0,0 +1,5572 @@ +/* + *************************************************************************** + * 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, 0x28}, + {BBP_R174, 0x28}, + {BBP_R175, 0x21}, + {BBP_R176, 0x1C}, + {BBP_R177, 0x20}, + {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, 0x000C0000}, // Jason,2012-09-13 + {TX_SW_CFG2, 0x00}, // Jason,2012-08-27 + {MIMO_PS_CFG, 0x02}, // Jason,2012-09-13 +}; + +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 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 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); + + 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_ERROR, ("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_ERROR, ("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_ERROR, ("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_ERROR, ("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_ERROR, ("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_ERROR, ("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_ERROR, ("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_ERROR, ("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) + AsicBBPWriteWithRxChain(pAd, BBP_R66, 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); + + RtmpUpdateFilterCoefficientControl(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*/ + /*AsicBBPWriteWithRxChain(pAd, BBP_R66, (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); + + AsicBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + +#ifdef DYNAMIC_VGA_SUPPORT + /* Backup BBP_R65 */ + pAd->CommonCfg.MO_Cfg.Stored_BBP_R66 = R66; +#endif /* DYNAMIC_VGA_SUPPORT */ + +} + +#ifdef RTMP_INTERNAL_TX_ALC +INT16 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, 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 = 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 = 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 = 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 = 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, 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 = 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 < 3; 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 = 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 = 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 +UCHAR GetSkuMinPwr( + IN PRTMP_ADAPTER pAd) +{ + if (pAd->CommonCfg.SkuChannel > 11) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s::no such channel\n", __FUNCTION__)); + return 0x20; /* default is 16 dBm */ + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s::Single-SKU at channel#%d\n", + __FUNCTION__, pAd->CommonCfg.SkuChannel)); + + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + return (sku_min_pwr_20bw[pAd->CommonCfg.SkuChannel - 1] * 2); + else if (pAd->CommonCfg.BBPCurrentBW == BW_40) + return (sku_min_pwr_40bw[pAd->CommonCfg.SkuChannel - 1] * 2); +} +} + +UCHAR GetSkuRatePwr( + IN PRTMP_ADAPTER pAd, + IN CHAR phymode, + IN UCHAR channel) +{ + INT i = 0; + + for (i = 0; i < pAd->ChannelListNum; i++) + { + if (pAd->ChannelList[i].Channel == channel) + break; + } + + if (i == pAd->ChannelListNum) + return 0xFF; + + switch (phymode) + { + case MODE_CCK: + pAd->ChannelList[i].MaxTxPwr = 18; + break; + + case MODE_OFDM: + if (channel == 1) + pAd->ChannelList[i].MaxTxPwr = 16; + else if (channel == 11) + pAd->ChannelList[i].MaxTxPwr = 15; + else + pAd->ChannelList[i].MaxTxPwr = 17; + break; + + case MODE_HTMIX: + default: + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + { + if ((channel == 1) || (channel == 10)) + pAd->ChannelList[i].MaxTxPwr = 14; + else if (channel == 11) + pAd->ChannelList[i].MaxTxPwr = 13; + else + pAd->ChannelList[i].MaxTxPwr = 16; + } + else if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + UCHAR cetl_chl = pAd->CommonCfg.CentralChannel; + + if (cetl_chl == 3) + pAd->ChannelList[i].MaxTxPwr = 11; + else if ((cetl_chl == 4) || (cetl_chl == 8)) + pAd->ChannelList[i].MaxTxPwr = 12; + else if (cetl_chl == 9) + pAd->ChannelList[i].MaxTxPwr = 10; + else + pAd->ChannelList[i].MaxTxPwr = 14; + } + break; + } + + return (pAd->ChannelList[i].MaxTxPwr * 2); +} + +CHAR RT6352_AdjustChannelPwr( + IN PRTMP_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 = 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; + + target_power = (target_power > sku_min_pwr) ? sku_min_pwr : target_power; + + if (target_power < 0) + target_power = 0; + + 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); + } + DBGPRINT(RT_DEBUG_TRACE, ("%s::mac 0x13B0 is 0x%08x\n", __FUNCTION__, mac_value)); + } + else /* Manual/Temperature mode */ +#endif /* RTMP_INTERNAL_TX_ALC */ + { + INT32 diff = 0; + 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; + + 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); + + 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;//, mcs_digpwr_diff; + 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 */ + } + } + + 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; + + 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); +} +#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<6; 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 */ + DoDPDCalibration(pAd); + } + } + + 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) + { + if (RT6352_TemperatureCompensation(pAd, TRUE) == TRUE) + { + INT32 TemperatureDiff = 0; + + TemperatureDiff = ((pAd->CurrTemperature - pAd->TemperatureRef25C) * 19) - pAd->DoCalibrationTemperature; + +#ifdef RT6352_EP_SUPPORT + if ((TemperatureDiff >= 400) || (TemperatureDiff <= -400)) + { + RT6352_ReCalibration(pAd); + pAd->DoCalibrationTemperature = (pAd->CurrTemperature - pAd->TemperatureRef25C) * 19; + } +#endif /* RT6352_EP_SUPPORT */ + } + } + + return; + } + else +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + { +#ifdef RTMP_TEMPERATURE_CALIBRATION + if (pAd->bCalibrationDone) + { + UINT8 bbpval; + CHAR BBPR49; + int wait; + INT32 TemperatureDiff = 0; + + 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 < 3; 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; + + TemperatureDiff = ((pAd->CurrTemperature - pAd->TemperatureRef25C) * 19) - pAd->DoCalibrationTemperature; + +#ifdef RT6352_EP_SUPPORT + if ((TemperatureDiff >= 400) || (TemperatureDiff <= -400)) + { + RT6352_ReCalibration(pAd); + pAd->DoCalibrationTemperature = (pAd->CurrTemperature - pAd->TemperatureRef25C) * 19; + } +#endif /* RT6352_EP_SUPPORT */ + } + } +#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, RFValue; + printk("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, RF_BYPASS0 , &orig_RF_BYPASS0); + + RTMP_IO_WRITE32(pAd, RF_BYPASS0 , 0x0); + /* MAC Bypass */ + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x0004); + RTMP_IO_WRITE32(pAd, 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; + pAd->DoCalibrationTemperature = (pAd->CurrTemperature - pAd->TemperatureRef25C) * 19; + + 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, RF_BYPASS0 , 0x0); + RTMP_IO_WRITE32(pAd, RF_CONTROL0 , orig_RF_CONTROL0); + RTMP_IO_WRITE32(pAd, RF_BYPASS0 , orig_RF_BYPASS0); + + pAd->bLowTemperatureTrigger = FALSE; + pAd->CurrTemperatureMode = TEMPERATURE_MODE_NORMAL; + + + 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_ERROR, ("%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_ERROR, ("%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%lx)\n", GpioMode)); + RTMP_SYS_IO_READ32(0xb0000060, &GpioMode); + DBGPRINT(RT_DEBUG_ERROR,("After Change, now GPIO_MODE value is 0x%lx\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_EP_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 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 */ + +UINT32 mt6532_get_current_temp( + IN RTMP_ADAPTER *pAd) +{ + UINT32 current_temp = 0; + current_temp = (19*(pAd->CurrTemperature - pAd->TemperatureRef25C))/10 + 25; + return current_temp; +} + + +/* +======================================================================== +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; + + /* init capability */ + pChipCap->MaxNumOfRfId = 64; + pChipCap->MaxNumOfBbpId = 255; + pChipCap->bbpRegTbSize = 0; + 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 = mt6532_get_current_temp; + +#ifdef THERMAL_PROTECT_SUPPORT + 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->FlgIsVcoReCalMode = VCO_CAL_MODE_3; + pChipCap->TXWISize = 20; + pChipCap->RXWISize = 24; + pChipCap->WPDMABurstSIZE = 2; + pChipCap->DPDCalPassThres = 5; + pChipCap->DPDCalPassLowThresTX0 = -999; + pChipCap->DPDCalPassLowThresTX1 = 0; + pChipCap->DPDCalPassHighThresTX0 = 5; + pChipCap->DPDCalPassHighThresTX1 = 15; +#ifdef RTMP_FLASH_SUPPORT + pChipCap->eebuf = 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 MCS_LUT_SUPPORT + pChipCap->bFlgHwTxLuCap = TRUE; +#endif /* MCS_LUT_SUPPORT */ + +#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; + 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 SPECIFIC_BCN_BUF_SUPPORT + RtmpChipBcnSpecInit(pAd); +#else + RtmpChipBcnInit(pAd); +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ +} +#endif /* RT6352 */ +/* End of rt3352.c */ + diff --git a/mt7620/src/chips/rt6352.c.bak b/mt7620/src/chips/rt6352.c.bak new file mode 100755 index 0000000..8535650 --- /dev/null +++ b/mt7620/src/chips/rt6352.c.bak @@ -0,0 +1,2216 @@ +/* + *************************************************************************** + * 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, 0x01, 0x01, 0x00, 0x0c, 0x43, 0x30, 0x52, 0x88, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 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, 0x33, 0x52, 0x77, 0x00, 0x0c, 0x43, 0x33, 0x52, 0x66, 0x22, 0x0c, 0x20, 0x00, + 0xff, 0xff, 0x2f, 0x01, 0x55, 0x77, 0xa8, 0xaa, 0x8c, 0x88, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x10, 0x10, + 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x14, 0x14, 0x14, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x66, 0x66, + 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, 0x88, 0x66, 0xcc, 0xaa, + 0x88, 0x66, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 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_R05, 0x20}, /* 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_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_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, 0x08}, + {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, 0x35}, + {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}, +#if 1 + {BBP_R157, BW_20, 0x40}, + {BBP_R157, BW_40, 0x2F}, +#endif +}; + +/* 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, 0x0404}, // Gary,2010-07-20 + {TX_SW_CFG1, 0x00}, // Gary,2010-08-17 + {TX_SW_CFG2, 0x00}, // Gary,2010-08-17 +#if 0 + {BB_PA_MODE_CFG0, 0x000055FF}, // Gary,2012-03-28 + {BB_PA_MODE_CFG1, 0x00550055}, // Gary,2012-03-28 + {RF_PA_MODE_CFG0, 0x000055FF}, // Gary,2012-03-28 + {RF_PA_MODE_CFG1, 0x00550055}, // Gary,2012-03-28 +#endif +}; + +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 */ + +/* +======================================================================== +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 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_ALC_VGA3, 0x05050707); /* WH, 2012-08-20 */ + RTMP_IO_WRITE32(pAd, TX0_BB_GAIN_ATTEN, 0x0); + RTMP_IO_WRITE32(pAd, TX1_BB_GAIN_ATTEN, 0x0); + } + + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &Value); + Value = Value & (~0x80000000); + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_1, Value); +#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, 0x07); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R92, 0x04); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R148, 0x84); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R167, 0x80); + } + + /* 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 */ + /* 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); + MacValue1 = MacValue; + MacValue1 |= 0x8; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacValue1); + + /* 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 |= 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_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); + + 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); + + 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) +{ + //UINT8 RfReg = 0; + //ULONG value = 0; + UCHAR RFValue = 0; + int i; + + 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_ERROR, ("Initialize RF Central Registers for E2 !!!\n")); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R11, 0x21); + //RT635xWriteRFRegister(pAd, RF_BANK0, RF_R12, 0x40); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R13, 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); + } + + /* it is old RF_R17 */ + RFValue = pAd->RfFreqOffset & 0x7F; + 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_ERROR, ("Initialize RF Channel Registers for E2 !!!\n")); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R09, 0x13); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R09, 0x13); + 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, 0x2C); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R28, 0x2C); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R29, 0xEA); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R29, 0xEA); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R32, 0x7D); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R32, 0x7D); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R34, 0x56); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R34, 0x56); + 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, 0xE3); + 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, 0xE5); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R47, 0x67); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R47, 0x65); + 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, 0x00); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R58, 0x00); + 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); + } + +#ifdef RELEASE_EXCLUDE + /* 0: DRQFN-148 pin 1: TFBGA-269 ball */ +#endif /* RELEASE_EXCLUDE */ +#if 0 + if (pAd->CommonCfg.PKG_ID == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("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); + } + } +#endif + + // 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_ERROR, ("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); + } + + 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) + AsicBBPWriteWithRxChain(pAd, BBP_R66, 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 + + + /* + 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) + { + /* Frequeny plan setting */ + /* + * Rdiv setting + * R13[1:0] + */ + RT635xReadRFRegister(pAd, RF_BANK0, RF_R13, &RFValue); + RFValue = RFValue & (~0x03); + 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); + } + + /* + * bit<5:0> range from 0x0~0x27 + */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &Value); + Value = Value & (~0x3F3F); + Value |= TxPwer; + Value |= (TxPwer2 << 8); + Value |= (0x2F << 16); + Value |= (0x2F << 24); + + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_0, Value); + + 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.PKG_ID == 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 0 + /* 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_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); + } + 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_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); + } +#endif + 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); + + /* 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; + } + } + + /* BBP setting */ + if (Channel <= 14) + { + ULONG TxPinCfg = 0x00050F0A;/* 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; + + if (IS_RT6352(pAd)) + TxPinCfg |= 0x100000; + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + + RtmpUpdateFilterCoefficientControl(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); + } + } + + if (pAd->Antenna.field.RxPath == 1) + { + 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_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*/ + /*AsicBBPWriteWithRxChain(pAd, BBP_R66, (0x2E + lanGain), RX_CHAIN_ALL);*/ + if (bScan) + RTMPSetAGCInitValue(pAd, BW_20); + else + RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW); + + if (bScan == FALSE) + { + UCHAR BbpReg = 0; + UINT32 MacValue = 0, MacValue1 = 0; + USHORT k_count = 0; + + /* 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; + } + + /* 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 |= 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_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); + } + + /* 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); + + AsicBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + +#ifdef RELEASE_EXCLUDE + DBGPRINT(RT_DEBUG_INFO, ("RTMPAGCInit - Ch=%d, BandWidth=%d, LNA_GAIN=0x%x, set R66 as 0x%x \n", pAd->LatchRfRegs.Channel, BandWidth, GET_LNA_GAIN(pAd), R66)); +#endif /* RELEASE_EXCLUDE */ +} + +#ifdef RTMP_INTERNAL_TX_ALC +static VOID RT6352_InitDesiredTSSITable( + IN PRTMP_ADAPTER pAd) +{ + UCHAR TSSIBase = 0; /* The TSSI over OFDM 54Mbps */ + USHORT TSSIStepOver2dot4G = 0; /* The TSSI value/step (0.5 dB/unit) */ + UCHAR RFValue = 0; + BBP_R49_STRUC BbpR49; + ULONG i = 0; + USHORT TxPower = 0, TxPowerOFDM54 = 0, temp = 0; + + BbpR49.byte = 0; + + if (pAd->TxPowerCtrl.bInternalTxALC == FALSE) + { + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("---> %s\n", __FUNCTION__)); + + RT28xx_EEPROM_READ16(pAd, EEPROM_TSSI_OVER_OFDM_54, temp); + TSSIBase = (temp & 0x001F); + + RT28xx_EEPROM_READ16(pAd, (EEPROM_TSSI_STEP_OVER_2DOT4G - 1), TSSIStepOver2dot4G); + TSSIStepOver2dot4G = (0x000F & (TSSIStepOver2dot4G >> 8)); + + RT28xx_EEPROM_READ16(pAd, (EEPROM_OFDM_MCS6_MCS7 - 1), TxPowerOFDM54); + TxPowerOFDM54 = (0x000F & (TxPowerOFDM54 >> 8)); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: TSSIBase = %d, TSSIStepOver2dot4G = %d, TxPowerOFDM54 = %d\n", + __FUNCTION__, + TSSIBase, + TSSIStepOver2dot4G, + TxPowerOFDM54)); + + /* The desired TSSI over CCK */ + RT28xx_EEPROM_READ16(pAd, EEPROM_CCK_MCS0_MCS1, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xDE = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverCCK[MCS_0] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2)) + 6); + desiredTSSIOverCCK[MCS_1] = desiredTSSIOverCCK[MCS_0]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_CCK_MCS2_MCS3 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xDF = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverCCK[MCS_2] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2)) + 6); + desiredTSSIOverCCK[MCS_3] = desiredTSSIOverCCK[MCS_2]; + + /* Boundary verification: the desired TSSI value */ + for (i = 0; i < 4; i++) /* CCK: MCS 0 ~ MCS 3 */ + { + if (desiredTSSIOverCCK[i] < 0x00) + { + desiredTSSIOverCCK[i] = 0x00; + } + else if (desiredTSSIOverCCK[i] > 0x1F) + { + desiredTSSIOverCCK[i] = 0x1F; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverCCK[0] = %d, desiredTSSIOverCCK[1] = %d, desiredTSSIOverCCK[2] = %d, desiredTSSIOverCCK[3] = %d\n", + __FUNCTION__, + desiredTSSIOverCCK[0], + desiredTSSIOverCCK[1], + desiredTSSIOverCCK[2], + desiredTSSIOverCCK[3])); + + /* The desired TSSI over OFDM */ + RT28xx_EEPROM_READ16(pAd, EEPROM_OFDM_MCS0_MCS1, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE0 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverOFDM[MCS_0] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverOFDM[MCS_1] = desiredTSSIOverOFDM[MCS_0]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_OFDM_MCS2_MCS3 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE1 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverOFDM[MCS_2] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverOFDM[MCS_3] = desiredTSSIOverOFDM[MCS_2]; + RT28xx_EEPROM_READ16(pAd, EEPROM_OFDM_MCS4_MCS5, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE2 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverOFDM[MCS_4] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverOFDM[MCS_5] = desiredTSSIOverOFDM[MCS_4]; + desiredTSSIOverOFDM[MCS_6] = TSSIBase; + desiredTSSIOverOFDM[MCS_7] = TSSIBase; + + /* Boundary verification: the desired TSSI value */ + for (i = 0; i < 8; i++) /* OFDM: MCS 0 ~ MCS 7 */ + { + if (desiredTSSIOverOFDM[i] < 0x00) + { + desiredTSSIOverOFDM[i] = 0x00; + } + else if (desiredTSSIOverOFDM[i] > 0x1F) + { + desiredTSSIOverOFDM[i] = 0x1F; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverOFDM[0] = %d, desiredTSSIOverOFDM[1] = %d, desiredTSSIOverOFDM[2] = %d, desiredTSSIOverOFDM[3] = %d\n", + __FUNCTION__, + desiredTSSIOverOFDM[0], + desiredTSSIOverOFDM[1], + desiredTSSIOverOFDM[2], + desiredTSSIOverOFDM[3])); + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverOFDM[4] = %d, desiredTSSIOverOFDM[5] = %d, desiredTSSIOverOFDM[6] = %d, desiredTSSIOverOFDM[7] = %d\n", + __FUNCTION__, + desiredTSSIOverOFDM[4], + desiredTSSIOverOFDM[5], + desiredTSSIOverOFDM[6], + desiredTSSIOverOFDM[7])); + + /* The desired TSSI over HT */ + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_MCS0_MCS1, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE4 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHT[MCS_0] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_1] = desiredTSSIOverHT[MCS_0]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_MCS2_MCS3 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE5 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHT[MCS_2] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_3] = desiredTSSIOverHT[MCS_2]; + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_MCS4_MCS5, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE6 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHT[MCS_4] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_5] = desiredTSSIOverHT[MCS_4]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_MCS6_MCS7 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xE7 = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHT[MCS_6] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_7] = desiredTSSIOverHT[MCS_6] - 1; + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_MCS8_MCS9, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_HT_MCS9_MCS9(0xE8) = 0x%X\n", TxPower)); + desiredTSSIOverHT[MCS_8] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_9] = desiredTSSIOverHT[MCS_8]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_MCS10_MCS11 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_HT_MCS10_MCS11(0xE9) = 0x%X\n", TxPower)); + desiredTSSIOverHT[MCS_10] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_11] = desiredTSSIOverHT[MCS_10]; + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_MCS12_MCS13, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_HT_MCS12_MCS13(0xEA) = 0x%X\n", TxPower)); + desiredTSSIOverHT[MCS_12] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_13] = desiredTSSIOverHT[MCS_12]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_MCS14_MCS15 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("EEPROM_HT_MCS14_MCS15(0xEB) = 0x%X\n", TxPower)); + desiredTSSIOverHT[MCS_14] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHT[MCS_15] = desiredTSSIOverHT[MCS_14] - 1; + + /* Boundary verification: the desired TSSI value */ + for (i = 0; i < 16; i++) /* HT: MCS 0 ~ MCS 15 */ + { + if (desiredTSSIOverHT[i] < 0x00) + { + desiredTSSIOverHT[i] = 0x00; + } + else if (desiredTSSIOverHT[i] > 0x1F) + { + desiredTSSIOverHT[i] = 0x1F; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHT[0] = %d, desiredTSSIOverHT[1] = %d, desiredTSSIOverHT[2] = %d, desiredTSSIOverHT[3] = %d\n", + __FUNCTION__, + desiredTSSIOverHT[0], + desiredTSSIOverHT[1], + desiredTSSIOverHT[2], + desiredTSSIOverHT[3])); + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHT[4] = %d, desiredTSSIOverHT[5] = %d, desiredTSSIOverHT[6] = %d, desiredTSSIOverHT[7] = %d\n", + __FUNCTION__, + desiredTSSIOverHT[4], + desiredTSSIOverHT[5], + desiredTSSIOverHT[6], + desiredTSSIOverHT[7])); + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHT[8] = %d, desiredTSSIOverHT[9] = %d, desiredTSSIOverHT[10] = %d, desiredTSSIOverHT[11] = %d\n", + __FUNCTION__, + desiredTSSIOverHT[8], + desiredTSSIOverHT[9], + desiredTSSIOverHT[10], + desiredTSSIOverHT[11])); + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHT[12] = %d, desiredTSSIOverHT[13] = %d, desiredTSSIOverHT[14] = %d, desiredTSSIOverHT[15] = %d\n", + __FUNCTION__, + desiredTSSIOverHT[12], + desiredTSSIOverHT[13], + desiredTSSIOverHT[14], + desiredTSSIOverHT[15])); + + /* The desired TSSI over HT using STBC */ + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_USING_STBC_MCS0_MCS1, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xEC = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHTUsingSTBC[MCS_0] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHTUsingSTBC[MCS_1] = desiredTSSIOverHTUsingSTBC[MCS_0]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_USING_STBC_MCS2_MCS3 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xED = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHTUsingSTBC[MCS_2] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHTUsingSTBC[MCS_3] = desiredTSSIOverHTUsingSTBC[MCS_2]; + RT28xx_EEPROM_READ16(pAd, EEPROM_HT_USING_STBC_MCS4_MCS5, TxPower); + TxPower = (TxPower & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xEE = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHTUsingSTBC[MCS_4] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHTUsingSTBC[MCS_5] = desiredTSSIOverHTUsingSTBC[MCS_4]; + RT28xx_EEPROM_READ16(pAd, (EEPROM_HT_USING_STBC_MCS6_MCS7 - 1), TxPower); + TxPower = ((TxPower >> 8) & 0x000F); + DBGPRINT(RT_DEBUG_TRACE, ("%s: 0xEF = 0x%X\n", __FUNCTION__, TxPower)); + desiredTSSIOverHTUsingSTBC[MCS_6] = (TSSIBase + ((TxPower - TxPowerOFDM54) * (TSSIStepOver2dot4G * 2))); + desiredTSSIOverHTUsingSTBC[MCS_7] = desiredTSSIOverHTUsingSTBC[MCS_6]; + + /* Boundary verification: the desired TSSI value */ + for (i = 0; i < 8; i++) /* HT using STBC: MCS 0 ~ MCS 7 */ + { + if (desiredTSSIOverHTUsingSTBC[i] < 0x00) + { + desiredTSSIOverHTUsingSTBC[i] = 0x00; + } + else if (desiredTSSIOverHTUsingSTBC[i] > 0x1F) + { + desiredTSSIOverHTUsingSTBC[i] = 0x1F; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHTUsingSTBC[0] = %d, desiredTSSIOverHTUsingSTBC[1] = %d, desiredTSSIOverHTUsingSTBC[2] = %d, desiredTSSIOverHTUsingSTBC[3] = %d\n", + __FUNCTION__, + desiredTSSIOverHTUsingSTBC[0], + desiredTSSIOverHTUsingSTBC[1], + desiredTSSIOverHTUsingSTBC[2], + desiredTSSIOverHTUsingSTBC[3])); + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSIOverHTUsingSTBC[4] = %d, desiredTSSIOverHTUsingSTBC[5] = %d, desiredTSSIOverHTUsingSTBC[6] = %d, desiredTSSIOverHTUsingSTBC[7] = %d\n", + __FUNCTION__, + desiredTSSIOverHTUsingSTBC[4], + desiredTSSIOverHTUsingSTBC[5], + desiredTSSIOverHTUsingSTBC[6], + desiredTSSIOverHTUsingSTBC[7])); + + /* + * | RF_R28[5:4] | RF_R27[4] | RF_R27[5] + * | Adc5b_sel | Rf_tssi_sel | rf_tssi_en + *---------------+-------------+-----------+------------- + * Internal TSSI0 | 00 | 1 | 1 + * Internal TSSI1 | 10 | 0 | 1 + * External TSSI0 | 00 | 0 | 0 + * External TSSI1 | 10 | 1 | 0 + * + */ + + /* Internal TSSI0 */ + /* RFValue = (0x3 | 0x0<<2 | 0x1<<4 | 0x1 << 5); // tssi_gain0:x9, tssi_atten0:-17db, rf_tssi_sel=1, rf_tssi_en=1 */ + /* External TSSI0 */ + /* RFValue = (0x3 | 0x0<<2 | 0x0<<4 | 0x1 << 5); // tssi_gain0:x9, tssi_atten0:-17db, rf_tssi_sel=0, rf_tssi_en=1 */ + RFValue = (0x3 | 0x0<<2 | 0x3<<4);/* tssi_gain0:x9, tssi_atten0:-17db, rf_tssi_sel=0, rf_tssi_en=1 */ + /* Internal TSSI1 */ + /* RFValue = (0x3 | 0x0<<2 | 0x0<<4 | 0x1 << 5); // tssi_gain0:x9, tssi_atten0:-17db, rf_tssi_sel=0, rf_tssi_en=1 */ + RT30xxWriteRFRegister(pAd, RF_R27, RFValue); + + /* Internal TSSI0 */ + /* RFValue = (0x3 | 0x0<<2 | 0x2 << 4); // tssi_gain1:x9, tssi_atten1:-17db, Adc5b_sel=10 (Internal TSSI1) */ + RFValue = (0x3 | 0x0<<2);/* tssi_gain1:x9, tssi_atten1:-17db, Adc5b_sel=10 (Internal TSSI1) */ + /* Internal TSSI1 */ + /* RFValue = (0x3 | 0x0<<2 | 0x2 << 4); // tssi_gain1:x9, tssi_atten1:-17db, Adc5b_sel=10 (Internal TSSI1) */ + RT30xxWriteRFRegister(pAd, RF_R28, RFValue); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49.byte); + BbpR49.field.adc5_in_sel = 1; /* PSI */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R49, BbpR49.byte); + + DBGPRINT(RT_DEBUG_TRACE, ("<--- %s\n", __FUNCTION__)); +} + +/* + ========================================================================== + Description: + Get the desired TSSI based on the latest packet + + Arguments: + pAd + + Return Value: + The desired TSSI + ========================================================================== + */ +static UCHAR RT6352_GetDesiredTSSI( + IN PRTMP_ADAPTER pAd) +{ + PHTTRANSMIT_SETTING pLatestTxHTSetting = (PHTTRANSMIT_SETTING)(&pAd->LastTxRate); + UCHAR desiredTSSI = 0; + UCHAR MCS = 0; + + MCS = (UCHAR)(pLatestTxHTSetting->field.MCS); + + if (pLatestTxHTSetting->field.MODE == MODE_CCK) + { + if ((MCS < 0) || (MCS > 3)) /* boundary verification */ + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: incorrect MCS: MCS = %d\n", __FUNCTION__, MCS)); + MCS = 0; + } + + desiredTSSI = desiredTSSIOverCCK[MCS]; + } + else if (pLatestTxHTSetting->field.MODE == MODE_OFDM) + { + if ((MCS < 0) || (MCS > 7)) /* boundary verification */ + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: incorrect MCS: MCS = %d\n", __FUNCTION__, MCS)); + MCS = 0; + } + + desiredTSSI = desiredTSSIOverOFDM[MCS]; + } + else if ((pLatestTxHTSetting->field.MODE == MODE_HTMIX) || (pLatestTxHTSetting->field.MODE == MODE_HTGREENFIELD)) + { + if ((MCS < 0) || (MCS > 15)) /* boundary verification */ + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: incorrect MCS: MCS = %d\n", __FUNCTION__, MCS)); + MCS = 0; + } + + if (pLatestTxHTSetting->field.STBC == 1) + { + desiredTSSI = desiredTSSIOverHT[MCS]; + } + else + { + desiredTSSI = desiredTSSIOverHTUsingSTBC[MCS]; + } + + /* For HT BW40 MCS 7 with/without STBC configuration, the desired TSSI value should subtract one from the formula */ + if ((pLatestTxHTSetting->field.BW == BW_40) && (MCS == MCS_7)) + { + desiredTSSI -= 1; + } + } + + DBGPRINT(RT_DEBUG_INFO, ("%s: desiredTSSI = %d, Latest Tx HT setting: MODE = %d, MCS = %d, STBC = %d\n", + __FUNCTION__, + desiredTSSI, + pLatestTxHTSetting->field.MODE, + pLatestTxHTSetting->field.MCS, + pLatestTxHTSetting->field.STBC)); + + DBGPRINT(RT_DEBUG_INFO, ("<--- %s\n", __FUNCTION__)); + + return desiredTSSI; +} + +static VOID RT6352_AsicTxAlcGetAutoAgcOffset( + IN PRTMP_ADAPTER pAd, + IN PCHAR pDeltaPwr, + IN PCHAR pTotalDeltaPwr, + IN PCHAR pAgcCompensate, + IN PCHAR pDeltaPowerByBbpR1) +{ + const TX_POWER_TUNING_ENTRY_STRUCT *TxPowerTuningTable = pAd->chipCap.TxPowerTuningTable_2G; + PTX_POWER_TUNING_ENTRY_STRUCT pTxPowerTuningEntry = NULL; + BBP_R49_STRUC BbpR49; + UCHAR RFValue = 0; + CHAR desiredTssi = 0; + CHAR currentTssi = 0; + CHAR DeltaPwr = 0; + CHAR TotalDeltaPower = 0; + CHAR TuningTableIndex = 0; + + BbpR49.byte = 0; + + /* Locate the Internal Tx ALC tuning entry */ + if ((pAd->TxPowerCtrl.bInternalTxALC == TRUE) && (IS_RT6352(pAd))) + { + if ((pAd->Mlme.OneSecPeriodicRound % 4 == 0) && (*pDeltaPowerByBbpR1 == 0)) + { + desiredTssi = RT6352_GetDesiredTSSI(pAd); + + if (desiredTssi == -1) + { + goto LabelFail; + } + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49.byte); + currentTssi = BbpR49.field.TSSI; + + if (desiredTssi > currentTssi) + { + pAd->TxPowerCtrl.idxTxPowerTable++; + } + + if (desiredTssi < currentTssi) + { + pAd->TxPowerCtrl.idxTxPowerTable--; + } + + TuningTableIndex = pAd->TxPowerCtrl.idxTxPowerTable +#ifdef DOT11_N_SUPPORT + + pAd->TxPower[pAd->CommonCfg.CentralChannel-1].Power; +#else + + pAd->TxPower[pAd->CommonCfg.Channel-1].Power; +#endif /* DOT11_N_SUPPORT */ + + if (TuningTableIndex < LOWERBOUND_TX_POWER_TUNING_ENTRY) + { + TuningTableIndex = LOWERBOUND_TX_POWER_TUNING_ENTRY; + } + + if (TuningTableIndex >= UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd)) + { + TuningTableIndex = UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd); + } + + /* Valid pAd->TxPowerCtrl.idxTxPowerTable: -30 ~ 61 */ + pTxPowerTuningEntry = &TxPowerTuningTable[TuningTableIndex + TX_POWER_TUNING_ENTRY_OFFSET]; + pAd->TxPowerCtrl.RF_TX_ALC = pTxPowerTuningEntry->RF_TX_ALC; + pAd->TxPowerCtrl.MAC_PowerDelta = pTxPowerTuningEntry->MAC_PowerDelta; + + /* Tx power adjustment over RF */ + RFValue = pAd->TxPowerCtrl.RF_TX_ALC; + RT30xxWriteRFRegister(pAd, RF_R47, (UCHAR)RFValue); /* TX0_ALC */ + DBGPRINT(RT_DEBUG_TRACE, ("RF_R47 = 0x%X ", RFValue)); + + /* Delta Power between Tx0 and Tx1 */ + DeltaPwr = pAd->TxPower[pAd->CommonCfg.Channel].Power - pAd->TxPower[pAd->CommonCfg.Channel].Power2; + + if ((TuningTableIndex - DeltaPwr) < LOWERBOUND_TX_POWER_TUNING_ENTRY) + { + pTxPowerTuningEntry = &TxPowerTuningTable[LOWERBOUND_TX_POWER_TUNING_ENTRY + TX_POWER_TUNING_ENTRY_OFFSET]; + } + else if ((TuningTableIndex - DeltaPwr) >= UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd)) + { + pTxPowerTuningEntry = &TxPowerTuningTable[UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd) + TX_POWER_TUNING_ENTRY_OFFSET]; + } + else + { + pTxPowerTuningEntry -= DeltaPwr; + } + + RFValue = pTxPowerTuningEntry->RF_TX_ALC; + RT30xxWriteRFRegister(pAd, RF_R48, (UCHAR)RFValue); /* TX1_ALC */ + DBGPRINT(RT_DEBUG_TRACE, ("RF_R48 = 0x%X\n", RFValue)); + + /* Tx power adjustment over MAC */ + TotalDeltaPower = pAd->TxPowerCtrl.MAC_PowerDelta; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: desiredTSSI = %d, currentTSSI = %d, TuningTableIndex = %d, {RF_TX_ALC = %d, MAC_PowerDelta = %d}\n", + __FUNCTION__, + desiredTssi, + currentTssi, + TuningTableIndex, + pTxPowerTuningEntry->RF_TX_ALC, + pTxPowerTuningEntry->MAC_PowerDelta)); + } + else + { + /* Tx power adjustment over RF */ + RFValue = pAd->TxPowerCtrl.RF_TX_ALC; + RT30xxWriteRFRegister(pAd, RF_R47, (UCHAR)RFValue); /* TX0_ALC */ + DBGPRINT(RT_DEBUG_TRACE, ("RF_R47 = 0x%X ", RFValue)); + + /* Delta Power between Tx0 and Tx1 */ + DeltaPwr = pAd->TxPower[pAd->CommonCfg.Channel].Power - pAd->TxPower[pAd->CommonCfg.Channel].Power2; + + if ((pAd->TxPowerCtrl.idxTxPowerTable - DeltaPwr) < LOWERBOUND_TX_POWER_TUNING_ENTRY) + { + pTxPowerTuningEntry = &TxPowerTuningTable[LOWERBOUND_TX_POWER_TUNING_ENTRY + TX_POWER_TUNING_ENTRY_OFFSET]; + } + else if ((pAd->TxPowerCtrl.idxTxPowerTable - DeltaPwr) >= UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd)) + { + pTxPowerTuningEntry = &TxPowerTuningTable[UPPERBOUND_TX_POWER_TUNING_ENTRY(pAd) + TX_POWER_TUNING_ENTRY_OFFSET]; + } + else + { + pTxPowerTuningEntry -= DeltaPwr; + } + + RFValue = pTxPowerTuningEntry->RF_TX_ALC; + RT30xxWriteRFRegister(pAd, RF_R48, (UCHAR)RFValue); /* TX1_ALC */ + DBGPRINT(RT_DEBUG_TRACE, ("RF_R48 = 0x%X\n", RFValue)); + + /* Tx power adjustment over MAC */ + TotalDeltaPower = pAd->TxPowerCtrl.MAC_PowerDelta; + } + } + +LabelFail: + + *pTotalDeltaPwr = TotalDeltaPower; +} +#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; + + /* 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; + + if ((value2 & 0xff) != 0xff) + { + if ((value2 & 0x80)) + Gpwrdelta = (value2&0xf); + + if ((value2 & 0x40)) + bGpwrdeltaMinus = FALSE; + else + bGpwrdeltaMinus = TRUE; + } + + 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 (bGpwrdeltaMinus == FALSE) + { + t1 = value_1+(Gpwrdelta); + if (t1 > 0x3f) + t1 = 0x3f; + + t3 = value_3+(Gpwrdelta); + if (t3 > 0x3f) + t3 = 0x3f; + } + else + { + if (value_1 > Gpwrdelta) + t1 = value_1-(Gpwrdelta); + else + t1 = 0; + + if (value_3 > Gpwrdelta) + t3 = value_3-(Gpwrdelta); + else + t3 = 0; + } + 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 (bGpwrdeltaMinus == FALSE) + { + t1 = value_1+(Gpwrdelta); + if (t1 > 0x3f) + t1 = 0x3f; + + t3 = value_3+(Gpwrdelta); + if (t3 > 0x3f) + t3 = 0x3f; + } + else + { + if (value_1 > Gpwrdelta) + t1 = value_1-(Gpwrdelta); + else + t1 = 0; + + if (value_3 > Gpwrdelta) + t3 = value_3-(Gpwrdelta); + else + t3 = 0; + } + 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)); + } +} + +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)); +} + + +/* +======================================================================== +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; + + /* init capability */ + pChipCap->MaxNumOfRfId = 64; + pChipCap->MaxNumOfBbpId = 255; + pChipCap->bbpRegTbSize = 0; + pChipCap->SnrFormula = SNR_FORMULA2; + pChipCap->RfReg17WtMethod = RF_REG_WT_METHOD_NONE; + pChipOps->AsicGetTxPowerOffset = AsicGetTxPowerOffset; + pChipOps->AsicExtraPowerOverMAC = RT6352_AsicExtraPowerOverMAC, + +#ifdef RTMP_INTERNAL_TX_ALC + pChipCap->TxAlcTxPowerUpperBound_2G = 61; + pChipCap->TxPowerTuningTable_2G = RT6352_TxPowerTuningTable; + pChipOps->InitDesiredTSSITable = RT6352_InitDesiredTSSITable; + pChipOps->AsicTxAlcGetAutoAgcOffset = RT6352_AsicTxAlcGetAutoAgcOffset; +#endif /* RTMP_INTERNAL_TX_ALC */ + + pChipCap->FlgIsHwWapiSup = TRUE; + + pChipCap->FlgIsVcoReCalMode = VCO_CAL_MODE_3; + pChipCap->TXWISize = 20; + pChipCap->RXWISize = 24; + pChipCap->WPDMABurstSIZE = 2; + pChipCap->DPDCalPassThres = 5; +#ifdef RTMP_FLASH_SUPPORT + pChipCap->eebuf = 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 HW_TX_RATE_LOOKUP_SUPPORT + pChipCap->bFlgHwTxLuCap = TRUE; +#endif /* HW_TX_RATE_LOOKUP_SUPPORT */ + +#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; + pChipOps->ChipAGCInit = RT6352_RTMPSetAGCInitValue; +#ifdef CARRIER_DETECTION_SUPPORT + pAd->chipCap.carrier_func = TONE_RADAR_V2; + pChipOps->ToneRadarProgram = ToneRadarProgram_v2; +#endif /* CARRIER_DETECTION_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/mt7620/src/chips/rtmp_chip.c b/mt7620/src/chips/rtmp_chip.c new file mode 100644 index 0000000..db791c1 --- /dev/null +++ b/mt7620/src/chips/rtmp_chip.c @@ -0,0 +1,2025 @@ +/* + *************************************************************************** + * 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" + + + +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; + +#ifndef RT2880 +#if defined(RT28xx) || defined(RT2883) +/* Reset the RFIC setting to new series */ +RTMP_RF_REGS RF2850RegTable[] = { +/* ch R1 R2 R3(TX0~4=0) R4*/ + {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b}, + {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f}, + {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b}, + {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f}, + {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b}, + {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f}, + {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b}, + {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f}, + {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b}, + {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f}, + {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b}, + {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f}, + {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b}, + {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193}, + + /* 802.11 UNI / HyperLan 2*/ + {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3}, + {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193}, + {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183}, + {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3}, + {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b}, + {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b}, + {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193}, + {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3}, + {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b}, + {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183}, + {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193}, + {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, /* Plugfest#4, Day4, change RFR3 left4th 9->5.*/ + + /* 802.11 HyperLan 2*/ + {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783}, + + /* 2008.04.30 modified */ + /* The system team has AN to improve the EVM value */ + /* for channel 102 to 108 for the RT2850/RT2750 dual band solution.*/ + {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793}, + {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3}, + {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193}, + + {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183}, + {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b}, + {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3}, + {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193}, + {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183}, + {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193}, + {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, /* 0x980ed1bb->0x980ed15b required by Rory 20070927*/ + {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3}, + {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b}, + {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193}, + {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b}, + {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183}, + + /* 802.11 UNII*/ + {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7}, + {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187}, + {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f}, + {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f}, + {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7}, + {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187}, + {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197}, + {167, 0x98402ec4, 0x984c03d2, 0x98179855, 0x9815531f}, + {169, 0x98402ec4, 0x984c03d2, 0x98179855, 0x98155327}, + {171, 0x98402ec4, 0x984c03d6, 0x98179855, 0x98155307}, + {173, 0x98402ec4, 0x984c03d6, 0x98179855, 0x9815530f}, + + /* Japan*/ + {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b}, + {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13}, + {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b}, + {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23}, + {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13}, + {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b}, + {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23}, + + /* still lack of MMAC(Japan) ch 34,38,42,46*/ +}; +UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS)); +#endif /* defined(RT28xx) || defined(RT2883) */ +#endif /* !RT2880 */ + +#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 */ + +/* private function prototype */ + +static VOID RxSensitivityTuning( + IN PRTMP_ADAPTER pAd); + +#ifdef CONFIG_STA_SUPPORT +static UCHAR ChipAGCAdjust( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi, + IN UCHAR OrigR66Value); +#endif /* CONFIG_STA_SUPPORT */ + +static VOID ChipBBPAdjust( + IN RTMP_ADAPTER *pAd); + +static VOID ChipSwitchChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel, + IN BOOLEAN bScan); + +static VOID Default_ChipAGCInit( + IN PRTMP_ADAPTER pAd, + IN UCHAR BandWidth); + +static VOID AsicAntennaDefaultReset( + IN PRTMP_ADAPTER pAd, + IN EEPROM_ANTENNA_STRUC *pAntenna); + + +/* +======================================================================== +Routine Description: + Initialize specific beacon frame architecture. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpChipBcnSpecInit( + IN 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; + + DBGPRINT(RT_DEBUG_TRACE, ("< Beacon Spec Information: >\n")); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnMaxHwNum = \t%d\n", pChipCap->BcnMaxHwNum)); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnMaxNum = \t%d\n", pChipCap->BcnMaxNum)); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnMaxHwSize = \t0x%x\n", pChipCap->BcnMaxHwSize)); + DBGPRINT(RT_DEBUG_TRACE, ("\tWcidHwRsvNum = \t%d\n", pChipCap->WcidHwRsvNum)); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnBase[0] = \t0x%x\n", pChipCap->BcnBase[0])); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnBase[8] = \t0x%x\n", pChipCap->BcnBase[8])); +#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; + + DBGPRINT(RT_DEBUG_TRACE, ("< Beacon Information: >\n")); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnMaxHwNum = \t%d\n", pChipCap->BcnMaxHwNum)); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnMaxNum = \t%d\n", pChipCap->BcnMaxNum)); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnMaxHwSize = \t0x%x\n", pChipCap->BcnMaxHwSize)); + DBGPRINT(RT_DEBUG_TRACE, ("\tWcidHwRsvNum = \t%d\n", pChipCap->WcidHwRsvNum)); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnBase[0] = \t0x%x\n", pChipCap->BcnBase[0])); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnBase[1] = \t0x%x\n", pChipCap->BcnBase[1])); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnBase[2] = \t0x%x\n", pChipCap->BcnBase[2])); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnBase[3] = \t0x%x\n", pChipCap->BcnBase[3])); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnBase[4] = \t0x%x\n", pChipCap->BcnBase[4])); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnBase[5] = \t0x%x\n", pChipCap->BcnBase[5])); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnBase[6] = \t0x%x\n", pChipCap->BcnBase[6])); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnBase[7] = \t0x%x\n", pChipCap->BcnBase[7])); +} + +/* +======================================================================== +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 chip related information. + +Arguments: + pCB - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpChipOpsHook( + IN VOID *pCB) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pCB; + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + UINT32 MacValue; + UCHAR i = 0; + + + /* sanity check */ + do + { + RTMP_IO_READ32(pAd, MAC_CSR0, &MacValue); + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + if ((MacValue != 0x00) && (MacValue != 0xFFFFFFFF)) + break; + + RTMPusecDelay(10); + } while (i++ < 100); + + pAd->MACVersion = MacValue; + + /* default init */ + RTMP_DRS_ALG_INIT(pAd, RATE_ALG_LEGACY); + +#ifdef RTMP_RBUS_SUPPORT + if (pAd->infType == RTMP_DEV_INF_RBUS) + { +#ifdef RT2880 + RTMP_SYS_IO_READ32(0xa030000c, &pAd->CommonCfg.CID); +#else + RTMP_SYS_IO_READ32(0xb000000c, &pAd->CommonCfg.CID); + RTMP_SYS_IO_READ32(0xb0000000, &pAd->CommonCfg.CN); +#endif /* RT2880 */ + +#ifdef RT6352 + 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 */ + +#ifdef GREENAP_SUPPORT + pChipOps->EnableAPMIMOPS = EnableAPMIMOPSv1; + pChipOps->DisableAPMIMOPS = DisableAPMIMOPSv1; +#endif /* GREENAP_SUPPORT */ + +#ifdef RT3883 + if (IS_RT3883(pAd)) + { + RT3883_Init(pAd); + goto done; + } +#endif /* RT3883 */ + + + /* 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; + + DBGPRINT(RT_DEBUG_TRACE, ("Efuse Size=0x%x [%x-%x] \n",pAd->chipCap.EFUSE_USAGE_MAP_SIZE,pAd->chipCap.EFUSE_USAGE_MAP_START,pAd->chipCap.EFUSE_USAGE_MAP_END)); +#endif /* RTMP_EFUSE_SUPPORT */ + + pChipCap->VcoPeriod = 10; + pChipCap->FlgIsVcoReCalMode = VCO_CAL_DISABLE; + pChipCap->WPDMABurstSIZE = 2; /* default 64B */ + pChipCap->MBSSIDMode = MBSSID_MODE0; + + + RtmpChipBcnInit(pAd); + + pChipOps->RxSensitivityTuning = RxSensitivityTuning; +#ifdef CONFIG_STA_SUPPORT + pChipOps->ChipAGCAdjust = ChipAGCAdjust; +#endif /* CONFIG_STA_SUPPORT */ + pChipOps->ChipBBPAdjust = ChipBBPAdjust; + pChipOps->ChipSwitchChannel = ChipSwitchChannel; + + /* TX ALC */ + pChipCap->bTempCompTxALC = FALSE; + pChipOps->AsicGetTxPowerOffset = NULL; + pChipOps->InitDesiredTSSITable = NULL; + pChipOps->AsicTxAlcGetAutoAgcOffset = NULL; + pChipOps->AsicExtraPowerOverMAC = NULL; + pChipOps->AsicAdjustTxPower = NULL; + + 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; + + +#ifdef RT28xx + pChipOps->ChipSwitchChannel = RT28xx_ChipSwitchChannel; +#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; + + + /* We depends on RfICType and MACVersion to assign the corresponding operation callbacks. */ +#ifdef RT2880 + if (IS_RT2880(pAd)) + RT2880_Init(pAd); +#endif /* RT2880 */ + +#ifdef RT305x +#ifdef RT3352 + /*FIXME by Steven: RFIC=RFIC_3022 in some RT3352 board*/ +/* if (pAd->RfIcType == RFIC_3322) {*/ + if (IS_RT3352(pAd)) + { + RT3352_Init(pAd); + } + else +#endif /* RT3352 */ +#ifdef RT5350 + if (IS_RT5350(pAd)) + { + RT5350_Init(pAd); + } + else +#endif /* RT5350 */ +/* comment : the RfIcType is not ready yet, because EEPROM doesn't be initialized. */ +/* if ((pAd->MACVersion == 0x28720200) && + ((pAd->RfIcType == RFIC_3320) || (pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3022))) */ + if (IS_RT3050_3052_3350(pAd)) + { + RT305x_Init(pAd); + } + else +#endif /* RT305x */ +#ifdef RT2883 + if (IS_RT2883(pAd) && (pAd->infType == RTMP_DEV_INF_RBUS)) + { + pChipOps->AsicBbpInit = NICInitRT2883BbpRegisters; + pChipCap->SnrFormula = SNR_FORMULA2; + pChipCap->MaxNumOfBbpId = 180; + pChipCap->TXWISize = 16; + pChipCap->RXWISize = 20; + pChipOps->AsicMacInit = NICInitRT2883MacRegisters; + } + else +#endif /* RT2883 */ + + +#ifdef RT6352 + if (IS_RT6352(pAd)) + RT6352_Init(pAd); +#endif /* RT6352 */ + +#if defined(RT3883) || defined(RT3290) +done: +#endif /* defined(RT3883) || defined(RT3290) */ + DBGPRINT(RT_DEBUG_TRACE, ("Chip specific bbpRegTbSize=%d!\n", pChipCap->bbpRegTbSize)); + DBGPRINT(RT_DEBUG_TRACE, ("Chip VCO calibration mode = %d!\n", pChipCap->FlgIsVcoReCalMode)); +} + + + +#ifdef GREENAP_SUPPORT +#ifdef RT305x +extern REG_PAIR RT305x_RFRegTable[]; +#endif /* RT305x */ +VOID EnableAPMIMOPSv2( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN ReduceCorePower) +{ + UCHAR BBPR3 = 0, BBPR95 = 0; + UINT32 macdata = 0; + + /* enable MMPS BBP control register*/ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); + BBPR3 |= 0x04; /*bit 2*/ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); + + if (IS_RT6352(pAd)) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R95, &BBPR95); + BBPR95 &= ~(0x80); /* bit 7 */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R95, BBPR95); + } + + /* enable MMPS MAC control register*/ + RTMP_IO_READ32(pAd, 0x1210, &macdata); + macdata |= 0x09; /*bit 0, 3*/ + RTMP_IO_WRITE32(pAd, 0x1210, macdata); + + /* swith to one-PAPE mode */ + RTMP_IO_READ32(pAd, TXOP_HLDR_ET, &macdata); + macdata = (macdata & (~0x18)) | 0x8; + RTMP_IO_WRITE32(pAd, TXOP_HLDR_ET, macdata); + + DBGPRINT(RT_DEBUG_INFO, ("EnableAPMIMOPSNew, 30xx changes the # of antenna to 1\n")); +} + +VOID DisableAPMIMOPSv2( + IN PRTMP_ADAPTER pAd) +{ + UCHAR BBPR3 = 0, BBPR95 = 0; + UINT32 macdata = 0; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); + BBPR3 &= ~(0x04); /*bit 2*/ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); + + if (IS_RT6352(pAd)) + { + if (pAd->Antenna.field.RxPath > 1) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R95, &BBPR95); + BBPR95 |= 0x80; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R95, BBPR95); + } + } + + /* enable MMPS MAC control register*/ + RTMP_IO_READ32(pAd, 0x1210, &macdata); + macdata &= ~(0x09); /*bit 0, 3*/ + RTMP_IO_WRITE32(pAd, 0x1210, macdata); + + /* disable one-PAPE mode */ + RTMP_IO_READ32(pAd, TXOP_HLDR_ET, &macdata); + macdata &= ~(0x18); + RTMP_IO_WRITE32(pAd, TXOP_HLDR_ET, macdata); + + DBGPRINT(RT_DEBUG_INFO, ("DisableAPMIMOPSNew, 30xx reserve only one antenna\n")); +} + +VOID EnableAPMIMOPSv1( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN ReduceCorePower) +{ + UCHAR BBPR3 = 0,BBPR1 = 0; + ULONG TxPinCfg = 0x00050F0A;/*Gary 2007/08/09 0x050A0A*/ + UCHAR BBPR4=0; + + UCHAR CentralChannel; + /*UINT32 Value=0;*/ + + +#ifdef RT305x + UCHAR RFValue=0; + + RT30xxReadRFRegister(pAd, RF_R01, &RFValue); + RFValue &= 0x03; //clear bit[7~2] + RFValue |= 0x3C; // default 2Tx 2Rx + // turn off tx1 + RFValue &= ~(0x1 << 5); + // turn off rx1 + RFValue &= ~(0x1 << 4); + // Turn off unused PA or LNA when only 1T or 1R +#endif /* RT305x */ + + 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 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPR4); + BBPR4 &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPR4); + /* RF Bandwidth related registers would be set in AsicSwitchChannel() */ + pAd->CommonCfg.BBPCurrentBW = BW_20; + if (pAd->Antenna.field.RxPath>1||pAd->Antenna.field.TxPath>1) + { + /*TX Stream*/ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1); + /*Rx Stream*/ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); + + + BBPR3 &= (~0x18); + BBPR1 &= (~0x18); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + +#ifdef RT305x + RT30xxWriteRFRegister(pAd, RF_R01, RFValue); +#endif /* RT305x */ + } + AsicSwitchChannel(pAd, CentralChannel, FALSE); + + DBGPRINT(RT_DEBUG_INFO, ("EnableAPMIMOPS, 305x/28xx changes the # of antenna to 1\n")); +} + + +VOID DisableAPMIMOPSv1( + IN PRTMP_ADAPTER pAd) +{ + UCHAR BBPR3=0,BBPR1=0; + ULONG TxPinCfg = 0x00050F0A;/*Gary 2007/08/09 0x050A0A*/ + + UCHAR CentralChannel; + UINT32 Value=0; + + +#ifdef RT305x + UCHAR RFValue=0; + + RT30xxReadRFRegister(pAd, RF_R01, &RFValue); + RFValue &= 0x03; //clear bit[7~2] + RFValue |= 0x3C; // default 2Tx 2Rx +#endif /* RT305x */ + + 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)) + { + 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; + + /* 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, &Value); + Value &= (~0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); + } + else if ((pAd->CommonCfg.Channel > 2) && (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_BELOW)) + { + 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, &Value); + Value |= (0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); + } + CentralChannel = pAd->CommonCfg.CentralChannel; + + /* Set BBP registers to BW40 */ + 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); + /* RF Bandwidth related registers would be set in AsicSwitchChannel() */ + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, CentralChannel, FALSE); + } + /*Rx Stream*/ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1); + /*Tx Stream*/ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); + BBPR3 &= (~0x18); + + /*RX Stream*/ + if(pAd->Antenna.field.RxPath == 3) + { + BBPR3 |= (0x10); + } + else if(pAd->Antenna.field.RxPath == 2) + { + BBPR3 |= (0x8); + } + else if(pAd->Antenna.field.RxPath == 1) + { + BBPR3 |= (0x0); + } + + /*Tx Stream*/ + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->Antenna.field.TxPath == 2)) + { + BBPR1 &= (~0x18); + BBPR1 |= 0x10; + } + else + { + BBPR1 &= (~0x18); + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1); + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + +#ifdef RT305x + RT30xxWriteRFRegister(pAd, RF_R01, RFValue); +#endif /* RT305x */ + + DBGPRINT(RT_DEBUG_INFO, ("DisableAPMIMOPS, 305x/28xx reserve only one antenna\n")); +} +#endif /* GREENAP_SUPPORT */ + + +static VOID RxSensitivityTuning( + IN PRTMP_ADAPTER pAd) +{ + UCHAR R66; + + + R66 = 0x26 + GET_LNA_GAIN(pAd); +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { +#ifdef RT2883 + if (IS_RT2883(pAd)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, 0x0); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, 0x20); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, 0x40); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); + } + else +#endif /* RT2883*/ +#ifdef RT3352 + if (IS_RT3352(pAd)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, 0x0); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, 0x20); + } + else +#endif /* RT3352 */ + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); + } + else +#endif /* RALINK_ATE */ + { + AsicBBPWriteWithRxChain(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)), 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) + AsicBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + + return R66; +} +#endif /* CONFIG_STA_SUPPORT */ + + +static VOID 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.AddHTInfo.AddHtInfo.ExtChanOffset == 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); + + if (pAd->CommonCfg.Channel > 14) + { /* request by Gary 20070208 for middle and long range A Band*/ + AsicBBPWriteWithRxChain(pAd, BBP_R66, 0x48, RX_CHAIN_ALL); + } + else + { /* request by Gary 20070208 for middle and long range G Band*/ + AsicBBPWriteWithRxChain(pAd, BBP_R66, 0x38, RX_CHAIN_ALL); + } + /* */ + 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); + } + 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, ("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.AddHTInfo.AddHtInfo.ExtChanOffset == 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); + + if (pAd->CommonCfg.Channel > 14) + { /* request by Gary 20070208 for middle and long range A Band*/ + AsicBBPWriteWithRxChain(pAd, BBP_R66, 0x48, RX_CHAIN_ALL); + } + else + { /* request by Gary 20070208 for middle and long range G band*/ + AsicBBPWriteWithRxChain(pAd, BBP_R66, 0x38, RX_CHAIN_ALL); + } + + + 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); + } + 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, ("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); + + /* 20 MHz bandwidth*/ + if (pAd->CommonCfg.Channel > 14) + { /* request by Gary 20070208*/ + AsicBBPWriteWithRxChain(pAd, BBP_R66, 0x40, RX_CHAIN_ALL); + } + else + { /* request by Gary 20070208*/ + /*AsicBBPWriteWithRxChain(pAd, BBP_R66, 0x30, RX_CHAIN_ALL); */ + /* request by Brian 20070306*/ + AsicBBPWriteWithRxChain(pAd, BBP_R66, 0x38, RX_CHAIN_ALL); + } + + 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); + } + 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); + } + +#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 */ + } + + if (pAd->CommonCfg.Channel > 14) + { /* request by Gary 20070208 for middle and long range A Band*/ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, 0x1D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, 0x1D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, 0x1D); + /*RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x1D);*/ + } + else + { /* request by Gary 20070208 for middle and long range G band*/ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, 0x2D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, 0x2D); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, 0x2D); + /*RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x2D);*/ + } +} + + +static VOID 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*/ + + /* + 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, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel)); + } + + { +#if defined(RT28xx) + ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0; + RTMP_RF_REGS *RFRegTable; + + RFRegTable = RF2850RegTable; +#endif /* Rdefined(RT28xx) */ + + switch (pAd->RfIcType) + { +#if defined(RT28xx) +#if defined(RT28xx) + case RFIC_2820: + case RFIC_2850: + case RFIC_2720: + case RFIC_2750: +#endif /* defined(RT28xx) */ + for (index = 0; index < NUM_OF_2850_CHNL; index++) + { + if (Channel == RFRegTable[index].Channel) + { + R2 = RFRegTable[index].R2; + if (pAd->Antenna.field.TxPath == 1) + { + R2 |= 0x4000; /* If TXpath is 1, bit 14 = 1;*/ + } + + if (pAd->Antenna.field.RxPath == 2 +#ifdef GREENAP_SUPPORT + && (pAd->ApCfg.bGreenAPActive == FALSE) +#endif /* GREENAP_SUPPORT */ +) + { + R2 |= 0x40; /* write 1 to off Rxpath.*/ + } + else if (pAd->Antenna.field.RxPath == 1 +#ifdef GREENAP_SUPPORT + || (pAd->ApCfg.bGreenAPActive == TRUE) +#endif /* GREENAP_SUPPORT */ +) + { + R2 |= 0x20040; /* write 1 to off RxPath*/ + } + + if (Channel > 14) + { + /* initialize R3, R4*/ + R3 = (RFRegTable[index].R3 & 0xffffc1ff); + R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15); + + /* 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB*/ + /* R3*/ + if ((TxPwer >= -7) && (TxPwer < 0)) + { + TxPwer = (7+TxPwer); + + /* TxPwer is not possible larger than 15 */ +/* TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);*/ + + R3 |= (TxPwer << 10); + DBGPRINT(RT_DEBUG_TRACE, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer)); + } + else + { + TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); + R3 |= (TxPwer << 10) | (1 << 9); + } + + /* R4*/ + if ((TxPwer2 >= -7) && (TxPwer2 < 0)) + { + TxPwer2 = (7+TxPwer2); + R4 |= (TxPwer2 << 7); + DBGPRINT(RT_DEBUG_TRACE, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2)); + } + else + { + TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); + R4 |= (TxPwer2 << 7) | (1 << 6); + } + } + else + { + R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); /* set TX power0*/ + R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);/* Set freq Offset & TxPwr1*/ + } + + /* Based on BBP current mode before changing RF channel.*/ + if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40) +#ifdef GREENAP_SUPPORT + && (pAd->ApCfg.bGreenAPActive == 0) +#endif /* GREENAP_SUPPORT */ + ) + { + R4 |=0x200000; + } + + /* Update variables*/ + pAd->LatchRfRegs.Channel = Channel; + pAd->LatchRfRegs.R1 = RFRegTable[index].R1; + pAd->LatchRfRegs.R2 = R2; + pAd->LatchRfRegs.R3 = R3; + pAd->LatchRfRegs.R4 = R4; + + /* Set RF value 1's set R3[bit2] = [0]*/ + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + RTMPusecDelay(200); + + /* Set RF value 2's set R3[bit2] = [1]*/ + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04)); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + RTMPusecDelay(200); + + /* Set RF value 3's set R3[bit2] = [0]*/ + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + break; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%lu, Pwr1=%lu, %dT) to , R1=0x%08x, R2=0x%08x, R3=0x%08x, R4=0x%08x\n", + Channel, + pAd->RfIcType, + (R3 & 0x00003e00) >> 9, + (R4 & 0x000007c0) >> 6, + pAd->Antenna.field.TxPath, + pAd->LatchRfRegs.R1, + pAd->LatchRfRegs.R2, + pAd->LatchRfRegs.R3, + pAd->LatchRfRegs.R4)); + + break; +#endif /* defined(RT28xx) */ + default: + DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d : unknown RFIC=%d\n", + Channel, pAd->RfIcType)); + break; + } + } + + /* Change BBP setting during siwtch from a->g, g->a*/ + if (Channel <= 14) + { + ULONG TxPinCfg = 0x00050F0A;/*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))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);/*(0x44 - GET_LNA_GAIN(pAd))); According the Rory's suggestion to solve the middle range issue.*/ + + /* Rx High power VGA offset for LNA select*/ + { + if (pAd->NicConfig2.field.ExternalLNAForG) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + } + + /* 5G band selection PIN, bit1 and bit2 are complement*/ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x04); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + { + /* 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); + } + else + { + ULONG TxPinCfg = 0x00050F05;/*Gary 2007/8/9 0x050505*/ + UINT8 bbpValue; + + 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))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);/*(0x44 - GET_LNA_GAIN(pAd))); According the Rory's suggestion to solve the middle range issue. */ + + /* Set the BBP_R82 value here */ + bbpValue = 0xF2; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, bbpValue); + + + /* Rx High power VGA offset for LNA select*/ + if (pAd->NicConfig2.field.ExternalLNAForA) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + /* 5G band selection PIN, bit1 and bit2 are complement*/ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x02); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + /* Turn off unused PA or LNA when only 1T or 1R*/ + { + /* 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); + } + + /* R66 should be set according to Channel and use 20MHz when scanning*/ + /* AsicBBPWriteWithRxChain(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)), 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 Default_ChipAGCInit( + IN PRTMP_ADAPTER pAd, + IN UCHAR BandWidth) +{ + UCHAR R66 = 0x30; +#ifdef RT2883 + UCHAR byteValue = 0; +#endif // RT2883 // + + if (pAd->LatchRfRegs.Channel <= 14) + { // BG band + { + R66 = 0x2E + GET_LNA_GAIN(pAd); +#if defined(RT3352) + if (IS_RT3352(pAd)) + { + /* Gary 20100714: Update BBP R66 programming: */ + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + R66 = (GET_LNA_GAIN(pAd)*2+0x1C); + else + R66 = (GET_LNA_GAIN(pAd)*2+0x24); + } +#endif // defined(RT3352) // + } + } + else + { //A band + { + if (BandWidth == BW_20) + R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3); +#ifdef DOT11_N_SUPPORT + else + R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3); +#endif // DOT11_N_SUPPORT // + } + } + AsicBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); + +} + + +#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 // + +static VOID AsicAntennaDefaultReset( + IN PRTMP_ADAPTER pAd, + IN EEPROM_ANTENNA_STRUC *pAntenna) +{ +#if defined(RT2883) || defined(RT3593) + if (IS_RT2883(pAd)) + { + pAntenna->word = 0; +#ifdef RT2883 + if (IS_RT2883(pAd)) + pAntenna->field.RfIcType = RFIC_2853; +#endif /* RT2883 */ + pAntenna->field.TxPath = 3; + pAntenna->field.RxPath = 3; + } + else +#endif /* defined(RT2883) || defined(RT3593) */ +#ifdef RT5350 + if (IS_RT5350(pAd)) + { + pAntenna->word = 0; + pAntenna->field.RfIcType = RFIC_3320; + pAntenna->field.TxPath = 1; + pAntenna->field.RxPath = 1; + } + else +#endif /* RT5350 */ + { + + 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 */ +} + + +/* + ======================================================================== + + Routine Description: + Read initial channel power parameters from EEPROM + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPReadChannelPwr( + IN PRTMP_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++) + { + + { /* Default routine. RT3070 and RT3370 run here. */ + UCHAR max_pwr = 31; + +#ifdef RT6352 + if (IS_RT6352(pAd)) + max_pwr = 47; +#endif /* RT6352 */ + + 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 > max_pwr) || (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 > max_pwr) || (Power.field.Byte1 < 0)) + pAd->TxPower[i * 2 + 1].Power = DEFAULT_RF_TX_POWER; + } + + if ((Power2.field.Byte0 > max_pwr) || (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 > max_pwr) || (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; + + +} + + +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 & 0xf0000000) < 0x28830000) || + (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; +} + + +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) < 0x28830000) || + (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; +} + + + + + +INT WaitForAsicReady( + IN 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; + + RTMPusecDelay(10); + } while (idx++ < 100); + + DBGPRINT(RT_DEBUG_ERROR, + ("%s(0x%x):AsicNotReady!\n", + __FUNCTION__, mac_val)); + + return TRUE; +} + + +INT AsicGetMacVersion( + IN RTMP_ADAPTER *pAd) +{ + UINT32 reg = MAC_CSR0; + + + if (WaitForAsicReady(pAd) == TRUE) + { + RTMP_IO_READ32(pAd, reg, &pAd->MACVersion); + DBGPRINT(RT_DEBUG_OFF, ("MACVersion[Ver:Rev]=0x%08x\n", + pAd->MACVersion)); + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s() failed!\n", __FUNCTION__)); + return FALSE; + } +} + +/* End of rtmp_chip.c */ + diff --git a/mt7620/src/common/action.c b/mt7620/src/common/action.c new file mode 100644 index 0000000..294652e --- /dev/null +++ b/mt7620/src/common/action.c @@ -0,0 +1,1867 @@ +/**************************************************************************** + * 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 // + +#ifdef P2P_SUPPORT +/* Group Formation Action */ + +extern VOID P2pPeerGoNegoReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +extern VOID P2pPeerGoNegoRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +extern VOID P2pPeerGoNegoConfirmAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +extern VOID P2pPeerProvisionReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +extern VOID P2pPeerProvisionRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +extern VOID P2pPeerDeviceDiscRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +extern VOID P2pPeerInvitesReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +extern VOID P2pPeerInvitesRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +extern VOID P2pPeerDevDiscoverReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif /* P2P_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 PRTMP_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); + 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 +#endif /* CONFIG_AP_SUPPORT */ + + + +} + +#ifdef DOT11_N_SUPPORT +VOID MlmeADDBAAction( + IN PRTMP_ADAPTER pAd, + IN 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; +#ifdef CONFIG_AP_SUPPORT + UCHAR apidx; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef P2P_SUPPORT + MAC_TABLE_ENTRY *pEntry = NULL; +#endif /* P2P_SUPPORT */ + + 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 */ + Idx = pAd->MacTab.Content[pInfo->Wcid].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 P2P_SUPPORT + /*if (VALID_WCID(pInfo->Wcid))*/ + { + pEntry = &pAd->MacTab.Content[pInfo->Wcid]; + + if (pEntry) + { +#ifdef CONFIG_STA_SUPPORT + if (ADHOC_ON(pAd) +#ifdef QOS_DLS_SUPPORT + || (IS_ENTRY_DLS(&pAd->MacTab.Content[pInfo->Wcid])) +#endif /* QOS_DLS_SUPPORT */ +#ifdef DOT11Z_TDLS_SUPPORT + || (IS_ENTRY_TDLS(&pAd->MacTab.Content[pInfo->Wcid])) +#endif /* DOT11Z_TDLS_SUPPORT */ + ) + { + ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + } + else +#endif /* CONFIG_STA_SUPPORT */ + { + ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pEntry->HdrAddr2, pEntry->HdrAddr3); + } + } + } +#else +#ifdef MESH_SUPPORT + if (IS_ENTRY_MESH(&pAd->MacTab.Content[pInfo->Wcid])) + { + ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->MeshTab.CurrentAddress, pInfo->pAddr); + } + else +#endif /* MESH_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(&pAd->MacTab.Content[pInfo->Wcid])) + { +#ifdef MAC_REPEATER_SUPPORT + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[pInfo->Wcid]; +#endif /* MAC_REPEATER_SUPPORT */ + + apidx = pAd->MacTab.Content[pInfo->Wcid].MatchAPCLITabIdx; +#ifdef MAC_REPEATER_SUPPORT + if (pEntry && pEntry->bReptCli) + ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->ApCfg.ApCliTab[apidx].RepeaterCli[pEntry->MatchReptCliIdx].CurrentAddress, pInfo->pAddr); + else +#endif /* MAC_REPEATER_SUPPORT */ + ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress, pInfo->pAddr); + } + else +#endif /* APCLI_SUPPORT */ + { + apidx = pAd->MacTab.Content[pInfo->Wcid].apidx; + ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].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(&pAd->MacTab.Content[pInfo->Wcid])) +#endif /* QOS_DLS_SUPPORT */ +#ifdef DOT11Z_TDLS_SUPPORT + || (IS_ENTRY_TDLS(&pAd->MacTab.Content[pInfo->Wcid])) +#endif /* DOT11Z_TDLS_SUPPORT */ + ) + ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + else + ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pInfo->pAddr); + } +#endif /* CONFIG_STA_SUPPORT */ +#endif /* P2P_SUPPORT */ + + Frame.Category = CATEGORY_BA; + Frame.Action = ADDBA_REQ; + Frame.BaParm.AMSDUSupported = 0; + 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 = pAd->MacTab.Content[pInfo->Wcid].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 | MapUserPriorityToAccessCategory[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( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MLME_DELBA_REQ_STRUCT *pInfo; + PUCHAR pOutBuffer = NULL; + PUCHAR pOutBuffer2 = NULL; + NDIS_STATUS NStatus; + ULONG Idx; + FRAME_DELBA_REQ Frame; + ULONG FrameLen; + FRAME_BAR FrameBar; +#ifdef CONFIG_AP_SUPPORT + UCHAR apidx; +#endif /* CONFIG_AP_SUPPORT */ + + 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)) + { + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeDELBAAction() allocate memory failed 1. \n")); + return; + } + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); /*Get an unused nonpaged memory*/ + if(NStatus != 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.) */ + Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID]; + +#ifdef P2P_SUPPORT + /*if (VALID_WCID(pInfo->Wcid)) */ + { + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[pInfo->Wcid]; + + if (pEntry) + BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pInfo->Wcid].Addr, pEntry->HdrAddr2); + } +#else +#ifdef MESH_SUPPORT + if (IS_ENTRY_MESH(&pAd->MacTab.Content[pInfo->Wcid])) + { + BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->MeshTab.CurrentAddress); + } + else +#endif /* MESH_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(&pAd->MacTab.Content[pInfo->Wcid])) + { +#ifdef MAC_REPEATER_SUPPORT + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[pInfo->Wcid]; +#endif /* MAC_REPEATER_SUPPORT */ + + apidx = pAd->MacTab.Content[pInfo->Wcid].MatchAPCLITabIdx; +#ifdef MAC_REPEATER_SUPPORT + if (pEntry && pEntry->bReptCli) + BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->ApCfg.ApCliTab[apidx].RepeaterCli[pEntry->MatchReptCliIdx].CurrentAddress); + else +#endif /* MAC_REPEATER_SUPPORT */ + BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress); + } + else +#endif /* APCLI_SUPPORT */ + { + apidx = pAd->MacTab.Content[pInfo->Wcid].apidx; + BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->ApCfg.MBSSID[apidx].Bssid); + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress); +#endif /* CONFIG_STA_SUPPORT */ +#endif /* P2P_SUPPORT */ + + 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; +#ifdef P2P_SUPPORT + if (VALID_WCID(pInfo->Wcid)) + { + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[pInfo->Wcid]; + + if (pEntry) + { +#ifdef CONFIG_STA_SUPPORT + if (ADHOC_ON(pAd) +#ifdef QOS_DLS_SUPPORT + || (IS_ENTRY_DLS(&pAd->MacTab.Content[pInfo->Wcid])) +#endif /* QOS_DLS_SUPPORT */ +#ifdef DOT11Z_TDLS_SUPPORT + || (IS_ENTRY_TDLS(&pAd->MacTab.Content[pInfo->Wcid])) +#endif /* DOT11Z_TDLS_SUPPORT */ + ) + { + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + } + else +#endif /* CONFIG_STA_SUPPORT */ + { + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pEntry->HdrAddr2, pEntry->HdrAddr3); + } + } + } +#else +#ifdef MESH_SUPPORT + if (IS_ENTRY_MESH(&pAd->MacTab.Content[pInfo->Wcid])) + { + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->MeshTab.CurrentAddress, pAd->MacTab.Content[pInfo->Wcid].Addr); + } + else +#endif /* MESH_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(&pAd->MacTab.Content[pInfo->Wcid])) + { +#ifdef MAC_REPEATER_SUPPORT + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[pInfo->Wcid]; +#endif /* MAC_REPEATER_SUPPORT */ + + apidx = pAd->MacTab.Content[pInfo->Wcid].MatchAPCLITabIdx; +#ifdef MAC_REPEATER_SUPPORT + if (pEntry && pEntry->bReptCli) + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->ApCfg.ApCliTab[apidx].RepeaterCli[pEntry->MatchReptCliIdx].CurrentAddress, pAd->MacTab.Content[pInfo->Wcid].Addr); + else +#endif /* MAC_REPEATER_SUPPORT */ + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress, pAd->MacTab.Content[pInfo->Wcid].Addr); + } + else +#endif /* APCLI_SUPPORT */ + { + apidx = pAd->MacTab.Content[pInfo->Wcid].apidx; + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].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(&pAd->MacTab.Content[pInfo->Wcid])) +#endif /* QOS_DLS_SUPPORT */ +#ifdef DOT11Z_TDLS_SUPPORT + || (IS_ENTRY_TDLS(&pAd->MacTab.Content[pInfo->Wcid])) +#endif /* DOT11Z_TDLS_SUPPORT */ + ) + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + else + ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[pInfo->Wcid].Addr); + } +#endif /* CONFIG_STA_SUPPORT */ +#endif /* P2P_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( + 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) +{ + /*PUCHAR pOutBuffer = NULL;*/ + /*Return the receiving frame except the MSB of category filed set to 1. 7.3.1.11*/ +} + +VOID PeerQOSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ +} + +#ifdef QOS_DLS_SUPPORT +VOID PeerDLSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + switch(Action) + { + case ACTION_DLS_REQUEST: +#ifdef CONFIG_AP_SUPPORT +#ifndef P2P_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + APPeerDlsReqAction(pAd, Elem); +#endif /* P2P_SUPPORT */ +#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 +#ifndef P2P_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + APPeerDlsRspAction(pAd, Elem); +#endif /* P2P_SUPPORT */ +#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 +#ifndef P2P_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + APPeerDlsTearDownAction(pAd, Elem); +#endif /* P2P_SUPPORT */ +#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( + IN PRTMP_ADAPTER pAd, + IN 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 ApPublicAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + BSS_2040_COEXIST_IE BssCoexist; + + /* Format as in IEEE 7.4.7.2*/ + if (Action == ACTION_BSS_2040_COEXIST) + { + BssCoexist.word = Elem->Msg[LENGTH_802_11+2]; + } +} + + +VOID SendBSS2040CoexistMgmtAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR apidx, + IN UCHAR InfoReq) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + FRAME_ACTION_HDR Frame; + ULONG FrameLen; + BSS_2040_COEXIST_ELEMENT BssCoexistInfo; + BSS_2040_INTOLERANT_CH_REPORT BssIntolerantInfo; + PUCHAR pAddr1; + + 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; + ActHeaderInit(pAd, &Frame.Hdr, pAddr1, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN PUCHAR 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,("ACT - Update2040CoexistFrameAndNotify. BSSCoexist2040 = %x. EventANo = %d. \n", 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 PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN BOOLEAN bAddIntolerantCha) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + FRAME_ACTION_HDR Frame; + ULONG FrameLen; + UINT32 IntolerantChaRepLen; + UCHAR HtLen = 1; + + 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; + } + + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + + 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 BBPValue = 0; + INT32 MACValue; + + DBGPRINT(RT_DEBUG_TRACE,("SPECTRUM - ChannelSwitchAction(NewChannel = %d , Secondary = %d) \n", NewChannel, Secondary)); + + if (ChannelSwitchSanityCheck(pAd, Wcid, NewChannel, Secondary) == FALSE) + return; + + /* 1. Switches to BW = 20.*/ + if (Secondary == 0) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue&= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + 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" )); + } + pAd->CommonCfg.BBPCurrentBW = BW_20; + pAd->CommonCfg.Channel = NewChannel; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel,FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 0; + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = 0; + DBGPRINT(RT_DEBUG_TRACE, ("!!!20MHz !!! \n" )); + } + /* 1. Switches to BW = 40 And Station supports BW = 40.*/ + else if (((Secondary == 1) || (Secondary == 3)) && (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == 1)) + { + pAd->CommonCfg.Channel = NewChannel; + + if (Secondary == 1) + { +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPActive == 1) + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + else +#endif /* GREENAP_SUPPORT */ + /* Secondary above.*/ + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2; + RTMP_IO_READ32(pAd, TX_BAND_CFG, &MACValue); + MACValue &= 0xfe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, MACValue); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue&= (~0x18); + +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPActive == 0) +#endif /* GREENAP_SUPPORT */ + BBPValue|= (0x10); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPValue); + BBPValue&= (~0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPValue); + DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Lower LINK UP !!! Control Channel at Below. Central = %d \n", pAd->CommonCfg.CentralChannel )); + } + else + { +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPActive == 1) + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + else +#endif /* GREENAP_SUPPORT */ + + /* Secondary below.*/ + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2; + RTMP_IO_READ32(pAd, TX_BAND_CFG, &MACValue); + MACValue &= 0xfe; + MACValue |= 0x1; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, MACValue); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue&= (~0x18); +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPActive == 0) +#endif /* GREENAP_SUPPORT */ + BBPValue|= (0x10); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPValue); + BBPValue&= (~0x20); + BBPValue|= (0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPValue); + DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Upper LINK UP !!! Control Channel at UpperCentral = %d \n", pAd->CommonCfg.CentralChannel )); + } +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPActive == 1) + pAd->CommonCfg.BBPCurrentBW = BW_20; + else +#endif /* GREENAP_SUPPORT */ + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 1; + } +} +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +VOID PeerPublicAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef P2P_SUPPORT + if (!P2P_INF_ON(pAd)) +#endif /* P2P_SUPPORT */ + if ((Elem->Wcid >= MaxWcidNum) +#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 +#ifdef P2P_SUPPORT + if ((Elem->OpMode == OPMODE_AP) || (pAd->OpMode == OPMODE_AP)) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { +#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 +#ifdef P2P_SUPPORT + if ((Elem->OpMode == OPMODE_STA) || (pAd->OpMode == OPMODE_STA)) +#else + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) +#endif /* P2P_SUPPORT */ + { + if (INFRA_ON(pAd)) + { + StaPublicAction(pAd, pBssCoexistIe); + } + } +#endif /* CONFIG_STA_SUPPORT */ + } + break; +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + 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 // + +#ifdef P2P_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("<---- Public. Vendor OUI+type = %08x \n", *(PULONG)&Elem->Msg[LENGTH_802_11+2] )); +#ifdef RT_BIG_ENDIAN + if (SWAP32(*(PUINT32)&Elem->Msg[LENGTH_802_11+2]) == P2P_OUI) +#else + if (*(PUINT32)&Elem->Msg[LENGTH_802_11+2] == P2P_OUI) +#endif /* RT_BIG_ENDIAN */ + { + UCHAR Subtype = Elem->Msg[LENGTH_802_11+6]; + + + DBGPRINT(RT_DEBUG_TRACE, ("!!!! Public action frames with Vendor specific OUI = WFAP2P.Subtype = %d. \n", Subtype)); + pAd->P2pCfg.bPeriodicListen = FALSE; + if (pAd->P2pCfg.P2pCounter.bStartScan) + { + pAd->P2pCfg.P2pCounter.bStartScan = FALSE; + pAd->P2pCfg.P2pCounter.bListen = FALSE; + pAd->P2pCfg.P2pCounter.bNextScan = FALSE; + /* update P2P Ctrl State Machine status. */ + MlmeEnqueue(pAd, P2P_CTRL_STATE_MACHINE, P2P_CTRL_DISC_CANL_EVT, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); + } + switch(Subtype) + { + case GO_NEGOCIATION_REQ: + DBGPRINT(RT_DEBUG_ERROR, ("%s : recv Group Nego. Req\n", __FUNCTION__)); + P2pPeerGoNegoReqAction(pAd,Elem); + break; + case GO_NEGOCIATION_RSP: + DBGPRINT(RT_DEBUG_ERROR, ("%s : recv Group Nego. Rsp\n", __FUNCTION__)); + P2pPeerGoNegoRspAction(pAd,Elem); + break; + case GO_NEGOCIATION_CONFIRM: + DBGPRINT(RT_DEBUG_ERROR, ("%s : recv Group Nego. Confirm\n", __FUNCTION__)); + P2pPeerGoNegoConfirmAction(pAd,Elem); + break; + case P2P_INVITE_REQ: + DBGPRINT(RT_DEBUG_ERROR, ("%s : recv Invite Req\n", __FUNCTION__)); + P2pPeerInvitesReqAction(pAd,Elem); + break; + case P2P_INVITE_RSP: + DBGPRINT(RT_DEBUG_ERROR, ("%s : recv Invite Rsp\n", __FUNCTION__)); + P2pPeerInvitesRspAction(pAd,Elem); + break; + case P2P_DEV_DIS_REQ: + DBGPRINT(RT_DEBUG_ERROR, ("%s : recv Device Discovery Req\n", __FUNCTION__)); + P2pPeerDevDiscoverReqAction(pAd,Elem); + break; + case P2P_DEV_DIS_RSP: + DBGPRINT(RT_DEBUG_ERROR, ("%s : recv Device Discovery Rsp\n", __FUNCTION__)); + P2pPeerDeviceDiscRspAction(pAd,Elem); + break; + case P2P_PROVISION_REQ: + DBGPRINT(RT_DEBUG_ERROR, ("%s : recv Provision Req\n", __FUNCTION__)); + P2pPeerProvisionReqAction(pAd,Elem); + break; + case P2P_PROVISION_RSP: + DBGPRINT(RT_DEBUG_ERROR, ("%s : recv Provision Rsp\n", __FUNCTION__)); + P2pPeerProvisionRspAction(pAd,Elem); + break; + default: + pAd->P2pCfg.bPeriodicListen = TRUE; + DBGPRINT(RT_DEBUG_ERROR,("Unknown Public action frames with Vendor specific OUI = WFAP2P.Subtype = %d \n", Subtype)); + break; + } + } +#endif /* P2P_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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ +#ifdef CONFIG_AP_SUPPORT +#endif /* CONFIG_AP_SUPPORT */ + return; +} + +#ifdef DOT11_N_SUPPORT +static VOID respond_ht_information_exchange_action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; +#ifdef CONFIG_AP_SUPPORT + INT apidx; +#endif /* CONFIG_AP_SUPPORT */ + FRAME_HT_INFO HTINFOframe, *pFrame; + UCHAR *pAddr; +#ifdef P2P_SUPPORT + MAC_TABLE_ENTRY *pEntry = NULL; +#endif /* P2P_SUPPORT */ + + + /* 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 - respond_ht_information_exchange_action() allocate memory failed \n")); + return; + } + + /* get RA */ + pFrame = (FRAME_HT_INFO *) &Elem->Msg[0]; + pAddr = pFrame->Hdr.Addr2; + + NdisZeroMemory(&HTINFOframe, sizeof(FRAME_HT_INFO)); + /* 2-1. Prepare ADDBA Response frame.*/ +#ifdef P2P_SUPPORT + if (VALID_WCID(Elem->Wcid)) + { + pEntry = &pAd->MacTab.Content[Elem->Wcid]; + + ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, pEntry->HdrAddr2, pEntry->HdrAddr3); + } +#else +#ifdef MESH_SUPPORT + if (IS_ENTRY_MESH(&pAd->MacTab.Content[Elem->Wcid])) + { + ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, pAd->MeshTab.CurrentAddress, pAddr); + } + else +#endif /* MESH_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(&pAd->MacTab.Content[Elem->Wcid])) + { +#ifdef MAC_REPEATER_SUPPORT + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[Elem->Wcid]; +#endif /* MAC_REPEATER_SUPPORT */ + + apidx = pAd->MacTab.Content[Elem->Wcid].MatchAPCLITabIdx; +#ifdef MAC_REPEATER_SUPPORT + if (pEntry && pEntry->bReptCli) + ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, pAd->ApCfg.ApCliTab[apidx].RepeaterCli[pEntry->MatchReptCliIdx].CurrentAddress, pAddr); + else +#endif /* MAC_REPEATER_SUPPORT */ + ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress, pAddr); + } + else +#endif /* APCLI_SUPPORT */ + { + apidx = pAd->MacTab.Content[Elem->Wcid].apidx; + ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid); + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (ADHOC_ON(pAd)) + ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + else + ActHeaderInit(pAd, &HTINFOframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr); + } +#endif /* CONFIG_STA_SUPPORT */ +#endif /* P2P_SUPPORT */ + + HTINFOframe.Category = CATEGORY_HT; + HTINFOframe.Action = HT_INFO_EXCHANGE; + HTINFOframe.HT_Info.Request = 0; + HTINFOframe.HT_Info.Forty_MHz_Intolerant = pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant; + HTINFOframe.HT_Info.STA_Channel_Width = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth; + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_HT_INFO), &HTINFOframe, + END_OF_ARGS); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +} + + +#ifdef CONFIG_AP_SUPPORT +#ifdef DOT11N_DRAFT3 +VOID SendNotifyBWActionFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR apidx) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + FRAME_ACTION_HDR Frame; + ULONG FrameLen; + PUCHAR pAddr1; + + + 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; + + ActHeaderInit(pAd, &Frame.Hdr, pAddr1, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].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( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + if (Elem->Wcid >= MaxWcidNum) + return; + + 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. */ + pAd->MacTab.Content[Elem->Wcid].HTPhyMode.field.BW = 0; + else + { + pAd->MacTab.Content[Elem->Wcid].HTPhyMode.field.BW = + pAd->MacTab.Content[Elem->Wcid].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)) + { + pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_ENABLE; + } + else if (((Elem->Msg[LENGTH_802_11+2]&0x2) == 0)) + { + pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_STATIC; + } + else + { + pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_DYNAMIC; + } + + DBGPRINT(RT_DEBUG_TRACE,("Aid(%d) MIMO PS = %d\n", Elem->Wcid, pAd->MacTab.Content[Elem->Wcid].MmpsMode)); + /* rt2860c : add something for smps change.*/ + break; + + case SETPCO_ACTION: + break; + + case MIMO_CHA_MEASURE_ACTION: + break; + + case HT_INFO_EXCHANGE: + { + HT_INFORMATION_OCTET *pHT_info; + + pHT_info = (HT_INFORMATION_OCTET *) &Elem->Msg[LENGTH_802_11+2]; + /* 7.4.8.10*/ + DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Information Exchange action----> \n")); + if (pHT_info->Request) + { + respond_ht_information_exchange_action(pAd, Elem); + } +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (pHT_info->Forty_MHz_Intolerant) + { + Handle_BSS_Width_Trigger_Events(pAd); + } + } +#endif /* CONFIG_AP_SUPPORT */ + } + break; + } +} + + +/* + ========================================================================== + 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 ORIBATimerTimeout( + IN PRTMP_ADAPTER pAd) +{ + MAC_TABLE_ENTRY *pEntry; + INT i, total; +/* FRAME_BAR FrameBar;*/ +/* ULONG FrameLen;*/ +/* NDIS_STATUS NStatus;*/ +/* PUCHAR pOutBuffer = NULL;*/ +/* USHORT Sequence;*/ + UCHAR TID; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + return; +#endif /* RALINK_ATE */ + + total = pAd->MacTab.Size * NUM_OF_TID; + + for (i = 1; ((i 0)) ; i++) + { + if (pAd->BATable.BAOriEntry[i].ORI_BA_Status == Originator_Done) + { + pEntry = &pAd->MacTab.Content[pAd->BATable.BAOriEntry[i].Wcid]; + TID = pAd->BATable.BAOriEntry[i].TID; + + ASSERT(pAd->BATable.BAOriEntry[i].Wcid < MaxWcidNum); + } + total --; + } +} + + +VOID SendRefreshBAR( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry) +{ + FRAME_BAR FrameBar; + ULONG FrameLen; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + USHORT Sequence; + UCHAR i, TID; + USHORT idx; + BA_ORI_ENTRY *pBAEntry; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + + 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 < MaxWcidNum); + + 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 P2P_SUPPORT + BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pEntry->HdrAddr2); +#else +#ifdef MESH_SUPPORT + if (IS_ENTRY_MESH(pEntry)) + BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pAd->MeshTab.CurrentAddress); + else +#endif /* MESH_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { +#ifdef MAC_REPEATER_SUPPORT + if (pEntry && pEntry->bReptCli) + BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].RepeaterCli[pEntry->MatchReptCliIdx].CurrentAddress); + else +#endif /* MAC_REPEATER_SUPPORT */ + BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].CurrentAddress); + } + else +#endif /* APCLI_SUPPORT */ + BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pAd->ApCfg.MBSSID[pEntry->apidx].Bssid); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pAd->CurrentAddress); +#endif /* CONFIG_STA_SUPPORT */ +#endif /* P2P_SUPPORT */ + + 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); + /*if (!(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET)))*/ + if (1) /* Now we always send BAR.*/ + { + /*MiniportMMRequestUnlock(pAd, 0, pOutBuffer, FrameLen);*/ + MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG | MapUserPriorityToAccessCategory[TID]), pOutBuffer, FrameLen); + + } + MlmeFreeMemory(pAd, pOutBuffer); + } + } +} +#endif /* DOT11_N_SUPPORT */ + +VOID ActHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN PUCHAR Addr1, + IN PUCHAR Addr2, + IN PUCHAR Addr3) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + pHdr80211->FC.Type = BTYPE_MGMT; + pHdr80211->FC.SubType = SUBTYPE_ACTION; + + COPY_MAC_ADDR(pHdr80211->Addr1, Addr1); + COPY_MAC_ADDR(pHdr80211->Addr2, Addr2); + COPY_MAC_ADDR(pHdr80211->Addr3, Addr3); +} + +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 = BTYPE_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/mt7620/src/common/auto_provision.c b/mt7620/src/common/auto_provision.c new file mode 100644 index 0000000..8cd0235 --- /dev/null +++ b/mt7620/src/common/auto_provision.c @@ -0,0 +1,1480 @@ +/* + *************************************************************************** + * 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: + auto_provision + + Abstract: +*/ + +#include "rt_config.h" + +extern UCHAR WPS_OUI[]; + +#ifdef EASY_CONFIG_SETUP +#ifdef CONFIG_AP_SUPPORT +VOID AutoProvisionBuildAssocRespIE( + IN PRTMP_ADAPTER pAd, + IN UCHAR ApIdx, + IN UCHAR Reason, + OUT PUCHAR pOutBuf, + OUT PUCHAR pIeLen) +{ + WSC_IE_HEADER ieHdr; + UCHAR Data[512] = {0}; + PUCHAR pData; + INT Len = 0, templen = 0; + UINT8 tempVal = 0; +#ifdef EASY_CONFIG_SETUP + UCHAR ExtData[4] = {0}; +#endif /* EASY_CONFIG_SETUP */ + UCHAR Version = 0x10; + USHORT Tag = 0, TlvLen = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscBuildAssocRespIE\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] = 0x04; + + pData = (PUCHAR) &Data[0]; + Len = 0; + + /* Version, 1 byte */ + Tag = cpu2be16(0x104A); + TlvLen = cpu2be16(1); + NdisMoveMemory(pData, &Tag, 2); + NdisMoveMemory(pData+2, &TlvLen, 2); + NdisMoveMemory(pData+4, &Version, 1); + templen = 5; + pData += templen; + Len += templen; + + /* Request Type */ + tempVal = 0x03; + Tag = cpu2be16(0x103B); + TlvLen = cpu2be16(1); + NdisMoveMemory(pData, &Tag, 2); + NdisMoveMemory(pData+2, &TlvLen, 2); + NdisMoveMemory(pData+4, &tempVal, 1); + templen = 5; + pData += templen; + Len += templen; + + /* + Only main bssid supports auto provision. + */ + if ((pAd->ApCfg.MBSSID[MAIN_MBSSID].EasyConfigInfo.bEnable == TRUE) && + (ApIdx == MAIN_MBSSID)) + { + /* WPS Vendor Extension */ + NdisMoveMemory(ExtData, RALINK_OUI, 3); + ExtData[3] = Reason; + Tag = cpu2be16(0x1049); + TlvLen = cpu2be16(4); + NdisMoveMemory(pData, &Tag, 2); + NdisMoveMemory(pData+2, &TlvLen, 2); + NdisMoveMemory(pData+4, &ExtData[0], 4); + templen = 8; + pData += templen; + Len += templen; + } + + 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; + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscBuildAssocRespIE\n")); +} + + +VOID AutoProvisionBuildAssocRspIE( + IN PRTMP_ADAPTER pAd, + IN PMLME_QUEUE_ELEM Elem, + IN PMAC_TABLE_ENTRY pEntry, + OUT PUCHAR pOutBuffer, + OUT PULONG pFrameLen) +{ + if (pEntry && pEntry->bRaAutoWpsCapable) + { + UCHAR *pWscBuf = NULL, WscIeLen = 0; + ULONG WscTmpLen = 0; + PEASY_CONFIG_INFO pEasyConfig = &pAd->ApCfg.MBSSID[pEntry->apidx].EasyConfigInfo; + + os_alloc_mem(NULL, (UCHAR **)&pWscBuf, 512); +/* if( (pWscBuf = kmalloc(512, GFP_ATOMIC)) != NULL) */ + if (pWscBuf != NULL) + { + CHAR Rssi = -80; + Rssi = RTMPMaxRssi(pAd, + ConvertToRssi(pAd, (CHAR)Elem->Rssi0, RSSI_0), + ConvertToRssi(pAd, (CHAR)Elem->Rssi1, RSSI_1), + ConvertToRssi(pAd, (CHAR)Elem->Rssi2, RSSI_2)); + + NdisZeroMemory(pWscBuf, 512); + +#ifdef WSC_AP_SUPPORT + if ((pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscConfMode != WSC_DISABLE) && + (MAC_ADDR_EQUAL(pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EntryAddr, pEntry->Addr))) + { + if (Rssi > pEasyConfig->RssiThreshold) + WscBuildAssocRespIE(pAd, pEntry->apidx, 0, pWscBuf, &WscIeLen); + else + { + pEntry->bRaAutoWpsCapable = FALSE; + WscBuildAssocRespIE(pAd, pEntry->apidx, 1, pWscBuf, &WscIeLen); + } + } + else +#endif /* WSC_AP_SUPPORT */ + if (pEasyConfig->bEnable == TRUE) + { + if (Rssi > pEasyConfig->RssiThreshold) + AutoProvisionBuildAssocRespIE(pAd, pEntry->apidx, 0, pWscBuf, &WscIeLen); + else + { + pEntry->bRaAutoWpsCapable = FALSE; + AutoProvisionBuildAssocRespIE(pAd, pEntry->apidx, 1, pWscBuf, &WscIeLen); + } + } + + MakeOutgoingFrame(pOutBuffer + (*pFrameLen), &WscTmpLen, + WscIeLen, pWscBuf, + END_OF_ARGS); + + (*pFrameLen) += WscTmpLen; +/* kfree(pWscBuf); */ + os_free_mem(NULL, pWscBuf); + } + else + DBGPRINT(RT_DEBUG_WARN, ("%s:: WscBuf Allocate failed!\n", __FUNCTION__)); + } +} + +VOID AutoProvisionCheckEntry( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PEID_STRUCT eid_ptr) +{ +#ifdef WAC_SUPPORT + if (pEntry && pEntry->bSamsungAutoWpsCapable) + return; +#endif // WAC_SUPPORT // + + if (pAd->ApCfg.MBSSID[MAIN_MBSSID].EasyConfigInfo.bEnable==TRUE) + { + if (pEntry && eid_ptr) + { + pEntry->bRaAutoWpsCapable = FALSE; + if (pEntry->apidx == MAIN_MBSSID) + { + if (WpsMICIntegrity(pAd, eid_ptr->Octet, (INT)eid_ptr->Len, pEntry->Addr, pEntry->apidx)) + { + pEntry->bRaAutoWpsCapable = TRUE; + } + } + } + } +} + +VOID AutoProvisionAssignSSID( + IN PRTMP_ADAPTER pAd, + IN PUCHAR eid_data, + IN INT eid_len, + IN PUCHAR pAddr2, + IN UCHAR apidx, + OUT PUCHAR SsidLen, + OUT PUCHAR Ssid) +{ + if (pAd->ApCfg.MBSSID[apidx].EasyConfigInfo.bEnable == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR, ("MBSSID[%d] do not support Easy Config, skip the checking EC OUI\n",apidx)); + return; + } + if (WpsMICIntegrity(pAd, eid_data, eid_len, pAddr2, apidx)) + { + *SsidLen = pAd->ApCfg.MBSSID[apidx].SsidLen; + NdisMoveMemory(Ssid, pAd->ApCfg.MBSSID[apidx].Ssid, *SsidLen); + } +} + +BOOLEAN AutoProvisionCheckWscMsg( + IN PRTMP_ADAPTER pAd, + IN PFRAME_802_11 pFrame, + INOUT PUSHORT pDataSize) +{ + /*int HeaderLen = LENGTH_802_1_H + sizeof(IEEE8021X_FRAME) + sizeof(EAP_FRAME);*/ + PSTRING pData; + PEAP_FRAME pEapFrame; + + /* Skip the EAP LLC header */ + pData = (PSTRING) (pFrame + LENGTH_802_1_H); + if (pData) + pEapFrame = (PEAP_FRAME)(pData + sizeof(IEEE8021X_FRAME)); + pData += sizeof(IEEE8021X_FRAME) + sizeof(EAP_FRAME); + + if ((pData != NULL) && + (pEapFrame->Code == EAP_CODE_RSP) && + (pEapFrame->Type == EAP_TYPE_WSC)) + { + if (WscCheckWSCHeader((PUCHAR) pData)) + { + /* EAP-Rsp (Messages) */ + pData += sizeof(WSC_FRAME); + if (pData && (pData + 9)) + { + UCHAR MsgType = *(pData + 9); + if (MsgType == 0x04) /* M1 */ + { + *pDataSize -= 19; + } + } + } + } + return FALSE; +} + +#endif /* CONFIG_AP_SUPPORT */ + +VOID AutoProvisionGenWpsPTK( + IN PRTMP_ADAPTER pAd, + IN UCHAR ApIdx) +{ + UCHAR temp1[64]; + CHAR temp2[6] = {'r', 'a', 'l', 'i', 'n', 'k'}; + PEASY_CONFIG_INFO pEasyConfigInfo; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + pEasyConfigInfo = &pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pEasyConfigInfo = &pAd->StaCfg.EasyConfigInfo; + } +#endif /* CONFIG_STA_SUPPORT */ + + /* use proprietary WPS PTK */ + NdisZeroMemory(temp1, 64); + NdisMoveMemory(temp1, "ralink_auto_provision", strlen("ralink_auto_provision")); + + NdisZeroMemory(pEasyConfigInfo->WpsPTK, 64); + /* use proprietary PTK */ + WpaDerivePTK(pAd, temp1, temp1, temp2, temp1, temp2, pEasyConfigInfo->WpsPTK, LEN_PTK); +} + +VOID AutoProvisionDecodeExtData( + IN PRTMP_ADAPTER pAd, + IN UCHAR ApIdx, + IN PUCHAR pEntryAddr, + IN PUCHAR pData) +{ +#ifdef WSC_INCLUDED + PWSC_CTRL pWpsCtrl = NULL; +#endif /* WSC_INCLUDED */ + PMAC_TABLE_ENTRY pEntry = NULL; + PEASY_CONFIG_INFO pEasyConfigInfo = NULL; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + pEasyConfigInfo = &pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo; +#ifdef WSC_INCLUDED + pWpsCtrl = &pAd->ApCfg.MBSSID[ApIdx].WscControl; +#endif /* WSC_INCLUDED */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pEasyConfigInfo = &pAd->StaCfg.EasyConfigInfo; +#ifdef WSC_INCLUDED + pWpsCtrl = &pAd->StaCfg.WscControl; +#endif /* WSC_INCLUDED */ + } +#endif /* CONFIG_STA_SUPPORT */ + + pEntry = MacTableLookup(pAd, pEntryAddr); + if (pEntry && (pEntry->bRaAutoWpsCapable && !pEntry->bSamsungAutoWpsCapable)) + { + CIPHER_KEY CipherKey; + CHAR EncryptedPIN[16] = {0}, PinStr[9] = {0}; + UINT16 PinLen = 12; + UCHAR iv_hdr[4]; + + NdisZeroMemory(&CipherKey, sizeof(CIPHER_KEY)); + NdisMoveMemory(&CipherKey, pEasyConfigInfo->WpsPTK, 64); + CipherKey.CipherAlg = CIPHER_WEP128; + CipherKey.KeyLen = 13; + NdisMoveMemory(&EncryptedPIN[4], pData+3, 12); + + /* Construct the 4-bytes WEP IV header */ + RTMPConstructWEPIVHdr(1, + CipherKey.TxTsc, + iv_hdr); + + NdisMoveMemory(&EncryptedPIN[0], &iv_hdr, 4); + + PinLen = 16; + if (RTMPSoftDecryptWEP(pAd, &CipherKey, EncryptedPIN, &PinLen)) + { + NdisMoveMemory(PinStr, &EncryptedPIN[0], 8); + NdisMoveMemory(&(pEasyConfigInfo->WpsPinCode[0]), &EncryptedPIN[0], 8); +#ifdef WSC_INCLUDED + if ((pWpsCtrl->WscConfMode != WSC_DISABLE) && + (pEasyConfigInfo->bEnable)) + { + pWpsCtrl->WscPinCode = simple_strtol(PinStr, 0, 10); + pWpsCtrl->WscPinCodeLen = 8; + /* + To make sure of doing WPS process with WPS Client by PIN method + */ + pWpsCtrl->WscMode = WSC_PIN_MODE; + WscGetRegDataPIN(pAd, pWpsCtrl->WscPinCode, pWpsCtrl); + } +#endif /* WSC_INCLUDED */ + } + } +} + +BOOLEAN WpsMICIntegrity( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN INT DataLen, + IN PUCHAR pMacAddr, + IN UCHAR ApIdx) +{ + BOOLEAN bStatus = FALSE; + PUCHAR pBuf = NULL; + INT BufLen = 0, Length = DataLen; + UCHAR *Ptr = pData + 4, *pWpsMIC = NULL, *pPeerWpsMIC = NULL; + WSC_IE *pWscIE; + EASY_CONFIG_INFO *pEasyConfigInfo = NULL; + + if (DataLen > 255) + { + DBGPRINT(RT_DEBUG_WARN, ("%s: DataLen > 255\n", __FUNCTION__)); + return FALSE; + } + + os_alloc_mem(NULL, (UCHAR **)&pBuf, 256); +/* if((pBuf = kmalloc(256, GFP_ATOMIC)) == NULL) */ + if (pBuf == NULL) + { + DBGPRINT(RT_DEBUG_WARN, ("%s: pBuf alloc fail !!\n", __FUNCTION__)); + return FALSE; + } + + pWpsMIC = pBuf + 200; + pPeerWpsMIC = pBuf + 216; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + pEasyConfigInfo = &pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pEasyConfigInfo = &pAd->StaCfg.EasyConfigInfo; + } +#endif /* CONFIG_STA_SUPPORT */ + + NdisZeroMemory(pBuf, 256); + while (Length > 0) + { + WSC_IE WscIE; + NdisMoveMemory(&WscIE, Ptr, sizeof(WSC_IE)); + /* Check for WSC IEs */ + pWscIE = &WscIE; + + /* Check for device password ID, PBC = 0x0004 */ + if (be2cpu16(pWscIE->Type) == 0x1049) + { + /* + 4: 0x00 0x50 0xF2 0x04 + 4: 0x10 0x49 0x00 0x0x + */ + BufLen = DataLen - 4 - 4 - (INT)be2cpu16(pWscIE->Length); + NdisMoveMemory(pBuf, pData + 4, BufLen); + /* + 7: 0x10 0x49 0x00 0x0x 0x00 0x0c 0x43 + */ + NdisMoveMemory(pPeerWpsMIC, Ptr + 7, LEN_KEY_DESC_MIC); + WpsCalculateMIC(pAd, pBuf, BufLen, pEasyConfigInfo, pMacAddr, pWpsMIC); + if (NdisEqualMemory(pPeerWpsMIC, pWpsMIC, LEN_KEY_DESC_MIC)) + bStatus = TRUE; + break; + } + + /* Set the offset and look for PBC information */ + /* Since Type and Length are both short type, we need to offset 4, not 2 */ + Ptr += (be2cpu16(pWscIE->Length) + 4); + Length -= (be2cpu16(pWscIE->Length) + 4); + } + +/* kfree(pBuf); */ + os_free_mem(NULL, pBuf); + return bStatus; +} + +VOID WpsCalculateMIC( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBuf, + IN INT BufLen, + IN PEASY_CONFIG_INFO pEasyConfig, + IN PUCHAR pMacAddr, + OUT PUCHAR pMIC) +{ + PUCHAR pDigest = NULL, pTemp = NULL; + + os_alloc_mem(NULL, &pTemp, 256); + if(pTemp == NULL) + { + DBGPRINT(RT_DEBUG_WARN, ("%s: pTemp alloc fail !!\n", __FUNCTION__)); + return; + } + + os_alloc_mem(NULL, &pDigest, 80); + if(pDigest == NULL) + { + os_free_mem(pAd, pTemp); + DBGPRINT(RT_DEBUG_WARN, ("%s: pDigest alloc fail !!\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(pTemp, 256); + NdisMoveMemory(pTemp, pBuf, BufLen); + NdisMoveMemory(pTemp + BufLen, pMacAddr, MAC_ADDR_LEN); + + RT_HMAC_SHA1(pEasyConfig->WpsPTK, LEN_PTK_KCK, pTemp, BufLen + MAC_ADDR_LEN, pDigest, SHA1_DIGEST_SIZE); + NdisMoveMemory(pMIC, pDigest, LEN_KEY_DESC_MIC); + + os_free_mem(pAd, pTemp); + os_free_mem(pAd, pDigest); +} +#endif /* EASY_CONFIG_SETUP */ + +#ifdef WAC_SUPPORT + +/* + SAMSUNG DMC + WAC Attribute IDs +*/ +#define WAC_DEVICE_ADVERTISE_ID 0x00 +#define WAC_AUTO_PROVISION_ID 0x01 +#define WAC_STATUS_ID 0x02 +#define WAC_DEVICE_INFORMATION_ID 0x03 +/* Length of WAC Attributes */ +#define SAMSUNG_OUI_LEN 4 +#define DEVICE_ADVERTISE_ATTRIBUTE_LEN 3 +#define DEVICE_INFORMATION_ATTRIBUTE_LEN 7 +#define STATUS_ATTRIBUTE_LEN 3 +#define AUTO_PROVISIONING_ATTRIBUTE_LEN 10 +/* Setting of Device Information Fields */ +#define THRESHOLD_OFFSET1 0 /* In current, not used */ +#define THRESHOLD_OFFSET2 0 /* In current, not used */ +#define INTERNAL_ANTENNA 0 +#define EXTERNAL_ANTENNA 1 +/* Device Types */ +#define DEVICE_TYPE_TV 0 +#define DEVICE_TYPE_TC 6 +#define DEVICE_TYPE_BD 9 +/* Device Models */ +#define DEVICE_MODEL_TV 0 /* In current, not used */ +/* RSSI Threshold */ +#define RSSI_THRESHOLD -70 +/* +The Format of Device Information Attribute +--------------------------------------------------------------------------------------------------------------------- +| Field | Size(Octets) | Value | Description +--------------------------------------------------------------------------------------------------------------------- +| Attribute ID | 1 | 0x03 | Indicate Device Information attribute +| Length | 1 | variable | Length of Device Type, Year of Production, and Device Model field in octets +| Threshold Offset1 | 1 | variable | Offset for AP Tx Power, Signed value [dB] (-128 ~ + 127) +| Threshold Offset2 | 1 | variable | Offset Antenna, etc., Signed value [dB] (-128 ~ +127) +| Antenna Type | 1 | 0x00 / 0x01 | 0x00 = Internal, 0x01 = External +| Device Type | 1 | variable | Device Type Code +| Device Model | variable | variable | Model name of a device +--------------------------------------------------------------------------------------------------------------------- + +The example of TV +--------------------------------------------------------------------------------------------------------------------- +| Field | Size(Octets) | Value | Description +--------------------------------------------------------------------------------------------------------------------- +| Attribute ID | 1 | 0x03 | Indicate Device Information attribute +| Length | 1 | 0x05 | +| Threshold Offset1 | 1 | 0x00 | +| Threshold Offset2 | 1 | 0x00 | +| Antenna Type | 1 | 0x01 | External +| Device Type | 1 | 0x00 | +| Device Model | 1 | 0x00 | Not used +--------------------------------------------------------------------------------------------------------------------- +*/ + +UCHAR SAMSUNG_OUI[] = {0x00, 0x12, 0xFB}; +UCHAR SAMSUNG_OUI_TYPE = 0x01; + +/* + Device Advertise Attribute + Field Size(Octets) Value + ID 1 0 + Length 1 1 + WAC On/Off 1 0x01/0x00 WAC On(0x01), WAC Off(0x00) +*/ +VOID WAC_GenDeviceAdvertiseAttr( + IN BOOLEAN bEnableWAC, + OUT PUCHAR pData, + OUT PUCHAR pDataLen) +{ + PUCHAR pIE_Data = NULL; + + os_alloc_mem(NULL, &pIE_Data, 128); + + if (pIE_Data == NULL) + { + DBGPRINT(RT_DEBUG_WARN, ("%s pIE_Data alloc fail !!\n", __FUNCTION__)); + return; + } + + if (pIE_Data) + { + /* Ralink Original + NdisZeroMemory(pIE_Data, 128); + pIE_Data[0] = 0xDD; + pIE_Data[1] = 7; + NdisMoveMemory(pIE_Data+2, SAMSUNG_OUI, 3); + pIE_Data[5] = SAMSUNG_OUI_TYPE; + pIE_Data[6] = WAC_DEVICE_ADVERTISE_ID; + pIE_Data[7] = 1; + if (bEnableWAC) + pIE_Data[8] = 1; + else + pIE_Data[8] = 0; + *pDataLen = 9; + NdisMoveMemory(pData, pIE_Data, *pDataLen); + os_free_mem(NULL, pIE_Data); + */ + /* SAMSUNG DMC */ + NdisZeroMemory(pIE_Data, 128); + pIE_Data[0] = 0xDD; + /* 14 = Leng. of Samsung OUI, Device Advertise Attr. & Device Information Attr. */ + pIE_Data[1] = SAMSUNG_OUI_LEN + DEVICE_ADVERTISE_ATTRIBUTE_LEN + DEVICE_INFORMATION_ATTRIBUTE_LEN; + NdisMoveMemory(pIE_Data+2, SAMSUNG_OUI, 3); + pIE_Data[5] = SAMSUNG_OUI_TYPE; + pIE_Data[6] = WAC_DEVICE_ADVERTISE_ID; + pIE_Data[7] = 1; + if (bEnableWAC) + pIE_Data[8] = 1; + else + pIE_Data[8] = 0; + pIE_Data[9] = WAC_DEVICE_INFORMATION_ID; /* 3 */ + pIE_Data[10] = DEVICE_INFORMATION_ATTRIBUTE_LEN - 2; /* 5 */ + pIE_Data[11] = THRESHOLD_OFFSET1; /* 0, Threshold Offset1 */ + pIE_Data[12] = THRESHOLD_OFFSET2; /* 0, Threshold Offset2 */ + pIE_Data[13] = EXTERNAL_ANTENNA; /* 1, Antenna Type => External */ + pIE_Data[14] = DEVICE_TYPE_TV; /* 0, Device Type */ + pIE_Data[15] = DEVICE_MODEL_TV; /* 0, Device Model */ + + /* 2 + Leng. of Samsung OUI, Device Advertise Attr. & Device Information Attr. */ + *pDataLen = 2 + SAMSUNG_OUI_LEN + DEVICE_ADVERTISE_ATTRIBUTE_LEN + DEVICE_INFORMATION_ATTRIBUTE_LEN; + NdisMoveMemory(pData, pIE_Data, *pDataLen); + os_free_mem(NULL, pIE_Data); + } +} + +BOOLEAN WAC_ParseAttr( + IN UCHAR AttrID, + IN PUCHAR pInData, + IN UCHAR InDataLen, + OUT PUCHAR pOutData, + IN UCHAR OutDataLen) +{ + UCHAR eid =0, eid_len = 0, *eid_data; + UINT total_ie_len = 0; + + hex_dump("WAC_ParseAttr", pInData, InDataLen); + + eid = pInData[0]; + eid_len = pInData[1]; + total_ie_len = eid_len + 2; + eid_data = pInData+2; + + /* get variable fields from payload and advance the pointer */ + while((eid_data + eid_len) <= ((UCHAR*)pInData + InDataLen)) + { + if (eid == AttrID) + { + if (eid_len <= OutDataLen) + { + NdisMoveMemory(pOutData, eid_data, eid_len); + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s: OutData is not enough to record data, eid_len = %d\n", + __FUNCTION__, eid_len)); + return FALSE; + } + return TRUE; + } + eid = pInData[total_ie_len]; + eid_len = pInData[total_ie_len + 1]; + eid_data = pInData + total_ie_len + 2; + total_ie_len += (eid_len + 2); + } + return FALSE; +} + + +VOID WAC_AddDevAdvAttrIE( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx, + INOUT PUCHAR pBuf, + INOUT ULONG *pFrameLen) +{ + PUCHAR pWAC_IE = NULL; + UCHAR WAC_IELen = 0; + ULONG TmpWACLen = 0; + BOOLEAN bWAC_Enable = FALSE; + +#ifdef CONFIG_AP_SUPPORT + if (pAd->OpMode == OPMODE_AP) + bWAC_Enable = pAd->ApCfg.MBSSID[apidx].EasyConfigInfo.bEnableWAC; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (pAd->OpMode == OPMODE_STA) + bWAC_Enable = pAd->StaCfg.EasyConfigInfo.bEnableWAC; +#endif /* CONFIG_STA_SUPPORT */ + + os_alloc_mem(NULL, &pWAC_IE, 128); + if (pWAC_IE) + { + WAC_GenDeviceAdvertiseAttr(bWAC_Enable, pWAC_IE, &WAC_IELen); + MakeOutgoingFrame(pBuf+(*pFrameLen), &TmpWACLen, + WAC_IELen, pWAC_IE, + END_OF_ARGS); + (*pFrameLen) += TmpWACLen; + os_free_mem(NULL, pWAC_IE); + } +} + +#define WAC_COPY_VENDOR_INFO(__p, __len, __psrc, __src_len, __rv) \ +{\ + if (__p)\ + {\ + os_free_mem(NULL, __p);\ + (*__len) = 0;\ + }\ + os_alloc_mem(NULL, (UCHAR **) &__p, (__src_len + 2));\ + if (__p)\ + {\ + (*__len) = (__src_len + 2);\ + NdisMoveMemory((__p+2), __psrc, __src_len);\ + *(__p) = 0xdd;\ + *(__p+1) = __src_len;\ + }\ + else\ + (*__rv) = FALSE;\ +} + +VOID WAC_CopyVendorInfo( + IN PRTMP_ADAPTER pAd, + IN PWAC_REQUEST pWAC_Req, + IN PEASY_CONFIG_INFO pEasyInfo) +{ + switch(pWAC_Req->FrameType) + { +#ifdef CONFIG_STA_SUPPORT + case WAC_CMD_FOR_PROBE_REQ: + WAC_COPY_VENDOR_INFO(pEasyInfo->pVendorInfoForProbeReq, + &pEasyInfo->VendorInfoForProbeReqLen, + pWAC_Req->pVendorInfo, + pWAC_Req->VendorInfoLen, + &pWAC_Req->RV); + break; +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + case WAC_CMD_FOR_PROBE_RSP: + WAC_COPY_VENDOR_INFO(pEasyInfo->pVendorInfoForProbeRsp, + &pEasyInfo->VendorInfoForProbeRspLen, + pWAC_Req->pVendorInfo, + pWAC_Req->VendorInfoLen, + &pWAC_Req->RV); + break; + case WAC_CMD_FOR_BEACON: + WAC_COPY_VENDOR_INFO(pEasyInfo->pVendorInfoForBeacon, + &pEasyInfo->VendorInfoForBeaconLen, + pWAC_Req->pVendorInfo, + pWAC_Req->VendorInfoLen, + &pWAC_Req->RV); + if (pWAC_Req->RV) + { + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); + } + break; +#endif /* CONFIG_AP_SUPPORT */ + default: + pWAC_Req->RV = FALSE; + DBGPRINT(RT_DEBUG_WARN, ("%s: Unknow FrameType = 0x%x\n", + __FUNCTION__, pWAC_Req->FrameType)); + break; + } +} + +#define WAC_FREE_VENDOR_INFO(__p, __len) \ +{\ + if (__p)\ + { \ + os_free_mem(NULL, __p);\ + __p = NULL;\ + (*__len) = 0;\ + } \ +} + +INT WAC_IoctlReq( + IN PRTMP_ADAPTER pAd, + IN UCHAR ApIdx, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + PWAC_REQUEST pWAC_Req = NULL; + INT Status = NDIS_STATUS_SUCCESS; + PEASY_CONFIG_INFO pEasyInfo = NULL; + +#ifdef CONFIG_AP_SUPPORT + if (pAd->OpMode == OPMODE_AP) + pEasyInfo = &pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (pAd->OpMode == OPMODE_STA) + pEasyInfo = &pAd->StaCfg.EasyConfigInfo; +#endif /* CONFIG_STA_SUPPORT */ + + os_alloc_mem(NULL, (UCHAR **)&pWAC_Req, sizeof(WAC_REQUEST)); + + if (pWAC_Req == NULL) + { + DBGPRINT(RT_DEBUG_WARN, ("%s: pWAC_Req alloc fail !!\n", __FUNCTION__)); + return -ENOMEM; + } + + if (pWAC_Req) + { + Status = copy_from_user(pWAC_Req, wrq->u.data.pointer, wrq->u.data.length); + if (Status == NDIS_STATUS_SUCCESS) + { + pWAC_Req->RV = TRUE; + if (pWAC_Req->bReqType) + { + /* set command */ + switch (pWAC_Req->Command) + { + case WAC_CMD_ADD: + WAC_CopyVendorInfo(pAd, pWAC_Req, pEasyInfo); + break; + case WAC_CMD_DEL: +#ifdef CONFIG_STA_SUPPORT + if (pWAC_Req->FrameType == WAC_CMD_FOR_PROBE_REQ) + { + WAC_FREE_VENDOR_INFO(pEasyInfo->pVendorInfoForProbeReq, &pEasyInfo->VendorInfoForProbeReqLen); + } +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + if (pWAC_Req->FrameType == WAC_CMD_FOR_PROBE_RSP) + { + WAC_FREE_VENDOR_INFO(pEasyInfo->pVendorInfoForProbeRsp, &pEasyInfo->VendorInfoForProbeRspLen); + } + if (pWAC_Req->FrameType == WAC_CMD_FOR_BEACON) + { + WAC_FREE_VENDOR_INFO(pEasyInfo->pVendorInfoForBeacon, &pEasyInfo->VendorInfoForBeaconLen); + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); + } +#endif /* CONFIG_AP_SUPPORT */ + break; + default: + pWAC_Req->RV = FALSE; + DBGPRINT(RT_DEBUG_WARN, ("%s: Unknow command = 0x%x\n", + __FUNCTION__, pWAC_Req->Command)); + break; + } + if (pWAC_Req->RV) + { + Status = copy_to_user(wrq->u.data.pointer, pWAC_Req, wrq->u.data.length); + } + else + Status = -EFAULT; + } + else + { + /* get command */ + pWAC_Req->CurrentStatus = pEasyInfo->CurrentStatus; + Status = copy_to_user(wrq->u.data.pointer, pWAC_Req, wrq->u.data.length); + } + } + os_free_mem(NULL, pWAC_Req); + } + return Status; +} + +#ifdef CONFIG_AP_SUPPORT + +/* + Device Advertise Attribute + Field Size(Octets) Value + ID 1 0 + Length 1 1 + Status Code 1 0 Accepted + 1 Rejected because of invalid parameters + 2 Rejected because a WAC AP is unable to accommodate request + 3 Rejected because the RSS is not stronger than -25 dBm + 4 ~ 255 Reserved +*/ +/* Ralink Original +VOID WAC_GenStatusAttr( + IN PRTMP_ADAPTER pAd, + IN UCHAR ApIdx, + IN CHAR PeerRssi, + IN BOOLEAN bInvalidData, + OUT PUCHAR pData, + OUT PUCHAR pDataLen) +*/ +/* SAMSUNG DMC */ +VOID WAC_GenStatusAttr( + IN PRTMP_ADAPTER pAd, + IN UCHAR ApIdx, + IN CHAR PeerRssi, + IN BOOLEAN bInvalidData, + IN CHAR ThresholdOffset1, + OUT PUCHAR pData, + OUT PUCHAR pDataLen) +{ + PUCHAR pIE_Data = NULL; + + if (pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.bEnableWAC) + { + os_alloc_mem(NULL, &pIE_Data, 128); + if (pIE_Data) + { + /* SAMSUNG DMC*/ + NdisZeroMemory(pIE_Data, 128); + pIE_Data[0] = 0xDD; /* 17 = Leng. of Samsung OUI, Device Advertise Attr., Device Information Attr. & Status Attr. */ + pIE_Data[1] = SAMSUNG_OUI_LEN + DEVICE_ADVERTISE_ATTRIBUTE_LEN + DEVICE_INFORMATION_ATTRIBUTE_LEN + STATUS_ATTRIBUTE_LEN; + NdisMoveMemory(pIE_Data+2, SAMSUNG_OUI, 3); + pIE_Data[5] = SAMSUNG_OUI_TYPE; + pIE_Data[6] = WAC_DEVICE_ADVERTISE_ID; + pIE_Data[7] = 1; + if (pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.bEnableWAC) + pIE_Data[8] = 1; + else + pIE_Data[8] = 0; + pIE_Data[9] = WAC_DEVICE_INFORMATION_ID; /* 3 */ + pIE_Data[10] = DEVICE_INFORMATION_ATTRIBUTE_LEN - 2; /* 5 */ + pIE_Data[11] = THRESHOLD_OFFSET1; /* 0, Threshold Offset1 */ + pIE_Data[12] = THRESHOLD_OFFSET2; /* 0, Threshold Offset2 */ + pIE_Data[13] = EXTERNAL_ANTENNA; /* 1, Antenna Type => External */ + pIE_Data[14] = DEVICE_TYPE_TV; /* 0, Device Type */ + pIE_Data[15] = DEVICE_MODEL_TV; /* 0, Device Model */ + pIE_Data[16] = WAC_STATUS_ID; + pIE_Data[17] = 1; + if (bInvalidData) + { + pIE_Data[18] = 1; + pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.CurrentStatus = OFC_FAILED_INVALID_PARAM; + } + else + { + #ifdef WSC_AP_SUPPORT + PWSC_CTRL pWscCtrl = &pAd->ApCfg.MBSSID[ApIdx].WscControl; + if (pWscCtrl->EapMsgRunning || + (pWscCtrl->WscConfMode & WSC_REGISTRAR) == FALSE || + pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.bEnableWAC == FALSE) + { + DBGPRINT(RT_DEBUG_WARN, ("%s: EapMsgRunning = %d\n", __FUNCTION__, + pWscCtrl->EapMsgRunning)); + pIE_Data[18] = 2; + pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.CurrentStatus = OFC_FAILED_REJECT; + } + else + #endif // WSC_AP_SUPPORT // + { + /* + Ralink Original + if (PeerRssi < -25) + */ + /* SAMSUNG DMC */ + if (PeerRssi + ThresholdOffset1 < RSSI_THRESHOLD) + { + DBGPRINT(RT_DEBUG_WARN, ("%s: PeerRssi = %d\n", __FUNCTION__, PeerRssi)); + pIE_Data[18] = 3; + pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.CurrentStatus = OFC_FAILED_LOW_RSSI; + } + else + pIE_Data[18] = 0; + } + } + /* 19 = 2 + Leng. of Samsung OUI, Device Advertise Attr., Device Information Attr., & Status Attr. */ + *pDataLen = 2 + SAMSUNG_OUI_LEN + DEVICE_ADVERTISE_ATTRIBUTE_LEN + DEVICE_INFORMATION_ATTRIBUTE_LEN + STATUS_ATTRIBUTE_LEN; + NdisMoveMemory(pData, pIE_Data, *pDataLen); + os_free_mem(NULL, pIE_Data); + } + } +} + +/* Ralink Original +BOOLEAN WAC_PeerProbeReqSanity( + IN PRTMP_ADAPTER pAd, + IN UCHAR ApIdx, + IN VOID *Msg, + IN ULONG MsgLen, + OUT BOOLEAN *pPeerWAC, + OUT UCHAR *pParseResult) +*/ +/* SAMSUNG DMC */ +BOOLEAN WAC_PeerProbeReqSanity( + IN PRTMP_ADAPTER pAd, + IN UCHAR ApIdx, + IN VOID *Msg, + IN ULONG MsgLen, + OUT BOOLEAN *pPeerWAC, + OUT CHAR *pThresholdOffset1, + OUT UCHAR *pPeerDeviceType, + OUT UCHAR *pParseResult) +{ + PFRAME_802_11 Fr = (PFRAME_802_11)Msg; + UCHAR *Ptr; + UCHAR eid =0, eid_len = 0, *eid_data; + UCHAR oui_type = 0; + UINT total_ie_len = 0; + BOOLEAN bWAC_Enable= FALSE; + BOOLEAN bFoundSamsungWAC_OUI = FALSE; + + Ptr = Fr->Octet; + eid = Ptr[0]; + eid_len = Ptr[1]; + total_ie_len = eid_len + 2; + eid_data = Ptr+2; + + /* 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; + + if (NdisEqualMemory(eid_data, SAMSUNG_OUI, 3)) + { + oui_type = eid_data[3]; + DBGPRINT(RT_DEBUG_TRACE, ("%s: Samsung OUI Type = 0x%02X\n", __FUNCTION__, oui_type)); + if (oui_type == SAMSUNG_OUI_TYPE) + { + CHAR device_info[5]; + bFoundSamsungWAC_OUI = TRUE; + + if (WAC_ParseAttr(WAC_DEVICE_ADVERTISE_ID, eid_data+4, eid_len-4, &bWAC_Enable, 1)) + { + *pParseResult |= 0x01; + if (bWAC_Enable) + *pPeerWAC = TRUE; + } + + if (bWAC_Enable) + { + /* SAMSUNG DMC */ + DBGPRINT(RT_DEBUG_TRACE, ("%s: WAC_DEVICE_INFO_ID Parsing...\n", __FUNCTION__)); + + if (WAC_ParseAttr(WAC_DEVICE_INFORMATION_ID, eid_data+4, eid_len-4, &device_info[0], 5)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: WAC Device Information: %d, %d, %d, %d, %d\n", __FUNCTION__, device_info[0], device_info[1], device_info[2], device_info[3], device_info[4])); + *pThresholdOffset1 = (CHAR) device_info[0]; + *pPeerDeviceType = (CHAR) device_info[3]; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: WAC Device Information Parsing Error \n", __FUNCTION__)); + } + + if (WAC_ParseAttr(WAC_AUTO_PROVISION_ID, + eid_data+4, + eid_len-4, + pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.WpsPinCode, + 8)) + { +#ifdef WSC_INCLUDED + PWSC_CTRL pWpsCtrl = &pAd->ApCfg.MBSSID[ApIdx].WscControl; + UCHAR PinStr[9]; +#endif /* WSC_INCLUDED */ + *pParseResult |= 0x02; +#ifdef WSC_INCLUDED + NdisMoveMemory(&PinStr[0], &pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.WpsPinCode[0], 8); + PinStr[8] = '\0'; + /* + To make sure of doing WPS process with WPS Client by PIN method + */ + pWpsCtrl->WscMode = WSC_PIN_MODE; + WscGetRegDataPIN(pAd, simple_strtol(PinStr, 0, 10), pWpsCtrl); + DBGPRINT(RT_DEBUG_TRACE, ("%s: WscPinCode = %08u\n", __FUNCTION__, pWpsCtrl->WscPinCode)); +#endif /* WSC_INCLUDED */ + } + + } + else + *pPeerWAC = FALSE; + } + 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); + } + return bFoundSamsungWAC_OUI; +} + +VOID WAC_MaintainPeerList( + IN PLIST_HEADER pWscEnList) +{ + PWSC_PEER_ENTRY pPeerEntry = NULL; + PLIST_ENTRY pListEntry = NULL, pTempListEntry = NULL; + ULONG now_time = 0; + + NdisGetSystemUpTime(&now_time); + pListEntry = pWscEnList->pHead; + pPeerEntry = (PWSC_PEER_ENTRY)pListEntry; + + while (pPeerEntry != NULL) + { + if (RTMP_TIME_AFTER(now_time, pPeerEntry->receive_time + (5 * OS_HZ))) + { + pTempListEntry = pListEntry->pNext; + delEntryList(pWscEnList, pListEntry); + os_free_mem(NULL, pPeerEntry); + pListEntry = pTempListEntry; + } + else + pListEntry = pListEntry->pNext; + pPeerEntry = (PWSC_PEER_ENTRY)pListEntry; + } + + return; +} + +VOID WAC_CheckWACEntry( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry) +{ + if (pEntry == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: pEntry is NULL!!\n", __FUNCTION__)); + return; + } + + if (pAd->ApCfg.MBSSID[pEntry->apidx].EasyConfigInfo.bEnableWAC) + { +#ifdef WAC_QOS_PRIORITY + PWSC_PEER_ENTRY pWACPeerEntry = NULL; + PLIST_HEADER pWacFroceEnList = &pAd->ApCfg.MBSSID[pEntry->apidx].EasyConfigInfo.WAC_ForcePriorityList; +#endif /* WAC_QOS_PRIORITY */ + PLIST_HEADER pWscEnList = &pAd->ApCfg.MBSSID[pEntry->apidx].EasyConfigInfo.WAC_PeerList; + + RTMP_SEM_LOCK(&pAd->ApCfg.MBSSID[pEntry->apidx].EasyConfigInfo.WAC_PeerListSemLock); + WAC_MaintainPeerList(pWscEnList); + if (WscFindPeerEntry(pWscEnList, pEntry->Addr)) + { + pEntry->bRaAutoWpsCapable = TRUE; + pEntry->bSamsungAutoWpsCapable = TRUE; + } + RTMP_SEM_UNLOCK(&pAd->ApCfg.MBSSID[pEntry->apidx].EasyConfigInfo.WAC_PeerListSemLock); + +#ifdef WAC_QOS_PRIORITY + RTMP_SEM_LOCK(&pAd->ApCfg.MBSSID[pEntry->apidx].EasyConfigInfo.WAC_ForcePriorityListSemLock); + + pWACPeerEntry = WscFindPeerEntry(pWacFroceEnList, pEntry->Addr); + if (pWACPeerEntry) + { + if ((pWACPeerEntry->device_type == WAC_DEVICE_TYPE_TV) || + (pWACPeerEntry->device_type == WAC_DEVICE_TYPE_BD)) + pEntry->bSamsungForcePriority = TRUE; + } + RTMP_SEM_UNLOCK(&pAd->ApCfg.MBSSID[pEntry->apidx].EasyConfigInfo.WAC_ForcePriorityListSemLock); +#endif /* WAC_QOS_PRIORITY */ + } +} + +VOID WAC_PeerProbeReq( + IN PRTMP_ADAPTER pAd, + IN UCHAR ApIdx, + IN MLME_QUEUE_ELEM *Elem, + IN UCHAR *Addr2, + INOUT UCHAR *pBuf, + INOUT ULONG *pFrameLen) +{ + PUCHAR pWAC_IE = NULL; + UCHAR WAC_IELen = 0; + ULONG TmpWACLen = 0; + BOOLEAN bPeerWAC = FALSE; + /* SAMSUNG DMC */ + CHAR Threshold_Offset1 = 0; + UCHAR ParseResult = 0; + UCHAR PeerDeviceType = 0xff; + + if (WAC_PeerProbeReqSanity(pAd, ApIdx, Elem->Msg, Elem->MsgLen, &bPeerWAC, &Threshold_Offset1, &PeerDeviceType, &ParseResult)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: Found Samsung WAC OUI - bPeerWAC = %d, ParseResult = 0x%x\n", __FUNCTION__, bPeerWAC, ParseResult)); + os_alloc_mem(NULL, &pWAC_IE, 128); + if (pWAC_IE) + { + ULONG WACTmpLen = 0; + + /* + Peer is WAC enable + */ + if (((ParseResult & 0x01) == TRUE) && (bPeerWAC == TRUE)) + { +#ifdef WAC_QOS_PRIORITY + PLIST_HEADER pWacForceList = &pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.WAC_ForcePriorityList; +#endif /* WAC_QOS_PRIORITY */ + PFRAME_802_11 p80211Frame = (PFRAME_802_11)Elem->Msg; + CHAR PeerRssi = 0; + PeerRssi = RTMPMaxRssi(pAd, + ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), + ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), + ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); + if (MAC_ADDR_EQUAL(p80211Frame->Hdr.Addr3, pAd->ApCfg.MBSSID[ApIdx].Bssid) && (ParseResult & 0x02)) + { +#ifdef WSC_AP_SUPPORT + PWSC_CTRL pWscCtrl = &pAd->ApCfg.MBSSID[ApIdx].WscControl; + if (NdisEqualMemory(pWscCtrl->EntryAddr, ZERO_MAC_ADDR, MAC_ADDR_LEN) || + NdisEqualMemory(pWscCtrl->EntryAddr, p80211Frame->Hdr.Addr2, MAC_ADDR_LEN)) + { + pWscCtrl->EapMsgRunning = FALSE; + } +#endif /* WSC_AP_SUPPORT */ + + /* + Ralink Original + WAC_GenStatusAttr(pAd, ApIdx, PeerRssi, FALSE, pWAC_IE, &WAC_IELen); + */ + /* SAMSUNG DMC */ + WAC_GenStatusAttr(pAd, ApIdx, PeerRssi, FALSE, Threshold_Offset1, pWAC_IE, &WAC_IELen); + if ((ParseResult & 0x02) && (pWAC_IE[11] == 0)) + { + PLIST_HEADER pWscEnList = &pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.WAC_PeerList; + RTMP_SEM_LOCK(&pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.WAC_PeerListSemLock); + WscInsertPeerEntryByMAC(pWscEnList, Addr2); + RTMP_SEM_UNLOCK(&pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.WAC_PeerListSemLock); + } + } + else + WAC_GenDeviceAdvertiseAttr(pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.bEnableWAC, pWAC_IE, &WAC_IELen); +#ifdef WAC_QOS_PRIORITY + RTMP_SEM_LOCK(&pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.WAC_ForcePriorityListSemLock); + WAC_InsertForcePriorityEntryByMAC(pWacForceList, Addr2, PeerDeviceType); + RTMP_SEM_UNLOCK(&pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.WAC_ForcePriorityListSemLock); +#endif /* WAC_QOS_PRIORITY */ + } + else + WAC_GenDeviceAdvertiseAttr(pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.bEnableWAC, pWAC_IE, &WAC_IELen); + + MakeOutgoingFrame(pBuf+(*pFrameLen), &WACTmpLen, + WAC_IELen, pWAC_IE, + END_OF_ARGS); + (*pFrameLen) += WACTmpLen; + os_free_mem(NULL, pWAC_IE); + } + } + else + { + os_alloc_mem(NULL, &pWAC_IE, 128); + if (pWAC_IE) + { + WAC_GenDeviceAdvertiseAttr(pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.bEnableWAC, pWAC_IE, &WAC_IELen); + MakeOutgoingFrame(pBuf+(*pFrameLen), &TmpWACLen, + WAC_IELen, pWAC_IE, + END_OF_ARGS); + (*pFrameLen) += TmpWACLen; + os_free_mem(NULL, pWAC_IE); + } + } +} +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +/* + Device Advertise Attribute + Field Size(Octets) Value + ID 1 0 + Length 1 1 + WAC On/Off 1 0x01/0x00 WAC On(0x01), WAC Off(0x00) +*/ +VOID WAC_GenUicastProbeReqAttr( + IN BOOLEAN bEnableWAC, + IN PUCHAR pPIN, + OUT PUCHAR pData, + OUT PUCHAR pDataLen) +{ + PUCHAR pIE_Data = NULL; + + os_alloc_mem(NULL, &pIE_Data, 128); + + if (pIE_Data == NULL) + { + DBGPRINT(RT_DEBUG_WARN, ("%s: pIE_Data alloc fail !!\n", __FUNCTION__)); + return; + } + + if (pIE_Data) + { +/* Ralink Original + NdisZeroMemory(pIE_Data, 128); + pIE_Data[0] = 0xDD; + if (bEnableWAC) + pIE_Data[1] = 17; + else + pIE_Data[1] = 7; + NdisMoveMemory(pIE_Data+2, SAMSUNG_OUI, 3); + pIE_Data[5] = SAMSUNG_OUI_TYPE; + pIE_Data[6] = WAC_DEVICE_ADVERTISE_ID; + pIE_Data[7] = 1; + if (bEnableWAC) + pIE_Data[8] = 1; + else + pIE_Data[8] = 0; + if (bEnableWAC) + { + pIE_Data[9] = WAC_AUTO_PROVISION_ID; + pIE_Data[10] = 8; + NdisMoveMemory(pIE_Data+11, pPIN, 8); + *pDataLen = 19; + } + else + *pDataLen = 9; + NdisMoveMemory(pData, pIE_Data, *pDataLen); + os_free_mem(NULL, pIE_Data); +*/ + /* SAMSUNG DMC */ + NdisZeroMemory(pIE_Data, 128); + pIE_Data[0] = 0xDD; + if (bEnableWAC) + /* 24 = Leng. of Samsung OUI, Device Advertise Attr., Device Information Attr. & Auto Provisioning Attr. */ + pIE_Data[1] = SAMSUNG_OUI_LEN + DEVICE_ADVERTISE_ATTRIBUTE_LEN + DEVICE_INFORMATION_ATTRIBUTE_LEN + AUTO_PROVISIONING_ATTRIBUTE_LEN; + else + /* 14 = Leng. of Samsung OUI, Device Advertise Attr. & Device Information Attr. */ + pIE_Data[1] = SAMSUNG_OUI_LEN + DEVICE_ADVERTISE_ATTRIBUTE_LEN + DEVICE_INFORMATION_ATTRIBUTE_LEN; + NdisMoveMemory(pIE_Data+2, SAMSUNG_OUI, 3); + pIE_Data[5] = SAMSUNG_OUI_TYPE; + pIE_Data[6] = WAC_DEVICE_ADVERTISE_ID; + pIE_Data[7] = 1; + if (bEnableWAC) + pIE_Data[8] = 1; + else + pIE_Data[8] = 0; + pIE_Data[9] = WAC_DEVICE_INFORMATION_ID; /* 3 */ + pIE_Data[10] = DEVICE_INFORMATION_ATTRIBUTE_LEN - 2; /* 5 */ + pIE_Data[11] = THRESHOLD_OFFSET1; /* 0, Threshold Offset1 */ + pIE_Data[12] = THRESHOLD_OFFSET2; /* 0, Threshold Offset2 */ + pIE_Data[13] = EXTERNAL_ANTENNA; /* 1, Antenna Type => External */ + pIE_Data[14] = DEVICE_TYPE_TV; /* 0, Device Type */ + pIE_Data[15] = DEVICE_MODEL_TV; /* 0, Device Model */ + if (bEnableWAC) + { + pIE_Data[16] = WAC_AUTO_PROVISION_ID; + pIE_Data[17] = 8; + NdisMoveMemory(pIE_Data+18, pPIN, 8); + /* 26 = 2 + Leng. of Samsung OUI, Device Advertise Attr., Device Information Attr. & Auto Provisioning Attr. */ + *pDataLen = 2 + SAMSUNG_OUI_LEN + DEVICE_ADVERTISE_ATTRIBUTE_LEN + DEVICE_INFORMATION_ATTRIBUTE_LEN + AUTO_PROVISIONING_ATTRIBUTE_LEN; + } + else + { + /* 16 = 2 + Leng. of Samsung OUI, Device Advertise Attr. & Device Information Attr. */ + *pDataLen = 2 + SAMSUNG_OUI_LEN + DEVICE_ADVERTISE_ATTRIBUTE_LEN + DEVICE_INFORMATION_ATTRIBUTE_LEN; + } + NdisMoveMemory(pData, pIE_Data, *pDataLen); + os_free_mem(NULL, pIE_Data); + } +} + +UCHAR WAC_SearchSamsungWACAP( + IN PRTMP_ADAPTER pAd) +{ + INT i = 0, Len = 0; + PBSS_ENTRY pInBss; + UCHAR Count = 0; + PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl; + PBEACON_EID_STRUCT pEid = NULL; + UCHAR *pData; + UUID_BSSID_CH_INFO apCandiList[8]; + UUID_BSSID_CH_INFO *pApCandEntry; + + /* Ralink Original + CHAR RssiThreshold = -25; +*/ + /* + SAMSUNG DMC + - does not check RSSI tightly in device driver. + */ + CHAR RssiThreshold = -100; + + NdisZeroMemory(&apCandiList[0], sizeof(apCandiList)); + pAd->StaCfg.EasyConfigInfo.CurrentStatus = OFC_FAILED_NO_WAC_AP; + for (i = 0; i < pAd->ScanTab.BssNr; i++) + { + /* BSS entry for VarIE processing */ + pInBss = (PBSS_ENTRY) &pAd->ScanTab.BssEntry[i]; + + if ((pInBss->WpsAP & 0x04) && (Count < 8)) + { + if (pInBss->Rssi >= RssiThreshold) + { + pApCandEntry = &apCandiList[Count]; + NdisZeroMemory(pApCandEntry->Ssid, MAX_LEN_OF_SSID); + NdisZeroMemory(pApCandEntry->Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pApCandEntry->MacAddr, MAC_ADDR_LEN); + NdisZeroMemory(pApCandEntry->Uuid, 16); + + pApCandEntry->Channel = pInBss->Channel; + pApCandEntry->SsidLen = pInBss->SsidLen; + NdisMoveMemory(pApCandEntry->Ssid, pInBss->Ssid, pInBss->SsidLen); + NdisMoveMemory(pApCandEntry->Bssid, pInBss->Bssid, MAC_ADDR_LEN); + NdisMoveMemory(pApCandEntry->MacAddr, pInBss->MacAddr, MAC_ADDR_LEN); + Count++; + } + else + { + pAd->StaCfg.EasyConfigInfo.CurrentStatus = OFC_FAILED_LOW_RSSI; + DBGPRINT(RT_DEBUG_WARN, ("%s: pInBss->Rssi = %d\n", __FUNCTION__, pInBss->Rssi)); + } + } + } + + if (Count != 0) + { + NdisZeroMemory(&pWpsCtrl->WscSsid, sizeof(NDIS_802_11_SSID)); + NdisZeroMemory(pWpsCtrl->WscBssid, MAC_ADDR_LEN); + NdisZeroMemory(pWpsCtrl->WscPeerMAC, MAC_ADDR_LEN); + + pWpsCtrl->WscSsid.SsidLength = apCandiList[0].SsidLen; + NdisMoveMemory(pWpsCtrl->WscSsid.Ssid, apCandiList[0].Ssid, apCandiList[0].SsidLen); + NdisMoveMemory(pWpsCtrl->WscBssid, apCandiList[0].Bssid, MAC_ADDR_LEN); + NdisMoveMemory(pWpsCtrl->WscPeerMAC, apCandiList[0].MacAddr, MAC_ADDR_LEN); + pAd->MlmeAux.Channel = apCandiList[0].Channel; + } + + return Count; +} + +BOOLEAN WAC_FindWACAP( + IN PRTMP_ADAPTER pAd) +{ + UCHAR ApCount = 0; + PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl; + ApCount = WAC_SearchSamsungWACAP(pAd); + pAd->StaCfg.EasyConfigInfo.bWACAP = FALSE; + if (ApCount != 0) + { + /* + Update Reconnect Ssid, that user desired to connect. + */ + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pWpsCtrl->WscSsid.Ssid, pWpsCtrl->WscSsid.SsidLength); + pAd->MlmeAux.AutoReconnectSsidLen = pWpsCtrl->WscSsid.SsidLength; + + pAd->bConfigChanged = TRUE; + + // Turn off WSC state matchine + WscStop(pAd, +#ifdef CONFIG_AP_SUPPORT + FALSE, +#endif /* CONFIG_AP_SUPPORT */ + pWpsCtrl); + + // Set WSC state to WSC_STATE_INIT + pWpsCtrl->WscState = WSC_STATE_INIT; + pWpsCtrl->WscStatus = STATUS_WSC_SCAN_AP; + + // Init Registrar pair structures + WscInitRegistrarPair(pAd, pWpsCtrl, BSS0); + + pAd->StaCfg.BssType = BSS_INFRA; + pWpsCtrl->WscConfStatus = WSC_SCSTATE_UNCONFIGURED; + pWpsCtrl->WscConfMode = WSC_ENROLLEE; + pWpsCtrl->WscMode = 1; + pAd->StaCfg.EasyConfigInfo.bDoAutoWps = TRUE; + pAd->StaCfg.EasyConfigInfo.bWACAP = TRUE; + pAd->StaCfg.EasyConfigInfo.CurrentStatus = OFC_PROCEED_SECOND_PHASE; + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID, + MAC_ADDR_LEN, + pWpsCtrl->WscBssid, 0); + // call Mlme handler to execute it + RTMP_MLME_HANDLER(pAd); + return TRUE; + } + return FALSE; +} +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef WAC_QOS_PRIORITY +VOID WAC_InsertForcePriorityEntryByMAC( + IN PLIST_HEADER pWscEnList, + IN PUCHAR pMacAddr, + IN UCHAR DeviceType) +{ + PWSC_PEER_ENTRY pWscPeer = NULL; + + pWscPeer = WscFindPeerEntry(pWscEnList, pMacAddr); + if (pWscPeer) + { + NdisGetSystemUpTime(&pWscPeer->receive_time); + pWscPeer->device_type = DeviceType; + } + else + { + os_alloc_mem(NULL, &pWscPeer, WSC_PEER_ENTRY_SIZE); + if (pWscPeer) + { + NdisZeroMemory(pWscPeer, WSC_PEER_ENTRY_SIZE); + NdisMoveMemory(pWscPeer->mac_addr, pMacAddr, MAC_ADDR_LEN); + NdisGetSystemUpTime(&pWscPeer->receive_time); + pWscPeer->device_type = DeviceType; + insertTailList(pWscEnList, (PLIST_ENTRY)pWscPeer); + } + ASSERT(pWscPeer != NULL); + } +} +#endif /* WAC_QOS_PRIORITY */ +#endif /* CONFIG_AP_SUPPORT */ +#endif /* WAC_SUPPORT */ + diff --git a/mt7620/src/common/ba_action.c b/mt7620/src/common/ba_action.c new file mode 100644 index 0000000..b07bdf9 --- /dev/null +++ b/mt7620/src/common/ba_action.c @@ -0,0 +1,2380 @@ +#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( + IN PRTMP_ADAPTER pAd, + OUT USHORT *Idx); + +BA_REC_ENTRY *BATableAllocRecEntry( + IN PRTMP_ADAPTER pAd, + OUT 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; + + + MaxPeerRxSize = (((1 << (pEntryPeer->MaxRAmpduFactor + 3)) * 10) / 16) -1; + +#ifdef RT3883 + if (IS_RT3883(pAd)) + { + MaxSize = 31; /* RT3883 */ + + if ((pEntryPeer->HTCapability.MCSSet[2] != 0xff) && + (!CLIENT_STATUS_TEST_FLAG(pEntryPeer, fCLIENT_STATUS_RALINK_CHIPSET))) + MaxSize = 15; + } + else +#endif /* RT3883 */ +#ifdef RT6352 + if (IS_RT6352(pAd)) + { + MaxSize = 21; + } + else +#endif /* RT6352 */ + if (pAd->MACVersion >= RALINK_2883_VERSION) + { + if (pAd->MACVersion >= RALINK_3070_VERSION) + { + if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled) + MaxSize = 7; /* for non-open mode*/ + else + MaxSize = 13; + } + else + MaxSize = 31; + } + else if (pAd->MACVersion >= RALINK_2880E_VERSION) /* 2880 E*/ + { + if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled) + MaxSize = 7; /* for non-open mode*/ + else + MaxSize = 13; + } + else + MaxSize = 7; + +#ifdef CONFIG_AP_SUPPORT +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + + + DBGPRINT(RT_DEBUG_TRACE, ("ba>WinSize=%d, MaxSize=%d, MaxPeerRxSize=%d\n", + *pWinSize, MaxSize, MaxPeerRxSize)); + + if (!CLIENT_STATUS_TEST_FLAG(pEntryPeer, fCLIENT_STATUS_RALINK_CHIPSET)) + 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(IN PRTMP_ADAPTER pAd, + IN 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 +#ifdef 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(PRTMP_ADAPTER pAd) +{ + BA_TABLE *Tab; + PBA_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(PRTMP_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) + { +/* blk_count++; */ + /* 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); +/* blk_count--; */ + 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); + /* 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); + /* 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( + IN PRTMP_ADAPTER pAd, + PBA_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 PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR TID, + IN USHORT TimeOut, + IN ULONG DelayTime, + IN BOOLEAN isForced) + +{ + /*MLME_ADDBA_REQ_STRUCT AddbaReq;*/ + BA_ORI_ENTRY *pBAEntry = NULL; + USHORT Idx; + BOOLEAN Cancelled; + + 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,("ADDBA - MlmeADDBAAction() allocate BA session failed \n")); + return; + } + } + else + { + pBAEntry =&pAd->BATable.BAOriEntry[Idx]; + } + + if (pBAEntry->ORI_BA_Status >= Originator_WaitRes) + { + return; + } + + pEntry->BAOriWcidArray[TID] = Idx; + + /* Initialize BA session */ + pBAEntry->ORI_BA_Status = Originator_WaitRes; + pBAEntry->Wcid = pEntry->Aid; + pBAEntry->BAWinSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit; + 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 PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN PFRAME_ADDBA_RSP pFrame) +{ + BA_ORI_ENTRY *pBAEntry = NULL; + BOOLEAN Cancelled; + UCHAR TID; + USHORT Idx; + PUCHAR pOutBuffer2 = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + FRAME_BAR FrameBar; + UCHAR MaxPeerBufSize; +#ifdef CONFIG_AP_SUPPORT + UCHAR apidx; +#endif /* CONFIG_AP_SUPPORT */ + + 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->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, BAWinSize = %d, TimeOut = %ld\n", __FUNCTION__, pEntry->TXBAbitmap, + 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; + } + +#ifdef P2P_SUPPORT + BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->MacTab.Content[pBAEntry->Wcid].HdrAddr2); +#else +#ifdef MESH_SUPPORT + if (IS_ENTRY_MESH(&pAd->MacTab.Content[pBAEntry->Wcid])) + { + BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->MeshTab.CurrentAddress); + } + else +#endif /* MESH_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(&pAd->MacTab.Content[pBAEntry->Wcid])) + { +#ifdef MAC_REPEATER_SUPPORT + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; +#endif /* MAC_REPEATER_SUPPORT */ + + apidx = pAd->MacTab.Content[pBAEntry->Wcid].MatchAPCLITabIdx; +#ifdef MAC_REPEATER_SUPPORT + if (pEntry && pEntry->bReptCli) + BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->ApCfg.ApCliTab[apidx].RepeaterCli[pEntry->MatchReptCliIdx].CurrentAddress); + else +#endif /* MAC_REPEATER_SUPPORT */ + BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress); + } + else +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (IS_ENTRY_WDS(&pAd->MacTab.Content[pBAEntry->Wcid])) + { + apidx = pAd->MacTab.Content[pBAEntry->Wcid].MatchWDSTabIdx; + BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->ApCfg.MBSSID[MAIN_MBSSID].Bssid); + } + else +#endif /* WDS_SUPPORT */ + { + apidx = pAd->MacTab.Content[pBAEntry->Wcid].apidx; + BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->ApCfg.MBSSID[apidx].Bssid); + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->CurrentAddress); +#endif /* CONFIG_STA_SUPPORT */ +#endif /* P2P_SUPPORT */ + + 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 PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN PFRAME_ADDBA_REQ pFrame) +{ + BA_REC_ENTRY *pBAEntry = NULL; + BOOLEAN Status = TRUE; + BOOLEAN Cancelled; + USHORT Idx; + UCHAR TID; + UCHAR BAWinSize; + /*UINT32 Value;*/ + /*UINT offset;*/ + + + 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->Aid; + 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<Aid, TID); + + DBGPRINT(RT_DEBUG_TRACE,("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n", + pEntry->Aid, 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( + IN PRTMP_ADAPTER pAd, + OUT 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( + IN PRTMP_ADAPTER pAd, + OUT 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( + IN PRTMP_ADAPTER pAd, + IN 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]; + + 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)); + + + NdisAcquireSpinLock(&pAd->BATabLock); + 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( + IN PRTMP_ADAPTER pAd, + IN 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]; + + if (pBAEntry->REC_BA_Status != Recipient_NONE) + { + pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; + pEntry->BARecWcidArray[pBAEntry->TID] = 0; + + NdisAcquireSpinLock(&pAd->BATabLock); + + ASSERT(pAd->BATable.numAsRecipient != 0); + + pAd->BATable.numAsRecipient -= 1; + + pBAEntry->REC_BA_Status = Recipient_NONE; + NdisReleaseSpinLock(&pAd->BATabLock); + } +} + + +VOID BAOriSessionTearDown( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR TID, + IN BOOLEAN bPassive, + IN BOOLEAN bForceSend) +{ + ULONG Idx = 0; + BA_ORI_ENTRY *pBAEntry; + BOOLEAN Cancelled; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + if (Wcid >= MaxWcidNum) + { + 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; /* = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);*/ + 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); +/* kfree(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 = %ld, 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; /* = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);*/ + 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); +/* kfree(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; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + if (Wcid >= MaxWcidNum) + { + 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; + /*ULONG offset; */ + /*UINT32 VALUE;*/ + + RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled); + + + /* 1. Send DELBA Action Frame*/ + if (bPassive == FALSE) + { + 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 != 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); +/* kfree(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( + IN OUT PRTMP_ADAPTER pAd, + IN 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 +#ifdef P2P_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && IS_ENTRY_CLIENT(pEntry) && IS_P2P_ENTRY_NONE(pEntry)) +#else + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) +#endif /* P2P_SUPPORT */ + { + 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 = (UCHAR)(pEntry->Aid); + 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( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + /* 7.4.4.1*/ + /*ULONG Idx;*/ + UCHAR Status = 1; + UCHAR pAddr[6]; + FRAME_ADDBA_RSP ADDframe; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + PFRAME_ADDBA_REQ pAddreqFrame = NULL; + /*UCHAR BufSize;*/ + ULONG FrameLen; + PULONG ptemp; + PMAC_TABLE_ENTRY pMacEntry; +#ifdef CONFIG_AP_SUPPORT + INT apidx; +#endif /* CONFIG_AP_SUPPORT */ + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> (Wcid = %d)\n", __FUNCTION__, Elem->Wcid)); + + /*hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen);*/ +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + /*ADDBA Request from unknown peer, ignore this.*/ + if (Elem->Wcid >= MaxWcidNum) + return; + + pMacEntry = &pAd->MacTab.Content[Elem->Wcid]; + DBGPRINT(RT_DEBUG_TRACE,("BA - PeerAddBAReqAction----> \n")); + ptemp = (PULONG)Elem->Msg; + /*DBGPRINT_RAW(RT_DEBUG_EMU, ("%08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x\n", *(ptemp), *(ptemp+1), *(ptemp+2), *(ptemp+3), *(ptemp+4), *(ptemp+5), *(ptemp+6), *(ptemp+7), *(ptemp+8)));*/ + + 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(&pAd->MacTab.Content[Elem->Wcid])) + ASSERT(pAd->MacTab.Content[Elem->Wcid].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.*/ +#ifdef P2P_SUPPORT + if (pMacEntry) + { +#ifdef CONFIG_STA_SUPPORT + if (ADHOC_ON(pAd) +#ifdef QOS_DLS_SUPPORT + || (IS_ENTRY_DLS(&pAd->MacTab.Content[Elem->Wcid])) +#endif /* QOS_DLS_SUPPORT */ +#ifdef DOT11Z_TDLS_SUPPORT + || (IS_ENTRY_TDLS(&pAd->MacTab.Content[Elem->Wcid])) +#endif /* DOT11Z_TDLS_SUPPORT */ + ) + { + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + } + else +#endif /* CONFIG_STA_SUPPORT */ + { + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pMacEntry->HdrAddr2, pMacEntry->HdrAddr3); + } + } +#else +#ifdef MESH_SUPPORT + if (IS_ENTRY_MESH(&pAd->MacTab.Content[Elem->Wcid])) + { + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->MeshTab.CurrentAddress, pAddr); + } + else +#endif /* MESH_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(&pAd->MacTab.Content[Elem->Wcid])) + { +#ifdef MAC_REPEATER_SUPPORT + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[Elem->Wcid]; +#endif /* MAC_REPEATER_SUPPORT */ + + apidx = pAd->MacTab.Content[Elem->Wcid].MatchAPCLITabIdx; +#ifdef MAC_REPEATER_SUPPORT + if (pEntry && pEntry->bReptCli) + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->ApCfg.ApCliTab[apidx].RepeaterCli[pEntry->MatchReptCliIdx].CurrentAddress, pAddr); + else +#endif /* MAC_REPEATER_SUPPORT */ + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress, pAddr); + } + else +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (IS_ENTRY_WDS(&pAd->MacTab.Content[Elem->Wcid])) + { + apidx = pAd->MacTab.Content[Elem->Wcid].MatchWDSTabIdx; + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->ApCfg.MBSSID[MAIN_MBSSID].Bssid, pAddr); + } + else +#endif /* WDS_SUPPORT */ + { + apidx = pAd->MacTab.Content[Elem->Wcid].apidx; + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].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(&pAd->MacTab.Content[Elem->Wcid])) +#endif /* QOS_DLS_SUPPORT */ +#ifdef DOT11Z_TDLS_SUPPORT + || (IS_ENTRY_TDLS(&pAd->MacTab.Content[Elem->Wcid])) +#endif /* DOT11Z_TDLS_SUPPORT */ + ) + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + else + ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, 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; + ADDframe.BaParm.AMSDUSupported = 0; + 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( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + /*UCHAR Idx, i;*/ + /*PUCHAR pOutBuffer = NULL;*/ + PFRAME_ADDBA_RSP pFrame = NULL; + /*PBA_ORI_ENTRY pBAEntry;*/ + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + /*ADDBA Response from unknown peer, ignore this.*/ + if (Elem->Wcid >= MaxWcidNum) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __FUNCTION__, Elem->Wcid)); + + /*hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen);*/ + + if (PeerAddBARspActionSanity(pAd, 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) + +{ + /*UCHAR Idx;*/ + /*PUCHAR pOutBuffer = NULL;*/ + 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)) + { +#ifdef PEER_DELBA_TX_ADAPT + MAC_TABLE_ENTRY *pEntry = NULL; +#endif /* PEER_DELBA_TX_ADAPT */ + + pDelFrame = (PFRAME_DELBA_REQ)(&Elem->Msg[0]); + +#ifdef PEER_DELBA_TX_ADAPT + pEntry = &pAd->MacTab.Content[Elem->Wcid]; + + if ((pAd->CommonCfg.bBADecline == FALSE) && (pDelFrame->DelbaParm.TID == 0) + && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET))) + { + 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 PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN ULONG MsgLen, + IN PFRAME_BA_REQ pMsg) +{ + PFRAME_BA_REQ pFrame = pMsg; + /*PRTMP_REORDERBUF pBuffer;*/ + /*PRTMP_REORDERBUF pDmaBuf;*/ + PBA_REC_ENTRY pBAEntry; + /*BOOLEAN Result;*/ + ULONG Idx; + /*UCHAR NumRxPkt;*/ + UCHAR TID;/*, i;*/ + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + + 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 < MaxWcidNum) && (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 PSMP Action frame If PSMP mode switches. +*/ +VOID SendPSMPAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR Psmp) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + FRAME_PSMP_ACTION Frame; + ULONG FrameLen; +#ifdef CONFIG_AP_SUPPORT + UCHAR apidx; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef P2P_SUPPORT + PMAC_TABLE_ENTRY pEntry; +#endif /* P2P_SUPPORT */ + + 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; + } + +#ifdef P2P_SUPPORT + if (VALID_WCID(Wcid)) + { + pEntry = &pAd->MacTab.Content[Wcid]; + + if (pEntry) + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pEntry->HdrAddr2, pEntry->HdrAddr3); + } +#else +#ifdef MESH_SUPPORT + if (IS_ENTRY_MESH(&pAd->MacTab.Content[Wcid])) + { + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->MeshTab.CurrentAddress, pAd->MacTab.Content[Wcid].Addr); + } + else +#endif /* MESH_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(&pAd->MacTab.Content[Wcid])) + { +#ifdef MAC_REPEATER_SUPPORT + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[Wcid]; +#endif /* MAC_REPEATER_SUPPORT */ + + apidx = pAd->MacTab.Content[Wcid].MatchAPCLITabIdx; +#ifdef MAC_REPEATER_SUPPORT + if (pEntry && pEntry->bReptCli) + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->ApCfg.ApCliTab[apidx].RepeaterCli[pEntry->MatchReptCliIdx].CurrentAddress, pAd->MacTab.Content[Wcid].Addr); + else +#endif /* MAC_REPEATER_SUPPORT */ + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress, pAd->MacTab.Content[Wcid].Addr); + } + else +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (IS_ENTRY_WDS(&pAd->MacTab.Content[Wcid])) + { + apidx = pAd->MacTab.Content[Wcid].MatchWDSTabIdx; + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->ApCfg.MBSSID[MAIN_MBSSID].Bssid, pAd->MacTab.Content[Wcid].Addr); + } + else +#endif /* WDS_SUPPORT */ + { + apidx = pAd->MacTab.Content[Wcid].apidx; + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid); + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[Wcid].Addr); +#endif /* CONFIG_STA_SUPPORT */ +#endif /* P2P_SUPPORT */ + + Frame.Category = CATEGORY_HT; + Frame.Action = SMPS_ACTION; + switch (Psmp) + { + case MMPS_ENABLE: + Frame.Psmp = 0; + break; + case MMPS_DYNAMIC: + Frame.Psmp = 3; + break; + case MMPS_STATIC: + Frame.Psmp = 1; + break; + } + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_PSMP_ACTION), &Frame, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_ERROR,("HT - SendPSMPAction( %d ) \n", Frame.Psmp)); +} + + +#define RADIO_MEASUREMENT_REQUEST_ACTION 0 + +typedef struct GNU_PACKED +{ + 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 +{ + UCHAR ID; + UCHAR Length; + UCHAR Token; + UCHAR RequestMode; + UCHAR Type; +} MEASUREMENT_REQ; + +#ifdef CONFIG_AP_SUPPORT +VOID SendBeaconRequest( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid) +{ + PUCHAR 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].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid); + + Frame.Category = CATEGORY_RM; + Frame.Action = RADIO_MEASUREMENT_REQUEST_ACTION; + 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 +#ifdef P2P_SUPPORT + if (IS_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; + /* End of if */ + + 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 +#ifdef P2P_SUPPORT + if (IS_OPMODE_AP(pRxBlk)) + { + /* maybe insert VLAN tag to the received packet */ + UCHAR VLAN_Size = 0; + UCHAR *data_p; + USHORT VLAN_VID = 0, VLAN_Priority = 0; + UCHAR WhichBSSID = FromWhichBSSID; + + if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_P2P_GO) + WhichBSSID = FromWhichBSSID - MIN_NET_DEVICE_FOR_P2P_GO; + + /* VLAN related */ + 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 */ + + if (VLAN_VID != 0) + VLAN_Size = LENGTH_802_1Q; + /* End of if */ + + 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); + } + else + { +#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 + } +#else + 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 /* P2P_SUPPORT */ +#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); + + + +static VOID ba_enqueue_reordering_packet( + 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); + + 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); + } +} + + +/* + ========================================================================== + 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( + 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->pRxWI->WirelessCliID; + UCHAR TID = pRxBlk->pRxWI->TID; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + +#ifdef MAC_REPEATER_SUPPORT + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + 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 packet*/ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + + + if (Wcid < MaxWcidNum) + { + Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[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 !!!*/ + 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(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) + { + + /* 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(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; + } + } +} + + +VOID BaReOrderingBufferMaintain( + IN PRTMP_ADAPTER pAd) +{ + ULONG Now32; + UCHAR Wcid; + USHORT Idx; + UCHAR TID; + PBA_REC_ENTRY pBAEntry = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + +#ifdef MAC_REPEATER_SUPPORT + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + + /* update last rx time*/ + NdisGetSystemUpTime(&Now32); + + for (Wcid = 1; Wcid < MaxWcidNum; 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->bUseHwTxLURate != TRUE) + { + DBGPRINT(RT_DEBUG_WARN, + ("%s(): Warning! bUseHwTxLURate is FALSE.\n", + __FUNCTION__)); + return; + } + + if (!IS_HW_TXRATE_LOOKUP_SUPPORT(pAd)) + { + DBGPRINT(RT_DEBUG_WARN, + ("%s(): Warning! This chip does not support HW Tx rate lookup.\n", + __FUNCTION__)); + return; + } + + if (pEntry) + { + USHORT RegId = 0; + UINT32 MacReg = 0, BitLUT; + 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); + BitLUT = (MacReg & ((1 << 18))); + if (BitLUT) + { + /* Keep original register setting in this flag */ + pEntry->bPeerDelBaTxAdaptEn |= BitLUT; + } + else + { + MacReg |= (1 << 18); + RTMP_IO_WRITE32(pAd, TX_FBK_LIMIT, MacReg); + } + RegId = 0x1C00 + (pEntry->Aid << 3); + RTMP_IO_WRITE32(pAd, RegId, 0x4007); /* Legacy OFDM / no STBC / LGI / BW20 / MCS 7 */ + 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->bUseHwTxLURate != TRUE) + { + DBGPRINT(RT_DEBUG_WARN, + ("%s(): Warning! bUseHwTxLURate is FALSE.\n", + __FUNCTION__)); + return; + } + + if (!IS_HW_TXRATE_LOOKUP_SUPPORT(pAd)) + { + DBGPRINT(RT_DEBUG_WARN, + ("%s(): Warning! This chip does not support HW Tx rate lookup.\n", + __FUNCTION__)); + return; + } + + if (pEntry && pEntry->bPeerDelBaTxAdaptEn) + { + UINT32 BitLUT; + BOOLEAN Cancelled; + + BitLUT = (pEntry->bPeerDelBaTxAdaptEn & (1 << 18)); + if (!BitLUT) + { + 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)); + } + /* TODO: ressume MSC rate of the MAC look up table? */ + pEntry->bPeerDelBaTxAdaptEn = 0; + RTMPCancelTimer(&pEntry->DelBA_tx_AdaptTimer, &Cancelled); + 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/mt7620/src/common/client_wds.c b/mt7620/src/common/client_wds.c new file mode 100644 index 0000000..b5edbfc --- /dev/null +++ b/mt7620/src/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/mt7620/src/common/cmm_aes.c b/mt7620/src/common/cmm_aes.c new file mode 100644 index 0000000..7769570 --- /dev/null +++ b/mt7620/src/common/cmm_aes.c @@ -0,0 +1,1142 @@ +/* + *************************************************************************** + * 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; + USHORT fc; + UCHAR fc0; + UCHAR fc1; + UINT frame_type; + 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); + + fc = *((PUSHORT)pData); + + frame_type = ((fc0 >> 2) & 0x03); + 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; + + 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 7¡V12. + 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 == BTYPE_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 == BTYPE_DATA), + a4_exists, + qc_exists, + aad_hdr, + &aad_len); + + /* Construct NONCE header */ + RTMPConstructCCMPNonce(pHdr, + a4_exists, + qc_exists, + (frame_type == BTYPE_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 == BTYPE_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; + + /* Construct AAD header */ + RTMPConstructCCMPAAD(pHdr, + (frame_type == BTYPE_DATA), + a4_exists, + qc_exists, + aad_hdr, + &aad_len); + + /* Construct NONCE header */ + RTMPConstructCCMPNonce(pHdr, + a4_exists, + qc_exists, + (frame_type == BTYPE_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; +} + +/* + ======================================================================== + + 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"); + + } + + diff --git a/mt7620/src/common/cmm_asic.c b/mt7620/src/common/cmm_asic.c new file mode 100644 index 0000000..51c122c --- /dev/null +++ b/mt7620/src/common/cmm_asic.c @@ -0,0 +1,4220 @@ +/* + *************************************************************************** + * 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 RT2880 +/* Reset the RFIC setting to new series */ +RTMP_RF_REGS RF2850RegTable[] = { +/* ch R1 R2 R3(TX0~4=0) R4*/ + {1, 0x98402ecc, 0x984c0786, 0x981ab455, 0x9800510b}, + {2, 0x98402ecc, 0x984c0786, 0x981a8a55, 0x9800519f}, + {3, 0x98402ecc, 0x984c078a, 0x981a8a55, 0x9800518b}, + {4, 0x98402ecc, 0x984c078a, 0x981a8a55, 0x9800519f}, + {5, 0x98402ecc, 0x984c078e, 0x981a8a55, 0x9800518b}, + {6, 0x98402ecc, 0x984c078e, 0x981a8a55, 0x9800519f}, + {7, 0x98402ecc, 0x984c0792, 0x981a8a55, 0x9800518b}, + {8, 0x98402ecc, 0x984c0792, 0x981a8a55, 0x9800519f}, + {9, 0x98402ecc, 0x984c0796, 0x981a8a55, 0x9800518b}, + {10, 0x98402ecc, 0x984c0796, 0x981a8a55, 0x9800519f}, + {11, 0x98402ecc, 0x984c079a, 0x981a8a55, 0x9800518b}, + {12, 0x98402ecc, 0x984c079a, 0x981a8a55, 0x9800519f}, + {13, 0x98402ecc, 0x984c079e, 0x981a8a55, 0x9800518b}, + {14, 0x98402ecc, 0x984c07a2, 0x981a8a55, 0x98005193}, + + /* 802.11 UNI / HyperLan 2*/ + {36, 0x98402ecc, 0x984c099a, 0x98198a55, 0x980ed1a3}, + {38, 0x98402ecc, 0x984c099e, 0x98198a55, 0x980ed193}, + {40, 0x98402ec8, 0x984c0682, 0x98198a55, 0x980ed183}, + {44, 0x98402ec8, 0x984c0682, 0x98198a55, 0x980ed1a3}, + {46, 0x98402ec8, 0x984c0686, 0x98198a55, 0x980ed18b}, + {48, 0x98402ec8, 0x984c0686, 0x98198a55, 0x980ed19b}, + {52, 0x98402ec8, 0x984c068a, 0x98198a55, 0x980ed193}, + {54, 0x98402ec8, 0x984c068a, 0x98198a55, 0x980ed1a3}, + {56, 0x98402ec8, 0x984c068e, 0x98198a55, 0x980ed18b}, + {60, 0x98402ec8, 0x984c0692, 0x98198a55, 0x980ed183}, + {62, 0x98402ec8, 0x984c0692, 0x98198a55, 0x980ed193}, + {64, 0x98402ec8, 0x984c0692, 0x98198a55, 0x980ed1a3}, /* Plugfest#4, Day4, change RFR3 left4th 9->5.*/ + + /* 802.11 HyperLan 2*/ + {100, 0x98402ec8, 0x984c06b2, 0x981b8a55, 0x980ed783}, + + /* 2008.04.30 modified */ + /* The system team has AN to improve the EVM value */ + /* for channel 102 to 108 for the RT2850/RT2750 dual band solution.*/ + {102, 0x98402ec8, 0x985c06b2, 0x985b8a55, 0x980ed793}, + {104, 0x98402ec8, 0x985c06b2, 0x985b8a55, 0x980ed1a3}, + {108, 0x98402ecc, 0x985c0a32, 0x985b8a55, 0x980ed193}, + + {110, 0x98402ecc, 0x984c0a36, 0x981b8a55, 0x980ed183}, + {112, 0x98402ecc, 0x984c0a36, 0x981b8a55, 0x980ed19b}, + {116, 0x98402ecc, 0x984c0a3a, 0x981b8a55, 0x980ed1a3}, + {118, 0x98402ecc, 0x984c0a3e, 0x981b8a55, 0x980ed193}, + {120, 0x98402ec4, 0x984c0382, 0x981b8a55, 0x980ed183}, + {124, 0x98402ec4, 0x984c0382, 0x981b8a55, 0x980ed193}, + {126, 0x98402ec4, 0x984c0382, 0x981b8a55, 0x980ed15b}, /* 0x980ed1bb->0x980ed15b required by Rory 20070927*/ + {128, 0x98402ec4, 0x984c0382, 0x981b8a55, 0x980ed1a3}, + {132, 0x98402ec4, 0x984c0386, 0x981b8a55, 0x980ed18b}, + {134, 0x98402ec4, 0x984c0386, 0x981b8a55, 0x980ed193}, + {136, 0x98402ec4, 0x984c0386, 0x981b8a55, 0x980ed19b}, + {140, 0x98402ec4, 0x984c038a, 0x981b8a55, 0x980ed183}, + + /* 802.11 UNII*/ + {149, 0x98402ec4, 0x984c038a, 0x981b8a55, 0x980ed1a7}, + {151, 0x98402ec4, 0x984c038e, 0x981b8a55, 0x980ed187}, + {153, 0x98402ec4, 0x984c038e, 0x981b8a55, 0x980ed18f}, + {157, 0x98402ec4, 0x984c038e, 0x981b8a55, 0x980ed19f}, + {159, 0x98402ec4, 0x984c038e, 0x981b8a55, 0x980ed1a7}, + {161, 0x98402ec4, 0x984c0392, 0x981b8a55, 0x980ed187}, + {165, 0x98402ec4, 0x984c0392, 0x981b8a55, 0x980ed197}, + {167, 0x98402ec4, 0x984c03d2, 0x981b9855, 0x9815531f}, + {169, 0x98402ec4, 0x984c03d2, 0x981b9855, 0x98155327}, + {171, 0x98402ec4, 0x984c03d6, 0x981b9855, 0x98155307}, + {173, 0x98402ec4, 0x984c03d6, 0x981b9855, 0x9815530f}, + + /* Japan*/ + {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b}, + {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13}, + {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b}, + {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23}, + {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13}, + {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b}, + {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23}, + + /* still lack of MMAC(Japan) ch 34,38,42,46*/ +}; +UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS)); +#endif /* RT2880 */ + +#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 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 */ + PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate; + +#ifdef AGS_SUPPORT + PRTMP_TX_RATE_SWITCH_AGS 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 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 = (PRTMP_TX_RATE_SWITCH_AGS)pRateTable+1; + pNextTxRate = (PRTMP_TX_RATE_SWITCH)pNextTxRate_AGS; + } + else +#endif /* AGS_SUPPORT */ + pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1; + + for (i = 1; i < *((PUCHAR) pRateTable); i++) + { +#ifdef AGS_SUPPORT + if (bUseAGS) + { + pCurrTxRate_AGS = (PRTMP_TX_RATE_SWITCH_AGS)pRateTable+1+i; + pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pCurrTxRate_AGS; + } + else +#endif /* AGS_SUPPORT */ + pCurrTxRate = (PRTMP_TX_RATE_SWITCH)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 = 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 */ + +/* + ======================================================================== + + 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. + ======================================================================== +*/ +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]; + USHORT offset; + UCHAR i; + UINT32 MacReg = 0; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + return; +#endif /* RALINK_ATE */ + +#ifdef DOT11_N_SUPPORT + if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8)) + { + return; + } + +#ifdef RT3883 + if (pAd->FlgCWC) + RT3883_CWC_ProtectAdjust(pAd, &SetMask, &OperationMode); + else +#endif /* RT3883 */ + 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; + + /* update PHY mode and rate*/ + if (pAd->OpMode == OPMODE_AP) + { + /* update PHY mode and rate*/ + if (pAd->CommonCfg.Channel > 14) + ProtCfg.field.ProtectRate = 0x4000; + 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 = 0x4000; // OFDM 6Mbps + } + else + { + ProtCfg.field.ProtectRate = 0x0000; // CCK 1Mbps + if (pAd->CommonCfg.MinTxRate > RATE_11) + ProtCfg.field.ProtectRate |= 0x4000; // OFDM 6Mbps + } + } + + /* Handle legacy(B/G) protection*/ + if (bDisableBGProtect) + { + /*ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;*/ + ProtCfg.field.ProtectCtrl = 0; + Protect[0] = ProtCfg.word; + Protect[1] = ProtCfg.word; + pAd->FlgCtsEnabled = 0; /* CTS-self is not used */ + } + else + { + /*ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;*/ + ProtCfg.field.ProtectCtrl = 0; /* CCK do not need to be protected*/ + Protect[0] = ProtCfg.word; + ProtCfg.field.ProtectCtrl = ASIC_CTS; /* OFDM needs using CCK to protect*/ + Protect[1] = ProtCfg.word; + pAd->FlgCtsEnabled = 1; /* CTS-self is 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[4] = 0x01754004; + Protect[5] = 0x03f54084; + } + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; + 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[2] = ProtCfg.word; + Protect[3] = ProtCfg4.word; + Protect[4] = ProtCfg.word; + Protect[5] = ProtCfg4.word; + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; + 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[2] = ProtCfg.word; + Protect[3] = ProtCfg4.word; + if (bNonGFExist) + { + ProtCfg.field.ProtectCtrl = ASIC_RTS; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + } + Protect[4] = ProtCfg.word; + Protect[5] = ProtCfg4.word; + + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; + 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[2] = ProtCfg.word; + Protect[3] = ProtCfg4.word; + Protect[4] = ProtCfg.word; + Protect[5] = ProtCfg4.word; + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; + 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*/ + } + + Protect[2] = ProtCfg.word; /*0x01754004;*/ + Protect[3] = ProtCfg4.word; /*0x03f54084;*/ + Protect[4] = ProtCfg.word; /*0x01754004;*/ + Protect[5] = 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))) + { + RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]); + } +} +} + + +VOID AsicBBPAdjust(RTMP_ADAPTER *pAd) +{ + RTMP_CHIP_ASIC_BBP_ADJUST(pAd); + +} + + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSwitchChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel, + IN BOOLEAN bScan) +{ +#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 */ + +#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, ("AsicSwitchChannel: 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, ("AsicSwitchChannel autopm_resume fail ------\n")); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_SUSPEND); + return; + } + else + DBGPRINT(RT_DEBUG_TRACE, ("AsicSwitchChannel: autopm_resume do nothing \n")); + +#endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ +#endif /* CONFIG_PM */ +#endif /* CONFIG_STA_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT +#ifdef AP_QLOAD_SUPPORT + /* clear all statistics count for QBSS Load */ + QBSS_LoadStatusClear(pAd); +#endif /* AP_QLOAD_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + RTMP_CHIP_ASIC_SWITCH_CHANNEL(pAd, Channel, bScan); + +} + +/* + ========================================================================== + 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 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; + } +} + +VOID AsicGetTxPowerOffset( + IN PRTMP_ADAPTER pAd, + IN PULONG 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 */ + + 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 = &pAd->TssiMinusBoundaryG[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0]; + TxAgcStep = pAd->TxAgcStepG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + /* a channel */ + bAutoTxAgc = pAd->bAutoTxAgcA; + TssiRef = pAd->TssiRefA; + pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0]; + TxAgcStep = pAd->TxAgcStepA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &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 */ +#ifdef RT3883 + if (IS_RT3883(pAd)) + { + if ((idx == 5) && ((BbpR49.byte) > pTssiMinusBoundary[4] + 8)) + idx += 1; + } +#endif /* RT3883 */ + + *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; + } +#ifdef RT3883 + if (IS_RT3883(pAd) && (idx == 5)) + { + if ((BbpR49.byte) < (pTssiPlusBoundary[4] - 16)) + idx += 2; + else if ((BbpR49.byte) < (pTssiPlusBoundary[4] - 8)) + idx += 1; + } +#endif /* RT3883 */ + + /* 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); + } + +#ifdef RT3883 + if (IS_RT3883(pAd) && (pAd->bTxPwrRangeExt)) + DeltaPwr -= 2; +#endif /* RT3883 */ + + *pDeltaPwr = DeltaPwr; + *pAgcCompensate = *pTxAgcCompensate; + + DBGPRINT(RT_DEBUG_INFO, ("<--%s\n", __FUNCTION__)); +} + +#ifdef RTMP_TEMPERATURE_COMPENSATION +VOID InitLookupTable( + IN PRTMP_ADAPTER pAd) +{ + int Idx, IdxTmp; + int i; + enum IEEE80211_BAND band; + int band_nums = 1; + const int Offset = 7; + EEPROM_WORD_STRUC WordStruct = {{0}}; + UCHAR PlusStepNum[IEEE80211_BAND_NUMS][8] = {{0, 1, 3, 2, 3, 3, 3, 2}, {0, 1, 3, 2, 3, 3, 3, 2}}; + UCHAR MinusStepNum[IEEE80211_BAND_NUMS][8] = {{1, 1, 1, 1, 1, 1, 0, 1}, {1, 1, 1, 1, 1, 1, 0, 1}}; + UCHAR Step[IEEE80211_BAND_NUMS] = {10, 10}; + UCHAR RFValue = 0, BbpValue = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("==> InitLookupTable\n")); + + /* Read from EEPROM, as parameters for lookup table for G band */ + RT28xx_EEPROM_READ16(pAd, 0x6e, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 2.4G] EEPROM 6e = %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, ("[temp. compensation 2.4G] EEPROM 70 = %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, ("[temp. compensation 2.4G] EEPROM 72 = %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, ("[temp. compensation 2.4] EEPROM 74 = %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, ("[temp. compensation 2.4G] EEPROM 76 = %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, ("[temp. compensation 2.4G] Plus = %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, ("[temp. compensation 2.4G] Minus = %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, ("[temp. compensation 2.4G] tssi gain/step = %u\n", pAd->TxPowerCtrl.TssiGain[IEEE80211_BAND_2G])); + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 2.4] Step = %u\n", Step[IEEE80211_BAND_2G])); + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 2.4] RefTemp_2G = %d\n", pAd->TxPowerCtrl.RefTemp[IEEE80211_BAND_2G])); + +#ifdef A_BAND_SUPPORT + if (RFIC_IS_5G_BAND(pAd)) + { + /* Read from EEPROM, as parameters for lookup table for A band */ + RT28xx_EEPROM_READ16(pAd, 0xd4, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 5G] EEPROM d4 = %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, ("[temp. compensation 5G] EEPROM d6 = %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, ("[temp. compensation 5G] EEPROM d8 = %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, ("[temp. compensation 5G] EEPROM da = %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, ("[temp. compensation 5G] EEPROM dc = %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, ("[temp. compensation 5G] Plus = %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, ("[temp. compensation 5G] Minus = %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, ("[temp. compensation 5G] tssi gain/step = %u\n", pAd->TxPowerCtrl.TssiGain[IEEE80211_BAND_5G])); + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 5G] Step = %u\n", Step[IEEE80211_BAND_5G])); + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 5G] RefTemp_2G = %d\n", pAd->TxPowerCtrl.RefTemp[IEEE80211_BAND_5G])); + + band_nums = IEEE80211_BAND_NUMS; + } +#endif /* A_BAND_SUPPORT */ + + + for (band = IEEE80211_BAND_2G; band < band_nums; band++) + { + /* positive */ + i = 0; + IdxTmp = 1; + + pAd->TxPowerCtrl.LookupTable[band][1 + Offset] = Step[band] / 2; + pAd->TxPowerCtrl.LookupTable[band][0 + Offset] = pAd->TxPowerCtrl.LookupTable[band][1 + Offset] - Step[band]; + for (Idx = 2; Idx < 26;)/* Idx++ )*/ + { + if (PlusStepNum[band][i] != 0 || i >= 8) + { + if (Idx >= IdxTmp + PlusStepNum[band][i] && i < 8) + { + pAd->TxPowerCtrl.LookupTable[band][Idx + Offset] = pAd->TxPowerCtrl.LookupTable[band][Idx - 1 + Offset] + (Step[band] - (i+1) + 1); + IdxTmp = IdxTmp + PlusStepNum[band][i]; + i += 1; + } + else + { + pAd->TxPowerCtrl.LookupTable[band][Idx + Offset] = pAd->TxPowerCtrl.LookupTable[band][Idx - 1 + Offset] + (Step[band] - (i+1) + 1); + } + Idx++; + } + else + { + i += 1; + } + } + + /* negative */ + i = 0; + IdxTmp = 1; + for (Idx = 1; Idx < 8;)/* Idx++ )*/ + { + if (MinusStepNum[band][i] != 0 || i >= 8) + { + if ((Idx + 1) >= IdxTmp + MinusStepNum[band][i] && i < 8) + { + pAd->TxPowerCtrl.LookupTable[band][-Idx + Offset] = pAd->TxPowerCtrl.LookupTable[band][-Idx + 1 + Offset] - (Step[band] + (i+1) - 1); + IdxTmp = IdxTmp + MinusStepNum[band][i]; + i += 1; + } + else + { + pAd->TxPowerCtrl.LookupTable[band][-Idx + Offset] = pAd->TxPowerCtrl.LookupTable[band][-Idx + 1 + Offset] - (Step[band] + (i+1) - 1); + } + Idx++; + } + else + { + i += 1; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] Lookup table as below:\n")); + for (Idx = 0; Idx < 33; Idx++) + { + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation band(%d)] %d, %d\n", band, Idx - Offset, pAd->TxPowerCtrl.LookupTable[band][Idx])); + } + } + + /* Set BBP_R47 */ + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpValue); + + /* bit3 = 0 */ + BbpValue = (BbpValue & 0xf7); + + /* bit7 = 1, bit4 = 0 */ + BbpValue = (BbpValue | 0x80); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BbpValue); + + /* Set RF_R27 */ + RT30xxReadRFRegister(pAd, RF_R27, &RFValue); + + /* Set [7:6] to 01. For method 2, it is set at initialization. */ + RFValue = (RFValue & 0x7f); + RFValue = (RFValue | 0x40); + + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] Set RF_R27 to 0x%x\n", RFValue)); + RT30xxWriteRFRegister(pAd, RF_R27, RFValue); +} + +VOID AsicGetAutoAgcOffsetForTemperatureSensor( + IN PRTMP_ADAPTER pAd, + IN PCHAR pDeltaPwr, + IN PCHAR pTotalDeltaPwr, + IN PCHAR pAgcCompensate, + IN PCHAR pDeltaPowerByBbpR1) +{ + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + const TX_POWER_TUNING_ENTRY_STRUCT *TxPowerTuningTable; + TX_POWER_TUNING_ENTRY_STRUCT *TxPowerTuningTableEntry0 = NULL; /* Ant0 */ + TX_POWER_TUNING_ENTRY_STRUCT *TxPowerTuningTableEntry1 = NULL; /* Ant1 */ + BBP_R49_STRUC BbpR49; + BOOLEAN bAutoTxAgc = FALSE; + PCHAR pTxAgcCompensate = NULL; + UCHAR RFValue = 0; + CHAR TuningTableUpperBound = 0, TuningTableIndex0 = 0, TuningTableIndex1 = 0; + INT CurrentTemp = 0; + INT RefTemp; + INT *LookupTable; + INT LookupTableIndex = pAd->TxPowerCtrl.LookupTableIndex + TEMPERATURE_COMPENSATION_LOOKUP_TABLE_OFFSET; + + DBGPRINT(RT_DEBUG_INFO, ("-->%s\n", __FUNCTION__)); + + BbpR49.byte = 0; + *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; + } + 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; + } + + /* AutoTxAgc in EEPROM means temperature compensation enabled/diablded. */ + if (bAutoTxAgc) + { + /* Current temperature */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49.byte); + CurrentTemp = (CHAR)BbpR49.byte; + DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] BBP_R49 = %02x, current temp = %d\n", BbpR49.byte, CurrentTemp)); + DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] RefTemp = %d\n", RefTemp)); + DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] index = %d\n", pAd->TxPowerCtrl.LookupTableIndex)); + DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] f(%d)= %d\n", pAd->TxPowerCtrl.LookupTableIndex - 1, LookupTable[LookupTableIndex - 1])); + DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] f(%d)= %d\n", pAd->TxPowerCtrl.LookupTableIndex, LookupTable[LookupTableIndex])); + DBGPRINT(RT_DEBUG_INFO, ("[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 < 32) + { + DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] ++\n")); + LookupTableIndex++; + pAd->TxPowerCtrl.LookupTableIndex++; + } + else if (CurrentTemp < RefTemp + LookupTable[LookupTableIndex] - ((LookupTable[LookupTableIndex] - LookupTable[LookupTableIndex - 1]) >> 2) && + LookupTableIndex > 0) + { + DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] --\n")); + LookupTableIndex--; + pAd->TxPowerCtrl.LookupTableIndex--; + } + else + { + DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] ==\n")); + } + + DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] idxTxPowerTable=%d, idxTxPowerTable2=%d, TuningTableUpperBound=%d\n", + pAd->TxPowerCtrl.idxTxPowerTable + pAd->TxPowerCtrl.LookupTableIndex, + pAd->TxPowerCtrl.idxTxPowerTable2 + pAd->TxPowerCtrl.LookupTableIndex, + TuningTableUpperBound)); + + 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 */ + /* 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]; + + 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 */ + /* 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]; + + DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] (tx0)RF_TX_ALC = %x, MAC_PowerDelta = %d, TuningTableIndex = %d\n", + TxPowerTuningTableEntry0->RF_TX_ALC, TxPowerTuningTableEntry0->MAC_PowerDelta, TuningTableIndex0)); + DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] (tx1)RF_TX_ALC = %x, MAC_PowerDelta = %d, TuningTableIndex = %d\n", + TxPowerTuningTableEntry1->RF_TX_ALC, TxPowerTuningTableEntry1->MAC_PowerDelta, TuningTableIndex1)); + + /* Update RF_R49 [0:5] */ + RT30xxReadRFRegister(pAd, RF_R49, &RFValue); + RFValue = ((RFValue & ~0x3F) | TxPowerTuningTableEntry0->RF_TX_ALC); + if ((RFValue & 0x3F) > 0x27) /* The valid range of the RF R49 (<5:0>tx0_alc<5:0>) is 0x00~0x27 */ + { + RFValue = ((RFValue & ~0x3F) | 0x27); + } + DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] Update RF_R49[0:5] to 0x%x\n", TxPowerTuningTableEntry0->RF_TX_ALC)); + RT30xxWriteRFRegister(pAd, RF_R49, RFValue); + + /* Update RF_R50 [0:5] */ + RT30xxReadRFRegister(pAd, RF_R50, &RFValue); + RFValue = ((RFValue & ~0x3F) | TxPowerTuningTableEntry1->RF_TX_ALC); + if ((RFValue & 0x3F) > 0x27) /* The valid range of the RF R49 (<5:0>tx0_alc<5:0>) is 0x00~0x27 */ + { + RFValue = ((RFValue & ~0x3F) | 0x27); + } + DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] Update RF_R50[0:5] to 0x%x\n", TxPowerTuningTableEntry1->RF_TX_ALC)); + RT30xxWriteRFRegister(pAd, RF_R50, RFValue); + + *pTotalDeltaPwr = TxPowerTuningTableEntry0->MAC_PowerDelta; + + } + + *pAgcCompensate = *pTxAgcCompensate; + DBGPRINT(RT_DEBUG_INFO, ("<--%s\n", __FUNCTION__)); +} +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + +#ifdef SINGLE_SKU +VOID GetSingleSkuDeltaPower( + IN PRTMP_ADAPTER pAd, + IN PCHAR pTotalDeltaPower, + INOUT PULONG pSingleSKUTotalDeltaPwr, + INOUT PUCHAR 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; + } + } + } + + 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; + } + + 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) +#ifdef P2P_SUPPORT + && (!P2P_GO_ON(pAd)) +#endif /* P2P_SUPPORT */ + ) + { + /* 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( + IN PRTMP_ADAPTER pAd, + INOUT PCHAR pTotalDeltaPower) +{ + UCHAR BbpR1 = 0; + + DBGPRINT(RT_DEBUG_INFO, ("%s: TotalDeltaPower = %d dBm\n", __FUNCTION__, *pTotalDeltaPower)); + + /* 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; + + if (*pTotalDeltaPower <= -12) + { + *pTotalDeltaPower += 12; + BbpR1 |= MDSM_DROP_TX_POWER_BY_12dBm; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); + + DBGPRINT(RT_DEBUG_INFO, ("%s: Drop the transmit power by 12 dBm (BBP R1)\n", __FUNCTION__)); + } + else if ((*pTotalDeltaPower <= -6) && (*pTotalDeltaPower > -12)) + { + *pTotalDeltaPower += 6; + BbpR1 |= MDSM_DROP_TX_POWER_BY_6dBm; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); + + DBGPRINT(RT_DEBUG_INFO, ("%s: Drop the transmit power by 6 dBm (BBP R1)\n", __FUNCTION__)); + } + else + { + /* Control the the transmit power by using the MAC only */ + 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)); +} + +/* + ========================================================================== + 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( + IN PRTMP_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 */ +#ifdef RTMP_INTERNAL_TX_ALC +#ifdef RT3352 + CHAR TotalDeltaPower2 = 0, Value2 = 0; + BOOLEAN bTX1 = FALSE; +#endif /* RT3352 */ +#endif /* RTMP_INTERNAL_TX_ALC */ + 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 RTMP_INTERNAL_TX_ALC +#ifdef RT3352 + if (IS_RT3352(pAd) && (pAd->TxPowerCtrl.bInternalTxALC == TRUE)) + { + TotalDeltaPower2 = pAd->TxPowerCtrl.TotalDeltaPower2; + } + + if (IS_RT3352(pAd) && (pAd->TxPowerCtrl.bInternalTxALC == FALSE)) + { + /* Get delta power based on the percentage specified from UI */ + AsicPercentageDeltaPower(pAd, Rssi, &DeltaPwr,&DeltaPowerByBbpR1); + } +#endif /* RT3352 */ +#endif /* RTMP_INTERNAL_TX_ALC */ +#ifndef RT3352 + /* Get delta power based on the percentage specified from UI */ + AsicPercentageDeltaPower(pAd, Rssi, &DeltaPwr,&DeltaPowerByBbpR1); +#endif /* RT3352 */ + + /* 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 */ + { +#ifndef RT3352 + AsicCompensatePowerViaBBP(pAd, &TotalDeltaPower); +#endif /* RT3352 */ + } + + /* Power will be updated each 4 sec. */ + if (pAd->Mlme.OneSecPeriodicRound % 4 == 0) + { +#ifndef RT3352 +/*****************************************************************************/ + /* Set new Tx power for different Tx rates */ + for (i=0; i < CfgOfTxPwrCtrlOverMAC.NumOfEntries; i++) + { + TX_POWER_CONTROL_OVER_MAC_ENTRY *pTxPwrEntry; + ULONG reg_val; + + pTxPwrEntry = &CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i]; + reg_val = pTxPwrEntry->RegisterValue; + if (reg_val != 0xffffffff) + { + for (j=0; j<8; j++) + { + CHAR _upbound, _lowbound, t_pwr; + BOOLEAN _bValid; + + _lowbound = 0; + _bValid = TRUE; + + Value = (CHAR)((reg_val >> j*4) & 0x0F); +#ifdef SINGLE_SKU + if (pAd->CommonCfg.bSKUMode == TRUE) + { + TotalDeltaPower = SingleSKUBbpR1Offset + TotalDeltaPowerOri - (CHAR)((SingleSKUTotalDeltaPwr[i] >> j*4) & 0x0F); + + DBGPRINT(RT_DEBUG_INFO, ("%s: BbpR1Offset(%d) + TX ALC(%d) - SingleSKU[%d/%d](%d) = TotalDeltaPower(%d)\n", + __FUNCTION__, SingleSKUBbpR1Offset, + TotalDeltaPowerOri, i, j, + (CHAR)((SingleSKUTotalDeltaPwr[i] >> j*4) & 0x0F), + TotalDeltaPower)); + } +#endif /* SINGLE_SKU */ + +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) + /* The upper bounds of MAC 0x1314 ~ 0x1324 are variable */ + if ((pAd->TxPowerCtrl.bInternalTxALC == TRUE)^(pAd->chipCap.bTempCompTxALC == TRUE)) + { + switch (0x1314 + (i * 4)) + { + case 0x1314: + _upbound = 0xe; + break; + + case 0x1318: + _upbound = (j <= 3) ? 0xc : 0xe; + break; + + case 0x131C: + _upbound = ((j == 0) || (j == 2) || (j == 3)) ? 0xc : 0xe; + break; + + case 0x1320: + _upbound = (j == 1) ? 0xe : 0xc; + break; + + case 0x1324: + _upbound = 0xc; + break; + + default: + { + /* do nothing */ + _bValid = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknown register = 0x%x\n", __FUNCTION__, (0x1314 + (i * 4)))); + } + break; + } + } + else +#endif /* RTMP_INTERNAL_TX_ALC || RTMP_TEMPERATURE_COMPENSATION */ +#ifdef RT3883 + if (IS_RT3883(pAd)) + _upbound = (pAd->NicConfig2.field.DynamicTxAgcControl) ? 0xf : 0xc; + else +#endif /* RT3883 */ + _upbound = 0xc; + + if (_bValid) + { + t_pwr = Value + TotalDeltaPower; + if (t_pwr < _lowbound) + Value = _lowbound; + else if (t_pwr > _upbound) + Value = _upbound; + else + Value = t_pwr; + } + + /* Fill new value into the corresponding MAC offset */ + pTxPwrEntry->RegisterValue = (reg_val & ~(0x0000000F << j*4)) | (Value << j*4); + } + + RTMP_IO_WRITE32(pAd, pTxPwrEntry->MACRegisterOffset, pTxPwrEntry->RegisterValue); + + } + } +#else /* specific for RT3352 */ +/*****************************************************************************/ + /* Set new Tx power for different Tx rates */ + for (i=0; i < CfgOfTxPwrCtrlOverMAC.NumOfEntries; i++) + { + if (CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].RegisterValue != 0xffffffff) + { + for (j=0; j<8; j++) + { + Value = (CHAR)((CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].RegisterValue >> j*4) & 0x0F); + +#ifdef RTMP_INTERNAL_TX_ALC +#ifdef RT3352 + /* Tx power adjustment over MAC */ + if (IS_RT3352(pAd) && (pAd->TxPowerCtrl.bInternalTxALC == TRUE)) + { + if (j & 0x00000001) /* j=1, 3, 5, 7 */ + { + /* TX1 ALC */ + Value2 = (CHAR)((CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].RegisterValue >> j*4) & 0x0F); /* 0 ~ 15 */ + bTX1 = TRUE; + } + else /* j=0, 2, 4, 6 */ + { + /* TX0 ALC */ + Value = (CHAR)((CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].RegisterValue >> j*4) & 0x0F); /* 0 ~ 15 */ + bTX1 = FALSE; + } + } +#endif /* RT3352 */ + /* The upper bounds of the MAC 0x1314~0x1324 are variable when the STA uses the internal Tx ALC.*/ + if ((pAd->TxPowerCtrl.bInternalTxALC == TRUE) && (pAd->Mlme.OneSecPeriodicRound % 4 == 0)) + { + switch (TX_PWR_CFG_0 + (i * 4)) + { + case TX_PWR_CFG_0: + { + if (bTX1 == FALSE) + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE) + { + Value = 0xE; + } + else + { + Value += TotalDeltaPower; + } + } +#ifdef RT3352 + /* Tx power adjustment over MAC */ + if (IS_RT3352(pAd) && (bTX1 == TRUE)) + { + /* TX1 ALC */ + if ((Value2 + TotalDeltaPower2) < 0) + { + Value2 = 0; + } + else if ((Value2 + TotalDeltaPower2) > 0xE) + { + Value2 = 0xE; + } + else + { + Value2 += TotalDeltaPower2; + } + } +#endif /* RT3352 */ + } + break; + + case TX_PWR_CFG_1: + { + if (bTX1 == FALSE) + { + if ((j >= 0) && (j <= 3)) + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE)/* by HK 2011.04.06 */ + { + Value = 0xE;/* by HK 2011.04.06 */ + } + else + { + Value += TotalDeltaPower; + } + } + else + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE) + { + Value = 0xE; + } + else + { + Value += TotalDeltaPower; + } + } + } +#ifdef RT3352 + /* Tx power adjustment over MAC */ + if (IS_RT3352(pAd) && (bTX1 == TRUE)) + { + /* TX1 ALC */ + if ((j >= 0) && (j <= 3)) + { + if ((Value2 + TotalDeltaPower2) < 0) + { + Value2 = 0; + } + else if ((Value2 + TotalDeltaPower2) > 0xE)/* by HK 2011.04.06 */ + { + Value2 = 0xE;/* by HK 2011.04.06 */ + } + else + { + Value2 += TotalDeltaPower2; + } + } + else + { + if ((Value2 + TotalDeltaPower2) < 0) + { + Value2 = 0; + } + else if ((Value2 + TotalDeltaPower2) > 0xE) + { + Value2 = 0xE; + } + else + { + Value2 += TotalDeltaPower2; + } + } + } +#endif /* RT3352 */ + } + break; + + case TX_PWR_CFG_2: + { + if (bTX1 == FALSE) + { + if ((j == 0) || (j == 2) || (j == 3)) + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE)/* by HK 2011.04.06 */ + { + Value = 0xE;/* by HK 2011.04.06 */ + } + else + { + Value += TotalDeltaPower; + } + } + else + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE) + { + Value = 0xE; + } + else + { + Value += TotalDeltaPower; + } + } + } +#ifdef RT3352 + /* Tx power adjustment over MAC */ + if (IS_RT3352(pAd) && (bTX1 == TRUE)) + { + /* TX1 ALC */ + if ((j == 0) || (j == 2) || (j == 3)) + { + if ((Value2 + TotalDeltaPower2) < 0) + { + Value2 = 0; + } + else if ((Value2 + TotalDeltaPower2) > 0xE)/* by HK 2011.04.06 */ + { + Value2 = 0xE;/* by HK 2011.04.06 */ + } + else + { + Value2 += TotalDeltaPower2; + } + } + else + { + if ((Value2 + TotalDeltaPower2) < 0) + { + Value2 = 0; + } + else if ((Value2 + TotalDeltaPower2) > 0xE) + { + Value2 = 0xE; + } + else + { + Value2 += TotalDeltaPower2; + } + } + } +#endif /* RT3352 */ + } + break; + + case TX_PWR_CFG_3: + { + if (bTX1 == FALSE) + { + if ((j == 0) || (j == 2) || (j == 3) || + ((j >= 4) && (j <= 7))) + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE)/* by HK 2011.04.06 */ + { + Value = 0xE;/* by HK 2011.04.06 */ + } + else + { + Value += TotalDeltaPower; + } + } + else + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE) + { + Value = 0xE; + } + else + { + Value += TotalDeltaPower; + } + } + } +#ifdef RT3352 + /* Tx power adjustment over MAC */ + if (IS_RT3352(pAd) && (bTX1 == TRUE)) + { + /* TX1 ALC */ + if ((j == 0) || (j == 2) || (j == 3) || + ((j >= 4) && (j <= 7))) + { + if ((Value2 + TotalDeltaPower2) < 0) + { + Value2 = 0; + } + else if ((Value2 + TotalDeltaPower2) > 0xE)/* by HK 2011.04.06 */ + { + Value2 = 0xE;/* by HK 2011.04.06 */ + } + else + { + Value2 += TotalDeltaPower2; + } + } + else + { + if ((Value2 + TotalDeltaPower2) < 0) + { + Value2 = 0; + } + else if ((Value2 + TotalDeltaPower2) > 0xE) + { + Value2 = 0xE; + } + else + { + Value2 += TotalDeltaPower2; + } + } + } +#endif /* RT3352 */ + } + break; + + case TX_PWR_CFG_4: + { + if (bTX1 == FALSE) + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; + } + else if ((Value + TotalDeltaPower) > 0xE)/* by HK 2011.04.06 */ + { + Value = 0xE;/* by HK 2011.04.06 */ + } + else + { + Value += TotalDeltaPower; + } + } +#ifdef RT3352 + /* Tx power adjustment over MAC */ + if (IS_RT3352(pAd) && (bTX1 == TRUE)) + { + /* TX1 ALC */ + if ((Value2 + TotalDeltaPower2) < 0) + { + Value2 = 0; + } + else if ((Value2 + TotalDeltaPower2) > 0xE)/* by HK 2011.04.06 */ + { + Value2 = 0xE;/* by HK 2011.04.06 */ + } + else + { + Value2 += TotalDeltaPower2; + } + } +#endif /* RT3352 */ + } + break; + + default: + { + /* do nothing*/ + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknown register = 0x%X\n", + __FUNCTION__, + (TX_PWR_CFG_0 + (i * 4)))); + } + break; + } + } + else +#endif /* RTMP_INTERNAL_TX_ALC */ + { + if ((Value + TotalDeltaPower) < 0) + { + Value = 0; /* min */ + } + else if ((Value + TotalDeltaPower) > 0xC) + { + Value = 0xC; /* max */ + } + else + { + Value += TotalDeltaPower; /* temperature compensation */ + } + } + +#ifdef RTMP_INTERNAL_TX_ALC +#ifdef RT3352 + /* fill new value to CSR offset */ + /* Tx power adjustment over MAC */ + if (IS_RT3352(pAd) && (pAd->TxPowerCtrl.bInternalTxALC == TRUE) && (pAd->Mlme.OneSecPeriodicRound % 4 == 0)) + { + if (bTX1 == TRUE) /* j=1, 3, 5, 7 */ + { + /* TX1 ALC */ + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].RegisterValue = + (CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].RegisterValue & ~(0x0000000F << j*4)) | (Value2 << j*4); + } + else /* j=0, 2, 4, 6 */ + { + /* TX0 ALC */ + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].RegisterValue = + (CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].RegisterValue & ~(0x0000000F << j*4)) | (Value << j*4); + } + } +#else + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].RegisterValue = (CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].RegisterValue & ~(0x0000000F << j*4)) | (Value << j*4); +#endif /* RT3352 */ + else +#endif /* RTMP_INTERNAL_TX_ALC */ + { + /* TX0 ALC only */ + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].RegisterValue = (CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].RegisterValue & ~(0x0000000F << j*4)) | (Value << j*4); + } + } + + /* write tx power value to CSR */ + /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M + TX power for OFDM 6M/9M + TX power for CCK5.5M/11M + TX power for CCK1M/2M */ + /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */ + + { + /* RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);*/ +#ifdef RTMP_INTERNAL_TX_ALC + if ((pAd->TxPowerCtrl.bInternalTxALC == TRUE) && (pAd->Mlme.OneSecPeriodicRound % 4 == 0)) +#endif /* RTMP_INTERNAL_TX_ALC */ + RTMP_IO_WRITE32(pAd, CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].MACRegisterOffset, CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].RegisterValue); + } + } + } +/*****************************************************************************/ +#endif /* !RT3352 */ + /* Extra set MAC registers to compensate Tx power if any */ + RTMP_CHIP_ASIC_EXTRA_POWER_OVER_MAC(pAd); + } + +} + +#ifdef THERMAL_PROTECT_SUPPORT +VOID thermal_protection( + IN RTMP_ADAPTER *pAd) +{ + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + INT32 temp_diff = 0, current_temp = 0; + + current_temp = pChipOps->ChipGetCurrentTemp(pAd); + 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 */) + pChipOps->ThermalPro2ndCond(pAd); + else if (current_temp > pAd->thermal_pro_criteria /* 80 */) + pChipOps->ThermalPro1stCond(pAd); + else + pChipOps->ThermalProDefaultCond(pAd); + } else if (temp_diff < 0) { + if (current_temp < (pAd->thermal_pro_criteria - 5) /* 75 */) + pChipOps->ThermalProDefaultCond(pAd); + else if (current_temp < (pAd->thermal_pro_criteria + 5) /* 85 */) + pChipOps->ThermalPro1stCond(pAd); + else + pChipOps->ThermalPro2ndCond(pAd); + } +} +#endif /* THERMAL_PROTECT_SUPPORT */ + +VOID AsicResetBBPAgent( +IN PRTMP_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 */ + RTMP_CHIP_ASIC_RESET_BBP_AGENT(pAd); + else + { + 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 + + ========================================================================== + */ +VOID AsicSetBssid( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBssid) +{ + ULONG Addr4; +#ifdef P2P_SUPPORT + UINT32 regValue; +#endif /* P2P_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n", + pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5])); + + Addr4 = (ULONG)(pBssid[0]) | + (ULONG)(pBssid[1] << 8) | + (ULONG)(pBssid[2] << 16) | + (ULONG)(pBssid[3] << 24); + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4); + + Addr4 = 0; + /* always one BSSID in STA mode*/ + Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8); + +#ifdef P2P_SUPPORT +#ifdef P2P_ODD_MAC_ADJUST + if ( (pAd->CurrentAddress[5] & 0x01 ) == 0x01 ) + { + Addr4 |= (1 << 16 ); + } +#endif /* P2P_ODD_MAC_ADJUST */ +#endif /* P2P_SUPPORT */ + + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4); +#ifdef P2P_SUPPORT + if (P2P_INF_ON(pAd)) + { + PUCHAR pP2PBssid = &pAd->CurrentAddress[0]; + + Addr4 = (ULONG)(pP2PBssid[0]) | + (ULONG)(pP2PBssid[1] << 8) | + (ULONG)(pP2PBssid[2] << 16) | + (ULONG)(pP2PBssid[3] << 24); + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4); + + Addr4 = 0; + + /* always one BSSID in STA mode */ + Addr4 = (ULONG)(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) +#ifdef P2P_SUPPORT +#ifdef P2P_ODD_MAC_ADJUST + && FALSE +#endif /* P2P_ODD_MAC_ADJUST */ +#endif /* P2P_SUPPORT */ + ) + 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); + } +#endif /* P2P_SUPPORT */ +} + +VOID AsicSetMcastWC( + IN PRTMP_ADAPTER pAd) +{ + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID]; + USHORT offset; + + pEntry->Sst = SST_ASSOC; + pEntry->Aid = MCAST_WCID; /* Softap supports 1 BSSID and use WCID=0 as multicast Wcid index*/ + pEntry->PsMode = PWR_ACTIVE; + pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate; + offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicDelWcidTab( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid) +{ + ULONG Addr0 = 0x0, Addr1 = 0x0; + ULONG offset; + + DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid)); + offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE; + RTMP_IO_WRITE32(pAd, offset, Addr0); + offset += 4; + RTMP_IO_WRITE32(pAd, offset, Addr1); +} + +#ifdef DOT11_N_SUPPORT +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicEnableRDG( + IN PRTMP_ADAPTER pAd) +{ + TX_LINK_CFG_STRUC TxLinkCfg; + UINT32 Data = 0; + + 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, EDCA_AC0_CFG, &Data); + Data &= 0xFFFFFF00; + Data |= 0x80; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + + /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);*/ +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicDisableRDG( + IN PRTMP_ADAPTER pAd) +{ + TX_LINK_CFG_STRUC TxLinkCfg; + UINT32 Data = 0; + + + + 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, EDCA_AC0_CFG, &Data); + + Data &= 0xFFFFFF00; + /*Data |= 0x20;*/ +#ifndef WIFI_TEST + /*if ( pAd->CommonCfg.bEnableTxBurst ) */ + /* Data |= 0x60; for performance issue not set the TXOP to 0*/ +#endif + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE) +#ifdef DOT11_N_SUPPORT + && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE) +#endif /* DOT11_N_SUPPORT */ + ) + { + /* For CWC test, change txop from 0x30 to 0x20 in TxBurst mode*/ + if (pAd->CommonCfg.bEnableTxBurst) + Data |= 0x20; + } + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + +} +#endif /* DOT11_N_SUPPORT */ + +/* + ========================================================================== + 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")); + + /* 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect*/ + /* that NIC will never wakes up because TSF stops and no more */ + /* TBTT interrupts*/ + 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; + + DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n")); + + 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); +} + +/* + ========================================================================== + 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( + IN PRTMP_ADAPTER pAd) +{ + BCN_TIME_CFG_STRUC csr9; + PUCHAR ptr; + UINT i; + ULONG beaconBaseLocation = 0; + USHORT beaconLen = (USHORT) pAd->BeaconTxWI.MPDUtotalByteCount; + UINT8 TXWISize = pAd->chipCap.TXWISize; + UINT32 longptr; +#ifdef RT_BIG_ENDIAN + TXWI_STRUC localTxWI; + + NdisMoveMemory((PUCHAR)&localTxWI, (PUCHAR)&pAd->BeaconTxWI, TXWISize); + RTMPWIEndianChange(pAd, (PUCHAR)&localTxWI, TYPE_TXWI); + beaconLen = (USHORT) localTxWI.MPDUtotalByteCount; +#endif /* RT_BIG_ENDIAN */ + + DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(MPDUtotalByteCount=%d, beaconLen=%d)\n", pAd->BeaconTxWI.MPDUtotalByteCount, beaconLen)); + + + DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount)); + + 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); +} + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSetEdcaParm( + IN PRTMP_ADAPTER pAd, + IN 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; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + 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 < MaxWcidNum; 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 .*/ + /*========================================================*/ +/*#ifndef WIFI_TEST*/ + 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*/ +/*#else*/ +/* Ac0Cfg.field.AcTxop = 0; QID_AC_BE*/ +/*#endif */ + Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS; + Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS; + Ac0Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); + + Ac1Cfg.field.AcTxop = 0; /* QID_AC_BK*/ + Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS; + Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS; + Ac1Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word); + + if (pAd->CommonCfg.PhyMode == PHY_11B) + { + 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 = CW_MIN_IN_BITS; + Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS; + Ac2Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word); + Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS; + Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS; + 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 (pAd->CommonCfg.PhyMode == PHY_11B) + { + 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 = CW_MIN_IN_BITS; + CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS; + CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS; + CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS; + RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word); + + CwmaxCsr.word = 0; + CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS; + CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS; + CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS; + CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS; + 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 VIDO 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 */ + +#ifdef APCLI_SUPPORT +#ifdef APCLI_CERT_SUPPORT + if (APCLI_IF_UP_CHECK(pAd, 0) && pAd->bApCliCertTest == TRUE) + { + /* 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 /* APCLI_CERT_SUPPORT */ +#endif /* APCLI_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]; + +/*#ifdef WIFI_TEST*/ + 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]; + } /* End of if */ + } +/*#endif WIFI_TEST */ +#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 */ + +#ifdef APCLI_SUPPORT +#ifdef APCLI_CERT_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 (APCLI_IF_UP_CHECK(pAd, 0) && pAd->bApCliCertTest == TRUE) + { + if(pEdcaParm->Aifsn[QID_AC_VI] == 10) + { + Ac0Cfg.field.AcTxop = 38; + } + } +#endif /* RTMP_MAC_PCI */ +#endif /* APCLI_CERT_SUPPORT */ +#endif /* APCLI_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 */ + +#ifdef APCLI_SUPPORT +#ifdef APCLI_CERT_SUPPORT + if(APCLI_IF_UP_CHECK(pAd, 0) && pAd->bApCliCertTest == TRUE) + CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; /*for TGn wifi test*/ +#endif /* APCLI_CERT_SUPPORT */ +#endif /* APCLI_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*/ + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef APCLI_SUPPORT +#ifdef APCLI_CERT_SUPPORT + if (APCLI_IF_UP_CHECK(pAd, 0) && pAd->bApCliCertTest == TRUE) + { + 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_DEV_CONFIG_OPMODE_ON_STA(pAd) + AifsnCsr.field.Aifsn2 = 0x2; /*pEdcaParm->Aifsn[QID_AC_VI]; for WiFi WMM S4-T04.*/ + } + + } +#endif /* APCLI_CERT_SUPPORT */ +#endif /* APCLI_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; +} + +/* + ========================================================================== + 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); +} + +/* + ======================================================================== + 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; + UINT16 SharedKeyTableBase, SharedKeyModeBase; +#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])); + } +/*============================================================================================*/ + + /* fill key material - key + TX MIC + RX MIC*/ + if (BssIndex >= 8) + { + SharedKeyTableBase = SHARED_KEY_TABLE_BASE_EXT; + SharedKeyModeBase = SHARED_KEY_MODE_BASE_EXT; + BssIndex -= 8; + } + else + { + SharedKeyTableBase = SHARED_KEY_TABLE_BASE; + SharedKeyModeBase = SHARED_KEY_MODE_BASE; + } + +#ifdef RTMP_MAC_PCI + offset = SharedKeyTableBase + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE; + for (i=0; i= 8) + { + SharedKeyModeBase = SHARED_KEY_MODE_BASE_EXT; + BssIndex -= 8; + } + else + { + SharedKeyModeBase = SHARED_KEY_MODE_BASE; + } + + RTMP_IO_READ32(pAd, SharedKeyModeBase+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, SharedKeyModeBase+4*(BssIndex/2), csr1.word); + ASSERT(BssIndex < 8); + ASSERT(KeyIdx < 4); + +} + +VOID AsicUpdateWCIDIVEIV( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN ULONG uIV, + IN ULONG uEIV) +{ + ULONG offset; + + offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_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; + + /* Initialize the content of WCID Attribue */ + WCIDAttri.word = 0; + + /* The limitation of HW WCID table */ + if (/*Wcid < 1 ||*/ Wcid > 254) + { + DBGPRINT(RT_DEBUG_WARN, ("%s: Wcid is invalid (%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 = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE); + RTMP_IO_WRITE32(pAd, offset, WCIDAttri.word); + + DBGPRINT(RT_DEBUG_TRACE, ("%s : WCID #%d, KeyIndex #%d, Alg=%s\n", __FUNCTION__, Wcid, KeyIdx, CipherName[CipherAlg])); + DBGPRINT(RT_DEBUG_TRACE, (" WCIDAttri = 0x%x \n", WCIDAttri.word)); + +} + + +/* + ======================================================================== + 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; + PUCHAR pKey = pCipherKey->Key; + PUCHAR pTxMic = pCipherKey->TxMic; + PUCHAR pRxMic = pCipherKey->RxMic; + UCHAR CipherAlg = pCipherKey->CipherAlg; +#ifdef RTMP_MAC_PCI +#ifdef SPECIFIC_BCN_BUF_SUPPORT + unsigned long irqFlag = 0; +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + +#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 */ + /* EKEY*/ + offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE); +#ifdef RTMP_MAC_PCI + for (i=0; ichipOps.sendCommandToMcu) + return pAd->chipOps.sendCommandToMcu(pAd, Command, Token, Arg0, Arg1, in_atomic); + else + return FALSE; +} + + +BOOLEAN AsicSendCommandToMcuBBP( + IN PRTMP_ADAPTER pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1, + IN BOOLEAN FlgIsNeedLocked) +{ + 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) */ +#ifdef RT2883 + case RFIC_2853: +#endif /* RT2883 */ + 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)) + { + ULONG offset; + + offset = WAPI_PN_TABLE_BASE + (WCID * WAPI_PN_ENTRY_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 (pAd->bCalibrationDone == FALSE) + return; +#endif /* RT6352 */ + +#ifdef RTMP_INTERNAL_TX_ALC +#ifdef RT5350 + if (pAd->TxPowerCtrl.bInternalTxALC == TRUE) + { + UCHAR BbpR47 = 0; + + //TSSI_REPORT_SEL = 0 + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpR47); + BbpR47 &= ~0x3; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BbpR47 ); + } +#endif /* RT5350 */ +#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; + +#ifdef RT6352 + case VCO_CAL_MODE_3: + 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); + break; +#endif /* RT6352 */ + + default: + return; + } + + RtmpOsMsDelay(2); + + 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 */ + ) + { + ITxBFDividerCalibration(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 * 4; + 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( + IN 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); + } +} + + +/* Enable the stream mode*/ + +/* Parameters*/ +/* pAd: The adapter data structure*/ + +/* Return Value:*/ +/* None*/ + +VOID AsicEnableStreamMode( + IN PRTMP_ADAPTER pAd) +{ + TX_CHAIN_ADDR0_L_STRUC TxChainAddr0L = {{0}}; + TX_CHAIN_ADDR0_H_STRUC TxChainAddr0H = {{0}}; + TX_CHAIN_ADDR1_H_STRUC TxChainAddr1H = {{0}}; + TX_CHAIN_ADDR2_H_STRUC TxChainAddr2H = {{0}}; + TX_CHAIN_ADDR3_H_STRUC TxChainAddr3H = {{0}}; + + DBGPRINT(RT_DEBUG_INFO, ("---> %s\n", __FUNCTION__)); + + /* Chain #0 for broadcast*/ + TxChainAddr0L.field.TxChainAddr0L_Byte3 = 0xFF; + TxChainAddr0L.field.TxChainAddr0L_Byte2 = 0xFF; + TxChainAddr0L.field.TxChainAddr0L_Byte1 = 0xFF; + TxChainAddr0L.field.TxChainAddr0L_Byte0 = 0xFF; + RTMP_IO_WRITE32(pAd, TX_CHAIN_ADDR0_L, TxChainAddr0L.word); + + RTMP_IO_READ32(pAd, TX_CHAIN_ADDR0_H, &TxChainAddr0H.word); + TxChainAddr0H.field.TxChainAddr0H_Byte4 = 0xFF; + TxChainAddr0H.field.TxChainAddr0H_Byte5 = 0xFF; + TxChainAddr0H.field.TxChainSel0 = 0xF; /* Enable the stream mode for chain #0*/ + RTMP_IO_WRITE32(pAd, TX_CHAIN_ADDR0_H, TxChainAddr0H.word); + + RTMP_IO_READ32(pAd, TX_CHAIN_ADDR1_H, &TxChainAddr1H.word); + TxChainAddr1H.field.TxChainSel0 = 0xF; /* Enable the stream mode for chain #1*/ + RTMP_IO_WRITE32(pAd, TX_CHAIN_ADDR1_H, TxChainAddr1H.word); + + RTMP_IO_READ32(pAd, TX_CHAIN_ADDR2_H, &TxChainAddr2H.word); + TxChainAddr2H.field.TxChainSel0 = 0xF; /* Enable the stream mode for chain #2*/ + RTMP_IO_WRITE32(pAd, TX_CHAIN_ADDR2_H, TxChainAddr2H.word); + + RTMP_IO_READ32(pAd, TX_CHAIN_ADDR3_H, &TxChainAddr3H.word); + TxChainAddr3H.field.TxChainSel0 = 0xF; /* Enable the stream mode for chain #3*/ + RTMP_IO_WRITE32(pAd, TX_CHAIN_ADDR3_H, TxChainAddr3H.word); + + DBGPRINT(RT_DEBUG_INFO, ("<--- %s\n", __FUNCTION__)); +} + + +/* Disable the stream mode*/ + +/* Parameters*/ +/* pAd: The adapter data structure*/ + +/* Return Value:*/ +/* None*/ + +VOID AsicDisableStreamMode( + IN PRTMP_ADAPTER pAd) +{ + TX_CHAIN_ADDR0_L_STRUC TxChainAddr0L = {{0}}; + TX_CHAIN_ADDR0_H_STRUC TxChainAddr0H = {{0}}; + TX_CHAIN_ADDR1_H_STRUC TxChainAddr1H = {{0}}; + TX_CHAIN_ADDR2_H_STRUC TxChainAddr2H = {{0}}; + TX_CHAIN_ADDR3_H_STRUC TxChainAddr3H = {{0}}; + + DBGPRINT(RT_DEBUG_INFO, ("---> %s\n", __FUNCTION__)); + + /* Chain #0 for broadcast*/ + TxChainAddr0L.field.TxChainAddr0L_Byte3 = 0xFF; + TxChainAddr0L.field.TxChainAddr0L_Byte2 = 0xFF; + TxChainAddr0L.field.TxChainAddr0L_Byte1 = 0xFF; + TxChainAddr0L.field.TxChainAddr0L_Byte0 = 0xFF; + RTMP_IO_WRITE32(pAd, TX_CHAIN_ADDR0_L, TxChainAddr0L.word); + + RTMP_IO_READ32(pAd, TX_CHAIN_ADDR0_H, &TxChainAddr0H.word); + TxChainAddr0H.field.TxChainAddr0H_Byte4 = 0xFF; + TxChainAddr0H.field.TxChainAddr0H_Byte5 = 0xFF; + TxChainAddr0H.field.TxChainSel0 = 0x0; /* Disable the stream mode for chain #0*/ + RTMP_IO_WRITE32(pAd, TX_CHAIN_ADDR0_H, TxChainAddr0H.word); + + RTMP_IO_READ32(pAd, TX_CHAIN_ADDR1_H, &TxChainAddr1H.word); + TxChainAddr1H.field.TxChainSel0 = 0x0; /* Disable the stream mode for chain #1*/ + RTMP_IO_WRITE32(pAd, TX_CHAIN_ADDR1_H, TxChainAddr1H.word); + + RTMP_IO_READ32(pAd, TX_CHAIN_ADDR2_H, &TxChainAddr2H.word); + TxChainAddr2H.field.TxChainSel0 = 0x0; /* Disable the stream mode for chain #2*/ + RTMP_IO_WRITE32(pAd, TX_CHAIN_ADDR2_H, TxChainAddr2H.word); + + RTMP_IO_READ32(pAd, TX_CHAIN_ADDR3_H, &TxChainAddr3H.word); + TxChainAddr3H.field.TxChainSel0 = 0x0; /* Disable the stream mode for chain #3*/ + RTMP_IO_WRITE32(pAd, TX_CHAIN_ADDR3_H, TxChainAddr3H.word); + + DBGPRINT(RT_DEBUG_INFO, ("<--- %s\n", __FUNCTION__)); +} +#endif // STREAM_MODE_SUPPORT // + + +#ifdef DOT11_N_SUPPORT +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicEnableRalinkBurstMode( + IN PRTMP_ADAPTER pAd) +{ + UINT32 Data = 0; + + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + pAd->CommonCfg.RestoreBurstMode = Data; + Data &= 0xFFF00000; + Data |= 0x86380; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicDisableRalinkBurstMode( + IN PRTMP_ADAPTER pAd) +{ + UINT32 Data = 0; + + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + + 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); +} +#endif // DOT11_N_SUPPORT // + + +VOID RtmpUpdateFilterCoefficientControl( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel) +{ + UCHAR BBPValue = 0; + + if (Channel == 14) + { + if (pAd->CommonCfg.PhyMode == PHY_11B) + { + /* when Channel==14 && Mode==CCK && BandWidth==20M, BBP R4 bit5=1 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue |= 0x20; /* set bit5=1 */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + } + else + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + } + } +} + +#ifdef WOW_SUPPORT +#endif /* WOW_SUPPORT */ + +#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, ("===> AsicSetApCliBssid %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_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 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 */ + diff --git a/mt7620/src/common/cmm_cal.c.bak b/mt7620/src/common/cmm_cal.c.bak new file mode 100755 index 0000000..f36ace9 --- /dev/null +++ b/mt7620/src/common/cmm_cal.c.bak @@ -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-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}, +}; + +UCHAR RT6352_VGA_TABLE_PARMS = (sizeof(RT6352_VGA_TABLE) / sizeof(REG_PAIR)); + +INT32 CalcCalibration( + IN PRTMP_ADAPTER pAd, + IN COMPLEX_VALUE iqData[][3], + IN INT numSamples) +{ + UCHAR ii; + INT32 sum = 0; + + for (ii= 0; ii < numSamples ; ii++) + { + sum += iqData[ii][0].q; + } + + return (sum / 16); +} + +INT32 CalcRCalibrationCode( + IN PRTMP_ADAPTER pAd, + IN INT32 D1, + IN INT32 D2) +{ + INT32 CalCode, CalCode1; + + CalCode = ((D2 - D1) * 1000) / 48; + CalCode1 = CalCode % 10; + CalCode = ((D2 - D1) * 100) / 48; + + if (CalCode1 >= 5) + CalCode++; + + return CalCode; +} + +UINT32 *DataCapSaveMacData( + IN 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= 0x8000) SMM_Addr = SMM_Addr - 0x4000; + + RTMP_IO_READ32(pAd, PKT_Addr, &PKT1.Value); + //printk("PKT1 are 0x%08X \n", PKT1.Value); + PKT_Addr += 4; + if (PKT_Addr >= 0x10000) PKT_Addr = PKT_Addr - 0x8000; + + RTMP_IO_READ32(pAd, PKT_Addr, &PKT2.Value); + //printk("PKT2 are 0x%08X \n", PKT2.Value); + PKT_Addr += 4; + if (PKT_Addr >= 0x10000) PKT_Addr = PKT_Addr - 0x8000; + + /* Reorder samples so iqData[i][0] is Ant0, iqData[i][1] is Ant1, iqData[i][2] is Ant2 */ + if (IS_RT6352(pAd)) + { + iqData[i][2].i = SMM.field.BYTE1; + iqData[i][2].q = SMM.field.BYTE0; + iqData[i][1].i = PKT1.field.BYTE3; + iqData[i][1].q = PKT1.field.BYTE2; + iqData[i][0].i = PKT1.field.BYTE1; + iqData[i][0].q = PKT1.field.BYTE0; + if (++i >= numSamples) + break; + + iqData[i][2].i = SMM.field.BYTE3; + iqData[i][2].q = SMM.field.BYTE2; + iqData[i][1].i = PKT2.field.BYTE3; + iqData[i][1].q = PKT2.field.BYTE2; + iqData[i][0].i = PKT2.field.BYTE1; + iqData[i][0].q = PKT2.field.BYTE0; + } + else + { + iqData[i][2].i = SMM.field.BYTE0; + iqData[i][2].q = SMM.field.BYTE1; + iqData[i][1].i = PKT1.field.BYTE2; + iqData[i][1].q = PKT1.field.BYTE3; + iqData[i][0].i = PKT1.field.BYTE0; + iqData[i][0].q = PKT1.field.BYTE1; + if (++i >= numSamples) + break; + + iqData[i][2].i = SMM.field.BYTE2; + iqData[i][2].q = SMM.field.BYTE3; + iqData[i][1].i = PKT2.field.BYTE2; + iqData[i][1].q = PKT2.field.BYTE3; + iqData[i][0].i = PKT2.field.BYTE0; + iqData[i][0].q = PKT2.field.BYTE1; + } + } + + return; +} + + +/* + DumpCaptureData - Display capture data + iqData - 3 channels of IQ data + numSamples - number of samples to display +*/ +VOID DumpCaptureData( + IN COMPLEX_VALUE iqData[][3], + IN INT StartIndex, + IN INT numSamples) +{ + int i; + + for (i = StartIndex; i < (StartIndex + numSamples); i++) + { + DBGPRINT(RT_DEBUG_WARN, ("%4d\t%4d\t%4d\t%4d\t%4d\t%4d\n", + iqData[i][0].i, iqData[i][0].q, + iqData[i][1].i, iqData[i][1].q, + iqData[i][2].i, iqData[i][2].q)); + } +} + +VOID CaptureDataMode( + IN PRTMP_ADAPTER pAd, + IN COMPLEX_VALUE iqData[][3]) +{ + UINT32 saveSysCtrl, savePbfCfg; + UINT32 capCtrl, i_count, CaptureStartAddr; + UINT8 saveBbp21, saveBbp196, BbpReg; + UINT32 CaptureModeOffset = 0x200; + + /* Disable Tx/Rx */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x00); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpReg); + BbpReg |= 0x04; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpReg); + + /* Disable Tx/Rx Queue */ + RTMP_IO_READ32(pAd, PBF_CFG, &savePbfCfg); + RTMP_IO_WRITE32(pAd, PBF_CFG, 0x00000000); + + /* Enable PBF/MAC/DMA clock. */ + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x2E00); + + /* Change the PBF SRAM from normal mode to BBP capture mode */ + RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &capCtrl); + capCtrl |= 0x4000; + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, capCtrl); + + /* Data scope indirect index */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R251, 0x64); + /* ADC capture is selected */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R252, 0x0); + + /* Save BBP Register */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x0); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R196, &saveBbp196); + /* Disable Packet detection */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, 0x80); + + /* IB-INTF indirect index */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R142, 0x10); + /* Manual Rx Enable */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R143, 0x01); + + /* Setup the trigger offset time */ + RTMP_IO_READ32(pAd, PBF_CAP_CTRL, &capCtrl); + capCtrl &= (~0x80008000); //set bit[31]=0, bit[15]=0 for ADC 8 + RTMP_IO_WRITE32(pAd, PBF_CAP_CTRL, capCtrl); + + /* trigger offset */ + RTMP_IO_READ32(pAd, PBF_CAP_CTRL, &capCtrl); + capCtrl &= ~(0x1FFF0000); + RTMP_IO_WRITE32(pAd, PBF_CAP_CTRL, capCtrl); + + if ((CaptureModeOffset > 0) && (CaptureModeOffset <= 0x1FFF)) + { + RTMP_IO_READ32(pAd, PBF_CAP_CTRL, &capCtrl); + capCtrl |= CaptureModeOffset << 16; + RTMP_IO_WRITE32(pAd, PBF_CAP_CTRL, capCtrl); + } + + /* start capturing */ + RTMP_IO_READ32(pAd, PBF_CAP_CTRL, &capCtrl); + capCtrl |= 0x40000000; + RTMP_IO_WRITE32(pAd, PBF_CAP_CTRL, capCtrl); + + RtmpOsMsDelay(100); + + /* Manual Trigger Enable */ + RTMP_IO_READ32(pAd, PBF_CAP_CTRL, &capCtrl); + capCtrl |= 0x20000000; + RTMP_IO_WRITE32(pAd, PBF_CAP_CTRL, capCtrl); + + RtmpOsMsDelay(100); + + /* Wait up to 1ms for capture buffer to fill */ + for (i_count=0; i_count < 1000; i_count++) + { + RTMP_IO_READ32(pAd, PBF_CAP_CTRL, &capCtrl); + if ((capCtrl & 0x40000000)==0) + break; + RTMPusecDelay(50); + } + + if (i_count >= 1000) + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Monitor the finish of capturing fail !!!\n", __FUNCTION__)); + + /* Read [0x440] bit[12:0] */ + RTMP_IO_READ32(pAd, PBF_CAP_CTRL, &CaptureStartAddr); + DBGPRINT(RT_DEBUG_WARN, ("PBF_CAP_CTRL = %08x\n", CaptureStartAddr)); + + CaptureStartAddr = CaptureStartAddr & 0x00001FFF; + + printk("0. CaptureStartAddr is 0x%lx \n", CaptureStartAddr); + + RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &saveSysCtrl); + saveSysCtrl &= (~0x00004000); + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, saveSysCtrl); + + ReadCaptureDataFromMemory(pAd, iqData, MAX_CAPTURE_LENGTH); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R195, 0x0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R196, saveBbp196); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R142, 0x10); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R143, 0x0); + + /* reset packet buffer */ + RTMP_IO_WRITE32(pAd, PBF_CTRL, 0x00000020); + + RTMP_IO_WRITE32(pAd, PBF_CFG, savePbfCfg); + + return; +} + + +VOID R_Calibration( + IN PRTMP_ADAPTER pAd) +{ + UINT32 saveMacSysCtrl, saveSysCtrl, CaptureStartAddr; + UINT32 savePbfCfg, saveDmaCtrl; + UINT32 saveMacPwrPinCfg; + UINT32 saveRfByPass0, saveRfByPass1, saveRfByPass2; + UINT32 saveRfControl0, saveRfControl2; + UCHAR saveRfB0R1, saveRfB0R34, saveRfB0R35; + UCHAR saveRfB5R4, saveRfB5R17, saveRfB5R18; + UCHAR saveRfB5R19, saveRfB5R20; + UCHAR saveRfCfg, ii, byteValue = 0; + INT32 sum = 0, D1 = 0, D2 = 0; + INT32 RCalCode; + + PCAP_IQ_DATA capIqData = NULL; + INT allocSize = MAX_CAPTURE_LENGTH * sizeof(COMPLEX_VALUE) * 3; + + /* Allocate buffer for capture data */ + capIqData = (PCAP_IQ_DATA) kmalloc(allocSize, MEM_ALLOC_FLAG); + + if (capIqData == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__)); + return; + } + + /* Save MAC registers */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &saveMacSysCtrl); + RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &saveSysCtrl); + RTMP_IO_READ32(pAd, PBF_CFG, &savePbfCfg); + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &saveDmaCtrl); + RTMP_IO_READ32(pAd, PWR_PIN_CFG, &saveMacPwrPinCfg); + + { + UINT32 dmaCfg, macCfg, macStatus, txrxPgcnt; + UINT32 DTxCycle, DRxCycle, MTxCycle, MRxCycle; + ULONG stTime, dt_time, dr_time, mt_time, mr_time; + + DTxCycle = DRxCycle = MTxCycle = MRxCycle = 0; + RTMP_IO_READ32(pAd, 0x438, &txrxPgcnt); + + /* Disable DMA Tx and wait DMA Tx status in idle state */ + NdisGetSystemUpTime(&stTime); + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &dmaCfg); + dmaCfg &= (~0x1); + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, dmaCfg); + for (DTxCycle = 0; DTxCycle < 10000; DTxCycle++) + { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &dmaCfg); + if (dmaCfg & 0x2) + RTMPusecDelay(50); + else + break; + } + NdisGetSystemUpTime(&dt_time); + dt_time -= stTime; + if (DTxCycle == 10000) + { + DBGPRINT(RT_DEBUG_WARN, ("%s(cnt=%d,time=0x%lx):stop DTx,dmaCfg=%d!\n", + __FUNCTION__, DTxCycle, dt_time, dmaCfg)); + } + + /* stop PBF txQ */ + RTMP_IO_WRITE32(pAd, PBF_CFG, (savePbfCfg & (~0x14))); + + /* 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)); + } + + /* stop PBF rxQ */ + RTMP_IO_WRITE32(pAd, PBF_CFG, (savePbfCfg & (~0x1e))); + + /* Disable DMA Rx */ + NdisGetSystemUpTime(&stTime); + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &dmaCfg); + dmaCfg &= (~0x4); + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, dmaCfg); + for (DRxCycle = 0; DRxCycle < 10000; DRxCycle++) + { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &dmaCfg); + if (dmaCfg & 0x8) + RTMPusecDelay(50); + else + break; + } + NdisGetSystemUpTime(&dr_time); + dr_time -= stTime; + if (DRxCycle == 10000) + { + DBGPRINT(RT_DEBUG_WARN, ("%s(cnt=%d,time=0x%lx):stop DRx, dmaCfg=%d!\n", + __FUNCTION__, DRxCycle, dr_time, dmaCfg)); + } + } + + /* 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); + + /* Enable PBF/MAC/DMA clock. */ + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x2E00); + + /* Disable Tx/Rx */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x7000); + + /* RF bypass MAC */ + RTMP_IO_WRITE32(pAd, RF_BYPASS0, 0x0000FFFF); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x0000000A); + + RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x00000001); + + RTMP_IO_WRITE32(pAd, RF_BYPASS1, 0x00007FFF); + RTMP_IO_WRITE32(pAd, RF_BYPASS2, 0x00003331); + RTMP_IO_WRITE32(pAd, RF_CONTROL2, 0x00003031); + + 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); + + 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); + + CaptureDataMode(pAd, capIqData); + DumpCaptureData(capIqData, 0, 512); + + D1 = CalcCalibration(pAd, capIqData, 16); + + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R35, 0x01); + + CaptureDataMode(pAd, capIqData); + DumpCaptureData(capIqData, 0, 512); + + D2 = CalcCalibration(pAd, capIqData, 16); + + RCalCode = CalcRCalibrationCode(pAd, D1, D2); + + printk("D1 = %d, D2 = %d, CalCode = %d !!!\n", D1, D2, RCalCode); + +#if 0 + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R07, RCalCode); +#endif + + /* 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_READ8_BY_REG_ID(pAd, BBP_R4, &byteValue); + byteValue &= (~0x18); + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + byteValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, byteValue); + + /* Restore registers */ + RTMP_IO_WRITE32(pAd, RF_BYPASS0, 0x0); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x0); + RTMP_IO_WRITE32(pAd, RF_BYPASS1, 0x0); + RTMP_IO_WRITE32(pAd, RF_BYPASS2, 0x0); + RTMP_IO_WRITE32(pAd, RF_CONTROL2, 0x0); + + /* Return to normal mode */ + RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, saveMacPwrPinCfg); + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, saveSysCtrl); + RTMP_IO_WRITE32(pAd, PBF_CFG, savePbfCfg); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, saveMacSysCtrl); + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, saveDmaCtrl); + + if (capIqData != NULL) + os_free_mem(pAd, capIqData); +} + +VOID R_Calibration_2( + IN PRTMP_ADAPTER pAd) +{ + UINT32 saveMacSysCtrl, saveSysCtrl, CaptureStartAddr; + UINT32 savePbfCfg, saveDmaCtrl; + UINT32 saveMacPwrPinCfg; + UINT32 saveRfByPass0, saveRfByPass1, saveRfByPass2; + UINT32 saveRfControl0, saveRfControl2; + UCHAR saveRfB0R1, saveRfB0R34, saveRfB0R35; + UCHAR saveRfB5R4, saveRfB5R17, saveRfB5R18; + UCHAR saveRfB5R19, saveRfB5R20; + UCHAR saveRfCfg, ii, byteValue = 0; + INT32 sum = 0; + INT32 RCalCode; + CHAR D1 = 0, D2 = 0; + + /* Save MAC registers */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &saveMacSysCtrl); + RTMP_IO_READ32(pAd, PBF_CFG, &savePbfCfg); + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &saveDmaCtrl); + + { + UINT32 dmaCfg, macCfg, macStatus, txrxPgcnt; + UINT32 DTxCycle, DRxCycle, MTxCycle, MRxCycle; + ULONG stTime, dt_time, dr_time, mt_time, mr_time; + + DTxCycle = DRxCycle = MTxCycle = MRxCycle = 0; + RTMP_IO_READ32(pAd, 0x438, &txrxPgcnt); + + /* Disable DMA Tx and wait DMA Tx status in idle state */ + NdisGetSystemUpTime(&stTime); + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &dmaCfg); + dmaCfg &= (~0x1); + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, dmaCfg); + for (DTxCycle = 0; DTxCycle < 10000; DTxCycle++) + { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &dmaCfg); + if (dmaCfg & 0x2) + RTMPusecDelay(50); + else + break; + } + NdisGetSystemUpTime(&dt_time); + dt_time -= stTime; + if (DTxCycle == 10000) + { + DBGPRINT(RT_DEBUG_WARN, ("%s(cnt=%d,time=0x%lx):stop DTx,dmaCfg=%d!\n", + __FUNCTION__, DTxCycle, dt_time, dmaCfg)); + } + + /* stop PBF txQ */ + RTMP_IO_WRITE32(pAd, PBF_CFG, (savePbfCfg & (~0x14))); + + /* 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)); + } + + /* stop PBF rxQ */ + RTMP_IO_WRITE32(pAd, PBF_CFG, (savePbfCfg & (~0x1e))); + + /* Disable DMA Rx */ + NdisGetSystemUpTime(&stTime); + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &dmaCfg); + dmaCfg &= (~0x4); + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, dmaCfg); + for (DRxCycle = 0; DRxCycle < 10000; DRxCycle++) + { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &dmaCfg); + if (dmaCfg & 0x8) + RTMPusecDelay(50); + else + break; + } + NdisGetSystemUpTime(&dr_time); + dr_time -= stTime; + if (DRxCycle == 10000) + { + DBGPRINT(RT_DEBUG_WARN, ("%s(cnt=%d,time=0x%lx):stop DRx, dmaCfg=%d!\n", + __FUNCTION__, DRxCycle, dr_time, dmaCfg)); + } + } + + /* 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); + + 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_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, 0x04); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, 0x80); + RTMPusecDelay(50); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &byteValue); + if (byteValue > 127) + 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(50); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &byteValue); + if (byteValue > 127) + D2= byteValue - 256; + else + D2 = (CHAR)byteValue; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, 0x0); + + RCalCode = CalcRCalibrationCode(pAd, D1, D2); + + printk("D1 = %d, D2 = %d, CalCode = %d !!!\n", D1, D2, RCalCode); + +#if 0 + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R07, RCalCode); +#endif + + /* 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); + + 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); + + /* Return to normal mode */ + RTMP_IO_WRITE32(pAd, PBF_CFG, savePbfCfg); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, saveMacSysCtrl); + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, saveDmaCtrl); +} + + +INT Set_TestRCalibration_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + printk("TestRCalibration !!!\n"); + R_Calibration(pAd); + + return TRUE; +} + +VOID RtmpKickOutHwNullFrame( + IN PRTMP_ADAPTER pAd) +{ + UINT8 TXWISize = pAd->chipCap.TXWISize; + TXWI_STRUC NullTxWI; + PTXWI_STRUC pTxWI;; + 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; + + NState = MlmeAllocateMemory(pAd, (PUCHAR *)&pNullFrame); + + NdisZeroMemory(pNullFrame, 48); + NdisZeroMemory(pTxWI, TXWISize); + + if (NState == NDIS_STATUS_SUCCESS) + { + pTxWI = &NullTxWI; + pNullFr = (PHEADER_802_11) pNullFrame; + Length = sizeof(HEADER_802_11); + + pNullFr->FC.Type = BTYPE_DATA; + pNullFr->FC.SubType = SUBTYPE_NULL_FUNC; + 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->CommonCfg.Bssid); + + 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, + FALSE, + &MlmeTransmit); + + pTxWI->MCS = 15; + pTxWI->PHYMODE = MODE_HTMIX; + pTxWI->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); + + /* kick NULL frame #0 */ + RTMP_IO_WRITE32(pAd, PBF_CTRL, 0x80); + + /* Check MAC Tx/Rx idle */ + for (k_count = 0; k_count < 10000; k_count++) + { + RTMP_IO_READ32(pAd, PBF_CTRL, &macStatus); + if (macStatus & 0x80) + RTMPusecDelay(50); + else + break; + } + + if (k_count == 10000) + { + DBGPRINT(RT_DEBUG_ERROR, ("Wait Null Frame SendOut to MAX !!!\n")); + } +} + + +BOOLEAN DPD_Calibration( + IN PRTMP_ADAPTER pAd, + IN UCHAR AntIdx) +{ + UCHAR index, Max_Retry = 0, Pass_Thres = 0,byteValue = 0; + UINT32 RF_ALC0 = 0, RF_ALC1 = 0, macStatus; + CHAR TxPwer = 0, TxPwer2 = 0; + UINT32 saveMacSysCtrl, saveSysCtrl, saveTxPinCfg; + USHORT AM_SUM =0, AM_10 = 0, k_count = 0; + BOOLEAN DPD_Cal_success = FALSE; + UCHAR saveBbpR27, saveBbpR65, SaveBbpR66; + UCHAR saveBbpR242, saveBbpR244; + UCHAR saveRfB0R1; + UCHAR saveRfB4R19, saveRfB4R21, saveRfB4R22; + UCHAR saveRfB5R17, saveRfB5R18, saveRfB5R19, saveRfB5R20; + UCHAR saveRfB6R19, saveRfB6R21, saveRfB6R22; + UCHAR saveRfB7R17, saveRfB7R18, saveRfB7R19, saveRfB7R20; + UCHAR VGA_Upper_Bound, VGA_Lower_Bound, AM_63 = 0; + UCHAR VGA_code = 0; + CHAR VGA_code_idx = 0; + + /* 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 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_READ8_BY_REG_ID(pAd, BBP_R66, &SaveBbpR66); + 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_R19, &saveRfB4R19); + RT635xReadRFRegister(pAd, RF_BANK4, RF_R21, &saveRfB4R21); + RT635xReadRFRegister(pAd, RF_BANK4, RF_R22, &saveRfB4R22); + 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_R19, &saveRfB6R19); + RT635xReadRFRegister(pAd, RF_BANK6, RF_R21, &saveRfB6R21); + RT635xReadRFRegister(pAd, RF_BANK6, RF_R22, &saveRfB6R22); + 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 0 + for (index = 0; index < MAX_NUM_OF_CHANNELS; index++) + { + if (pAd->CommonCfg.CentralChannel == pAd->TxPower[index].Channel) + { + TxPwer = pAd->TxPower[index].Power; + TxPwer2 = pAd->TxPower[index].Power2; + break; + } + } + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + PATE_INFO pATEInfo = &(pAd->ate); + + TxPwer = pATEInfo->TxPower0; + TxPwer2 = pATEInfo->TxPower1; + } +#endif /* RALINK_ATE */ +#endif + + /* 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; + } + + switch (AntIdx) + { + case 0: +#if 0 + /* Set ALC code to the nominal value and kick the value to BBP and RF */ + RF_ALC0 = ((TxPwer /12) << 2) + ((TxPwer % 12) / 4); + + RTMP_IO_WRITE32(pAd, RF_BYPASS3, 0xF0); + + RF_ALC0 = (RF_ALC0 << 4); + RTMP_IO_WRITE32(pAd, RF_CONTROL3, RF_ALC0); +#endif + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x04); + RtmpKickOutHwNullFrame(pAd); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x00); + + /* Setup the MAC to Transmit-Idle Mode through MAC registers */ + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0x000C0020); + + /* Connect RF loopback through MAC registers */ + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, 0x41); + 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, 0x17); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R22, 0xA1); + break; + + case 1: +#if 0 + /* Set ALC code to the nominal value and kick the value to BBP and RF */ + RF_ALC1 = ((TxPwer2 /12) << 2) + ((TxPwer2 % 12) / 4); + + RTMP_IO_WRITE32(pAd, RF_BYPASS3, 0xF000); + + RF_ALC1 = (RF_ALC0 << 12); + RTMP_IO_WRITE32(pAd, RF_CONTROL3, RF_ALC1); +#endif + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x04); + RtmpKickOutHwNullFrame(pAd); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x00); + + /* Setup the MAC to Transmit-Idle Mode through MAC registers */ + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0x000C0080); + + /* Connect RF loopback through MAC registers */ + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, 0x42); + 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, 0x17); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R22, 0xA1); + break; + + default: + break; + } + + /* Set BBP DPD parameters through MAC registers */ + if (AntIdx == 0) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, 0x00); + else + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x00); + 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); + 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)) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, 0x00); + VGA_code = RT6352_VGA_TABLE[VGA_code_idx].Value; + DBGPRINT(RT_DEBUG_WARN, ("VGA Gain(%d), R66(%x)\n", RT6352_VGA_TABLE[VGA_code_idx].Register, VGA_code)); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, VGA_code); + + /* Turn on debug tone and start DPD calibration through MAC registers */ + 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) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x80); + else + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x82); + + /* 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_WARN, ("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 + 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) !!!\n", VGA_code_idx)); + 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, 0x43); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R188, &byteValue); + AM_10 = byteValue; + + DBGPRINT(RT_DEBUG_WARN, ("AM_SUM = %d, AM_10 = %d !!!\n", AM_SUM, AM_10)); + + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x01); + + 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, &byteValue); + DBGPRINT(RT_DEBUG_WARN, ("%s(): AM[%d] = %d !\n", __FUNCTION__, k_count, byteValue)); + } + } + + if ((AM_SUM - ((11 * AM_10) / 2)) < Pass_Thres) + { + if (AntIdx == 0) + DBGPRINT(RT_DEBUG_WARN, ("DPD Calibration Pass for TX0 !!!\n")); + else + DBGPRINT(RT_DEBUG_WARN, ("DPD Calibration Pass for TX1 !!!\n")); + + DPD_Cal_success = TRUE; + break; + } + + if (index == 3) + { + Pass_Thres += 3; + } + } + + /* Restore RF registers */ + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, saveRfB0R1); + if (AntIdx == 0) + { + 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_R19, saveRfB4R19); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R21, saveRfB4R21); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R22, saveRfB4R22); + } + else + { + 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_R19, saveRfB6R19); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R21, saveRfB6R21); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R22, saveRfB6R22); + } + + /* 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); + + if (pATEInfo->TxWI.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_R27, saveBbpR27); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R65, saveBbpR65); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, SaveBbpR66); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R242, saveBbpR242); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, saveBbpR244); + + /* Resore MAC registers */ + RTMP_IO_WRITE32(pAd, RF_CONTROL3, 0x0); + RTMP_IO_WRITE32(pAd, RF_BYPASS3, 0x0); + + /* Reset MAC soft-reset */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x01); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); + + /* Restore TX PIN CFG registers */ + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, saveTxPinCfg); + + /* Restore MAC SYS CTRL registers */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, saveMacSysCtrl); + +#ifdef RALINK_ATE + if (!ATE_ON(pAd)) + RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW); +#endif /* RALINK_ATE */ + + return DPD_Cal_success; +} + +VOID DoDPDCalibration( + IN PRTMP_ADAPTER pAd) +{ + BOOLEAN Ant0 = FALSE, Ant1 = FALSE; + UCHAR byteValue = 0; +#ifdef RALINK_ATE + UCHAR saveBbpR1 = 0, saveRfB0R2 = 0, BBPValue = 0, RFValue = 0; +#endif /* RALINK_ATE */ + + printk(" 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); + 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 & Ant1) + { + /* 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, 0x03); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x03); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + 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); + + 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); + + if (pATEInfo->TxWI.BW == BW_40) + byteValue |= 0x10; + } +#endif /* RALINK_ATE */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, byteValue); + + printk(" 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, 0x40); + } +} + +INT Set_TestDPDCalibration_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + printk("TestDPDCalibration !!!\n"); + + 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); + + DoDPDCalibration(pAd); + + return TRUE; +} + +INT Set_TestDPDCalibrationTX0_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + BOOLEAN Ant0 = FALSE; + UCHAR byteValue = 0; +#ifdef RALINK_ATE + UCHAR saveBbpR1 = 0, saveRfB0R2 = 0, BBPValue = 0, RFValue = 0; +#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); + + printk("TestDPDCalibrationTX0 !!!\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); + +#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) + { + /* 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, 0x03); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x03); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + 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); + + 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); + + if (pATEInfo->TxWI.BW == BW_40) + byteValue |= 0x10; + } +#endif /* RALINK_ATE */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, byteValue); + + printk(" 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, 0x40); + } + + return TRUE; +} + +INT Set_TestDPDCalibrationTX1_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + BOOLEAN Ant1 = FALSE; + UCHAR byteValue = 0; +#ifdef RALINK_ATE + UCHAR saveBbpR1 = 0, saveRfB0R2 = 0, BBPValue = 0, RFValue = 0; +#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); + + printk("TestDPDCalibrationTX1 !!!\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 */ + + 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) + { + /* 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, 0x03); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x03); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R189, 0x0F); + 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); + + 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); + + if (pATEInfo->TxWI.BW == BW_40) + byteValue |= 0x10; + } +#endif /* RALINK_ATE */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, byteValue); + + printk(" 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, 0x40); + } + + return TRUE; +} + diff --git a/mt7620/src/common/cmm_cfg.c b/mt7620/src/common/cmm_cfg.c new file mode 100644 index 0000000..1cc5f7a --- /dev/null +++ b/mt7620/src/common/cmm_cfg.c @@ -0,0 +1,1738 @@ +/**************************************************************************** + * 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].CurrentAddress, MAC_ADDR_LEN); + else +#endif /* APCLI_SUPPORT */ + NdisMoveMemory(&macAddr[0], pAd->ApCfg.MBSSID[apidx].Bssid, 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 */ + +#ifdef P2P_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_P2P_GO) + NdisMoveMemory(&macAddr[0], pAd->P2PCurrentAddress, MAC_ADDR_LEN); + + if (bFromApcli) + { + APCLI_MR_APIDX_SANITY_CHECK(apidx); + NdisMoveMemory(&macAddr[0], pAd->ApCfg.ApCliTab[apidx].CurrentAddress, MAC_ADDR_LEN); + } +#endif /* P2P_SUPPORT */ + iPin = macAddr[3] * 256 * 256 + macAddr[4] * 256 + macAddr[5]; + + iPin = iPin % 10000000; + + + checksum = ComputeChecksum( iPin ); + iPin = iPin*10 + checksum; + + return iPin; +} + +char* GetPhyMode( + int Mode) +{ + switch(Mode) + { + case MODE_CCK: + return "CCK"; + + case MODE_OFDM: + return "OFDM"; +#ifdef DOT11_N_SUPPORT + case MODE_HTMIX: + return "HTMIX"; + + case MODE_HTGREENFIELD: + return "GREEN"; +#endif /* DOT11_N_SUPPORT */ + default: + return "N/A"; + } +} + + +char* GetBW( + int BW) +{ + switch(BW) + { + case BW_10: + return "10M"; + + case BW_20: + return "20M"; +#ifdef DOT11_N_SUPPORT + case BW_40: + return "40M"; +#endif /* DOT11_N_SUPPORT */ + default: + 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; + +} + + +/* + ========================================================================== + Description: + Set Wireless Mode + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT RT_CfgSetWirelessMode( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT MaxPhyMode = PHY_11G; + LONG WirelessMode; + +#ifdef DOT11_N_SUPPORT + if (!RTMP_TEST_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DOT_11N)) + MaxPhyMode = PHY_11N_5G; +#endif /* DOT11_N_SUPPORT */ + + WirelessMode = simple_strtol(arg, 0, 10); + + /* check if chip support 5G band when WirelessMode is 5G band */ + if (PHY_MODE_IS_5G_BAND(WirelessMode)) + { + if (!RFIC_IS_5G_BAND(pAd)) + { + DBGPRINT(RT_DEBUG_ERROR, + ("phy mode> Error! The chip does not support 5G band %d!\n", + pAd->RfIcType)); + return FALSE; + } + } + + if (WirelessMode <= MaxPhyMode) + { + pAd->CommonCfg.PhyMode = WirelessMode; + pAd->CommonCfg.DesiredPhyMode = WirelessMode; + return TRUE; + } + + return FALSE; + +} + + +/* maybe can be moved to GPL code, ap_mbss.c, but the code will be open */ +#ifdef CONFIG_AP_SUPPORT +#ifdef MBSS_SUPPORT +BOOLEAN RT_CfgMbssWirelessModeSameBand( + IN PRTMP_ADAPTER pAd, + IN UCHAR WirelessModeNew) +{ + BOOLEAN FlgIsOldMode24G = TRUE; + BOOLEAN FlgIsNewMode24G = TRUE; + + + if ((pAd->CommonCfg.PhyMode == PHY_11A) +#ifdef DOT11_N_SUPPORT + || (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) + || (pAd->CommonCfg.PhyMode == PHY_11N_5G) +#endif /* DOT11_N_SUPPORT */ + ) + { + FlgIsOldMode24G = FALSE; + } + + if ((WirelessModeNew == PHY_11A) +#ifdef DOT11_N_SUPPORT + || (WirelessModeNew == PHY_11AN_MIXED) + || (WirelessModeNew == PHY_11N_5G) +#endif /* DOT11_N_SUPPORT */ + ) + { + FlgIsNewMode24G = FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("mbss> Old phy mode %d, New phy mode %d!\n", + pAd->CommonCfg.PhyMode, WirelessModeNew)); + + if (FlgIsOldMode24G != FlgIsNewMode24G) + return FALSE; /* different phy band */ + + return TRUE; /* same phy band */ +} + + +UCHAR RT_CfgMbssWirelessModeMaxGet( + IN PRTMP_ADAPTER pAd) +{ + MULTISSID_STRUCT *pMbss; + UCHAR MaxPhyMode = PHY_11G, WirelessMode; + UINT32 IdBss; + BOOLEAN IsAnyB = FALSE; /* any b mode exist */ + BOOLEAN IsAnyG = FALSE; /* any g mode exist */ + BOOLEAN IsAnyA = FALSE; /* any a mode exist */ + BOOLEAN IsAny24N = FALSE; /* any n mode in 2.4G band exist */ + BOOLEAN IsAny5N = FALSE; /* any n mode in 5G band exist */ + BOOLEAN IsAny5 = FALSE; /* any 5G mode */ + + +#ifdef DOT11_N_SUPPORT + if (!RTMP_TEST_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DOT_11N)) + MaxPhyMode = PHY_11N_5G; +#endif /* DOT11_N_SUPPORT */ + + for(IdBss=0; IdBssApCfg.BssidNum; IdBss++) + { + pMbss = &pAd->ApCfg.MBSSID[IdBss]; + + /* check if the phy mode is out of range */ + if (pMbss->PhyMode > MaxPhyMode) + pMbss->PhyMode = PHY_11BG_MIXED; /* default */ + + /* check if the phy mode is legal */ + if (pMbss->PhyMode == PHY_11ABG_MIXED) + pMbss->PhyMode = PHY_11BG_MIXED; + +#ifdef DOT11_N_SUPPORT + if (pMbss->PhyMode == PHY_11ABGN_MIXED) + pMbss->PhyMode = PHY_11BGN_MIXED; + + if (pMbss->PhyMode == PHY_11AGN_MIXED) + pMbss->PhyMode = PHY_11GN_MIXED; +#endif /* DOT11_N_SUPPORT */ + + /* record the legacy phy mode */ + /* + Not use array to avoid the value of PHY_11B is changed in the future + If any code size problem, we can use array to replace if check. + */ + if (pMbss->PhyMode == PHY_11B) + IsAnyB = TRUE; + + if (pMbss->PhyMode == PHY_11G) + IsAnyG = TRUE; + + if (pMbss->PhyMode == PHY_11BG_MIXED) + { + IsAnyB = TRUE; + IsAnyG = TRUE; + } + + if (pMbss->PhyMode == PHY_11A) + { + IsAnyA = TRUE; + IsAny5 = TRUE; + } + +#ifdef DOT11_N_SUPPORT + /* record the N phy mode */ + if (pMbss->PhyMode == PHY_11N_5G) + { + IsAny5N = TRUE; + IsAny5 = TRUE; + } + + if (pMbss->PhyMode == PHY_11AN_MIXED) + { + IsAnyA = TRUE; + IsAny5N = TRUE; + IsAny5 = TRUE; + } + + if (pMbss->PhyMode == PHY_11N_2_4G) + IsAny24N = TRUE; + + if (pMbss->PhyMode == PHY_11BGN_MIXED) + { + IsAnyB = TRUE; + IsAnyG = TRUE; + IsAny24N = TRUE; + } +#endif /* DOT11_N_SUPPORT */ + } + + DBGPRINT(RT_DEBUG_TRACE, + ("mbss> b g a 2.4n 5n %d %d %d %d %d\n", + IsAnyB, IsAnyG, IsAnyA, IsAny24N, IsAny5N)); + + if (IsAny5 == 0) + { + if (IsAny24N == 0) + { + /* no N phy exists */ + if ((IsAnyB == 1) && (IsAnyG == 1)) + WirelessMode = PHY_11BG_MIXED; /* B & G phy exists */ + else if (IsAnyG == 1) + WirelessMode = PHY_11G; /* no B phy exists */ + else + WirelessMode = PHY_11B; /* no G phy exists */ + } +#ifdef DOT11_N_SUPPORT + else + { + /* N phy exists */ + if ((IsAnyB == 1) && (IsAnyG == 1)) + WirelessMode = PHY_11BGN_MIXED; /* B & G phy exists */ + else if (IsAnyG == 1) + WirelessMode = PHY_11GN_MIXED; /* no B phy exists */ + else + WirelessMode = PHY_11N_2_4G; /* no G phy exists */ + } +#endif /* DOT11_N_SUPPORT */ + } + else + { + if (IsAny5N == 0) + { + /* no N phy exists */ + WirelessMode = PHY_11A; /* A phy exists */ + } +#ifdef DOT11_N_SUPPORT + else + { + /* N phy exists */ + if (IsAnyA == 1) + WirelessMode = PHY_11AN_MIXED; /* A phy exists */ + else + WirelessMode = PHY_11N_5G; + } +#endif /* DOT11_N_SUPPORT */ + } /* End of if */ + + DBGPRINT(RT_DEBUG_TRACE, ("mbss> Get WirelessMode = %d\n", WirelessMode)); + return WirelessMode; +} + + +/* + ========================================================================== + Description: + Set Wireless Mode for MBSS + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT RT_CfgSetMbssWirelessMode( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT32 MaxPhyMode = PHY_11G; + UINT32 WirelessMode; + +#ifdef DOT11_N_SUPPORT + if (!RTMP_TEST_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DOT_11N)) + MaxPhyMode = PHY_11N_5G; +#endif /* DOT11_N_SUPPORT */ + + WirelessMode = simple_strtol(arg, 0, 10); + + if ((WirelessMode == PHY_11ABG_MIXED) +#ifdef DOT11_N_SUPPORT + || (WirelessMode == PHY_11ABGN_MIXED) + || (WirelessMode == PHY_11AGN_MIXED) +#endif /* DOT11_N_SUPPORT */ + ) + { + DBGPRINT(RT_DEBUG_ERROR, ("mbss> Wrong phy mode for AP!\n")); + return FALSE; + } + + /* check if chip support 5G band when WirelessMode is 5G band */ + if (PHY_MODE_IS_5G_BAND(WirelessMode)) + { + if (!RFIC_IS_5G_BAND(pAd)) + { + DBGPRINT(RT_DEBUG_ERROR, + ("phy mode> Error! The chip does not support 5G band!\n")); + return FALSE; + } + } + + if (WirelessMode <= MaxPhyMode) + { + if (pAd->ApCfg.BssidNum > 1) + { + /* pAd->CommonCfg.PhyMode = maximum capability of all MBSS */ + if (RT_CfgMbssWirelessModeSameBand(pAd, WirelessMode) == TRUE) + { + WirelessMode = RT_CfgMbssWirelessModeMaxGet(pAd); + + DBGPRINT(RT_DEBUG_TRACE, + ("mbss> Maximum phy mode = %d!\n", WirelessMode)); + } + 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].PhyMode = WirelessMode; + } + } + + pAd->CommonCfg.PhyMode = WirelessMode; + pAd->CommonCfg.DesiredPhyMode = WirelessMode; + return TRUE; + } + + return FALSE; +} +#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( + IN PSTRING arg) +{ + INT fix_tx_mode = FIXED_TXMODE_HT; + UINT32 value; + + if (strcmp(arg, "OFDM") == 0 || strcmp(arg, "ofdm") == 0) + { + fix_tx_mode = FIXED_TXMODE_OFDM; + } + else if (strcmp(arg, "CCK") == 0 || strcmp(arg, "cck") == 0) + { + fix_tx_mode = FIXED_TXMODE_CCK; + } + else if (strcmp(arg, "HT") == 0 || strcmp(arg, "ht") == 0) + { + fix_tx_mode = FIXED_TXMODE_HT; + } + else + { + value = simple_strtol(arg, 0, 10); + /* 1 : CCK*/ + /* 2 : OFDM*/ + /* otherwise : HT*/ + if (value == FIXED_TXMODE_CCK || value == FIXED_TXMODE_OFDM) + fix_tx_mode = value; + else + 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( + IN PSTRING arg, + OUT 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) +{ + TX_RTY_CFG_STRUC tx_rty_cfg; + UCHAR AutoFallBack = (UCHAR)simple_strtol(arg, 0, 10); + + RTMP_IO_READ32(pAd, TX_RTY_CFG, &tx_rty_cfg.word); + tx_rty_cfg.field.TxautoFBEnable = (AutoFallBack) ? 1 : 0; + RTMP_IO_WRITE32(pAd, TX_RTY_CFG, tx_rty_cfg.word); + DBGPRINT(RT_DEBUG_TRACE, ("RT_CfgSetAutoFallBack::(tx_rty_cfg=0x%x)\n", tx_rty_cfg.word)); + 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) +{ +#ifdef P2P_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; +#endif /* P2P_SUPPORT */ + UCHAR CurOpMode = OPMODE_AP; + + if (CurOpMode == OPMODE_AP) + { +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + if (P2P_CLI_ON(pAd)) + strcpy(pData, "Ralink P2P Cli"); + else if (P2P_GO_ON(pAd)) + strcpy(pData, "Ralink P2P GO"); + else + strcpy(pData, "Ralink P2P"); + } + else +#endif /* P2P_SUPPORT */ + 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; + UCHAR PermanentAddress[MAC_ADDR_LEN]; + USHORT Addr01, Addr23, Addr45; + + + 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: + /* set main net_dev */ + pAd->net_dev = pData; + +#ifdef CONFIG_AP_SUPPORT + pAd->ApCfg.MBSSID[MAIN_MBSSID].MSSIDDev = pData; +#endif /* CONFIG_AP_SUPPORT */ + 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; + + case CMD_RTPRIV_IOCTL_IRQ_INIT: + /* init IRQ */ + RTMP_IRQ_INIT(pAd); + break; + + 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; + +#ifdef CONFIG_APSTA_MIXED_SUPPORT + case CMD_RTPRIV_IOCTL_MAX_IN_BIT: + /* set MAX_IN_BIT for WMM */ + CW_MAX_IN_BITS = Data; + break; +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ +#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); + 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;/* = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);*/ + 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);/* kfree(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: + /* RT28xxUsbAsicRadioOff */ + RT28xxUsbAsicRadioOff(pAd); + break; + + case CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_USB_ASICRADIO_ON: + /* RT28xxUsbAsicRadioOn */ + RT28xxUsbAsicRadioOn(pAd); + break; + +#ifdef WOW_SUPPORT +#endif /* WOW_SUPPORT */ + +#endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ +#endif /* CONFIG_PM */ + + case CMD_RTPRIV_IOCTL_AP_BSSID_GET: + if (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) + NdisCopyMemory(pData, pAd->MlmeAux.Bssid, 6); + else + return NDIS_STATUS_FAILURE; + 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 MESH_SUPPORT + case CMD_RTPRIV_IOCTL_MESH_INIT: + MeshInit(pAd, pData); + break; + + case CMD_RTPRIV_IOCTL_MESH_REMOVE: + MESH_Remove(pAd); + break; + + case CMD_RTPRIV_IOCTL_MESH_OPEN_PRE: + if (MESH_OpenPre(pData) != 0) + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_MESH_OPEN_POST: + if (MESH_OpenPost(pData) != 0) + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_MESH_IS_VALID: + *(BOOLEAN *)pData = MeshValid(&pAd->MeshTab); + break; + + case CMD_RTPRIV_IOCTL_MESH_CLOSE: + MESH_Close(pData); + break; +#endif /* MESH_SUPPORT */ + +#ifdef P2P_SUPPORT + case CMD_RTPRIV_IOCTL_P2P_INIT: + P2pInit(pAd, pData); + break; + + case CMD_RTPRIV_IOCTL_P2P_REMOVE: + P2P_Remove(pAd); + break; + + case CMD_RTPRIV_IOCTL_P2P_OPEN_PRE: + if (P2P_OpenPre(pData) != 0) + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_P2P_OPEN_POST: + if (P2P_OpenPost(pData) != 0) + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_P2P_CLOSE: + P2P_Close(pData); + break; +#endif /* P2P_SUPPORT */ + + case CMD_RTPRIV_IOCTL_BEACON_UPDATE: + /* update all beacon contents */ +#ifdef CONFIG_AP_SUPPORT + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef MESH_SUPPORT + MeshMakeBeacon(pAd, pAd->MeshTab.BcnBufIdx); + MeshUpdateBeaconFrame(pAd, pAd->MeshTab.BcnBufIdx); +#endif /* MESH_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:g_if_id=%d status=%d\n",pAd->g_if_id,status)); + } + 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) + { + if (pInfConf->rt28xx_open(pAd->net_dev) != 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("rt28xx_open return fail!\n")); + return NDIS_STATUS_FAILURE; + } + } + 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 */ +#ifdef MESH_SUPPORT + { + extern VOID MeshMakeBeacon(IN PRTMP_ADAPTER pAd, IN UCHAR idx); + extern VOID MeshUpdateBeaconFrame(IN PRTMP_ADAPTER pAd, IN UCHAR idx); + MeshMakeBeacon(pAd, pAd->MeshTab.BcnBufIdx); + MeshUpdateBeaconFrame(pAd, pAd->MeshTab.BcnBufIdx); + } +#endif /* MESH_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) + pInfConf->rt28xx_close(pAd->net_dev); + } + 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_STATS *pStats = (RT_CMD_STATS *)pData; + pStats->pStats = pAd->stats; + 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 = pAd->Counters8023.OneCollision + pAd->Counters8023.MoreCollisions; /* 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 = pAd->Counters8023.RcvAlignmentErrors; /* recv'd frame alignment error*/ + pStats->rx_fifo_errors = pAd->Counters8023.RxNoBuffer; /* recv'r fifo overrun*/ + } +#ifdef CONFIG_AP_SUPPORT + else if(pAd->OpMode == OPMODE_AP) + { + INT index; + for(index = 0; index < MAX_MBSSID_NUM(pAd); index++) + { + if (pAd->ApCfg.MBSSID[index].MSSIDDev == (PNET_DEV)(pStats->pNetDev)) + { + break; + } + } + + if(index >= MAX_MBSSID_NUM(pAd)) + { + //reset counters + pStats->rx_packets = 0; + pStats->tx_packets = 0; + pStats->rx_bytes = 0; + pStats->tx_bytes = 0; + pStats->rx_errors = 0; + pStats->tx_errors = 0; + pStats->multicast = 0; /* multicast packets received*/ + pStats->collisions = 0; /* Collision packets*/ + pStats->rx_over_errors = 0; /* receiver ring buff overflow*/ + pStats->rx_crc_errors = 0; /* recved pkt with crc error*/ + pStats->rx_frame_errors = 0; /* recv'd frame alignment error*/ + pStats->rx_fifo_errors = 0; /* recv'r fifo overrun*/ + + DBGPRINT(RT_DEBUG_ERROR, ("CMD_RTPRIV_IOCTL_INF_STATS_GET: can not find mbss I/F\n")); + return NDIS_STATUS_FAILURE; + } + + pStats->rx_packets = pAd->ApCfg.MBSSID[index].RxCount; + pStats->tx_packets = pAd->ApCfg.MBSSID[index].TxCount; + pStats->rx_bytes = pAd->ApCfg.MBSSID[index].ReceivedByteCount; + pStats->tx_bytes = pAd->ApCfg.MBSSID[index].TransmittedByteCount; + pStats->rx_errors = pAd->ApCfg.MBSSID[index].RxErrorCount; + pStats->tx_errors = pAd->ApCfg.MBSSID[index].TxErrorCount; + pStats->multicast = pAd->ApCfg.MBSSID[index].mcPktsRx; /* multicast packets received */ + pStats->collisions = 0; /* Collision packets*/ + pStats->rx_over_errors = 0; /* receiver ring buff overflow*/ + pStats->rx_crc_errors = 0;/* recved pkt with crc error*/ + pStats->rx_frame_errors = 0; /* recv'd frame alignment error*/ + pStats->rx_fifo_errors = 0; /* 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; +#ifdef P2P_SUPPORT + if (pStats->priv_flags == INT_P2P) + CurOpMode = OPMODE_AP; +#endif /* P2P_SUPPORT */ + } +#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) +#ifdef P2P_SUPPORT + || (P2P_CLI_ON(pAd)) +#endif /* P2P_SUPPORT */ + ) + { + 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); +#ifdef P2P_APCLI_SUPPORT + else + pStats->level = + RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.AvgRssi0, + pAd->StaCfg.RssiSample.AvgRssi1, + pAd->StaCfg.RssiSample.AvgRssi2); +#endif /* P2P_APCLI_SUPPORT */ + } +#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 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: + + RT28xx_EEPROM_READ16(pAd, 0x04, Addr01); + RT28xx_EEPROM_READ16(pAd, 0x06, Addr23); + RT28xx_EEPROM_READ16(pAd, 0x08, Addr45); + + PermanentAddress[0] = (UCHAR)(Addr01 & 0xff); + PermanentAddress[1] = (UCHAR)(Addr01 >> 8); + PermanentAddress[2] = (UCHAR)(Addr23 & 0xff); + PermanentAddress[3] = (UCHAR)(Addr23 >> 8); + PermanentAddress[4] = (UCHAR)(Addr45 & 0xff); + PermanentAddress[5] = (UCHAR)(Addr45 >> 8); + + for(i=0; i<6; i++) + *(UCHAR *)(pData+i) = PermanentAddress[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; + +#ifdef MESH_SUPPORT + if (pRate->priv_flags == INT_MESH) + HtPhyMode = pAd->MeshTab.HTPhyMode; + else +#endif /* MESH_SUPPORT */ +#ifdef APCLI_SUPPORT + if (pRate->priv_flags == INT_APCLI) + HtPhyMode = pAd->ApCfg.ApCliTab[pObj->ioctl_if].HTPhyMode; + else +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (pRate->priv_flags == INT_WDS) + HtPhyMode = pAd->WdsTab.WdsEntry[pObj->ioctl_if].HTPhyMode; + else +#endif /* WDS_SUPPORT */ + { + HtPhyMode = pAd->ApCfg.MBSSID[pObj->ioctl_if].HTPhyMode; +#ifdef MBSS_SUPPORT + /* reset phy mode for MBSS */ + MBSS_PHY_MODE_RESET(pObj->ioctl_if, HtPhyMode); +#endif /* MBSS_SUPPORT */ + } + RtmpDrvMaxRateGet(pAd, HtPhyMode.field.MODE, HtPhyMode.field.ShortGI, + HtPhyMode.field.BW, HtPhyMode.field.MCS, + (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)) + { + 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; + + 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 +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { + if ((strlen(arg) != 0) && (strlen(arg) <= MAX_LEN_OF_SSID)) + { + NdisMoveMemory(Ssid.Ssid, arg, strlen(arg)); + Ssid.SsidLength = strlen(arg); + } + + pAd->ApCfg.bImprovedScan = TRUE; + if (Ssid.SsidLength == 0) + ApSiteSurvey(pAd, &Ssid, SCAN_PASSIVE, FALSE); + else + ApSiteSurvey(pAd, &Ssid, SCAN_ACTIVE, FALSE); + + 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 RT5350 +INT Set_Hw_Antenna_Div_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + return Set_Antenna_Proc(pAd, arg); +} +#endif /* RT5350 */ + +#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 MCS_LUT_SUPPORT +INT Set_HwTxRateLookUp_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg) +{ + UCHAR Enable; + UINT32 MacReg; + + Enable = simple_strtol(arg, 0, 10); + + RTMP_IO_READ32(pAd, TX_FBK_LIMIT, &MacReg); + if (Enable) + { + MacReg |= 0x00040000; + pAd->bUseHwTxLURate = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("==>UseHwTxLURate (ON)\n")); + } + else + { + MacReg &= (~0x00040000); + pAd->bUseHwTxLURate = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("==>UseHwTxLURate (OFF)\n")); + } + RTMP_IO_WRITE32(pAd, TX_FBK_LIMIT, MacReg); + + DBGPRINT(RT_DEBUG_WARN, ("UseHwTxLURate = %d \n", pAd->bUseHwTxLURate)); + + return TRUE; +} +#endif /* MCS_LUT_SUPPORT */ + diff --git a/mt7620/src/common/cmm_cmd.c b/mt7620/src/common/cmm_cmd.c new file mode 100644 index 0000000..6fddede --- /dev/null +++ b/mt7620/src/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/mt7620/src/common/cmm_cs.c b/mt7620/src/common/cmm_cs.c new file mode 100644 index 0000000..0764a87 --- /dev/null +++ b/mt7620/src/common/cmm_cs.c @@ -0,0 +1,763 @@ +/* + *************************************************************************** + * 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 +/* + ========================================================================== + 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 */ + +#ifdef CARRIER_DETECTION_FIRMWARE_SUPPORT +/* + ========================================================================== + Description: + When h/w interrupt is not available for CS, f/w take care of the operation, 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) +{ + CD_STATE *pCD_State = &pAd->CommonCfg.CarrierDetect.CD_State; + ULONG *pOneSecIntCount = &pAd->CommonCfg.CarrierDetect.OneSecIntCount; + CARRIER_DETECT_PARAM CarrDetectParam; + + +#ifdef RALINK_ATE + /* Nothing to do in ATE mode */ + if (ATE_ON(pAd)) + return; +#endif /* RALINK_ATE */ + + /* 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; + + DBGPRINT(RT_DEBUG_INFO, ("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) + { + RTMP_CARRIER_IO_READ8(pAd, 1, &bbp); + if (!(bbp & 0x1)) + return; + else + { + /* Disable carrier detection and clear the status bit*/ + RTMP_CARRIER_IO_WRITE8(pAd, 0, 0); + RTMP_CARRIER_IO_WRITE8(pAd, 1, 1); + /* Clear interrupt */ + RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR ,(1<<20)); + } + } + + 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) + { + /* Clear Status bit */ + //RTMP_CARRIER_IO_WRITE8(pAd, 1, bbp); + RTMP_CARRIER_IO_READ8(pAd, 1, &bbp); + if (bbp & 0x1) + DBGPRINT(RT_DEBUG_ERROR, ("CS bit not cleared!!!\n")); + /* re-enable carrier detection */ + RTMP_CARRIER_IO_WRITE8(pAd, 0, 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; +} + +/* + ========================================================================== + 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 + /* trun on interrupt polling for pcie device */ + if (pAd->infType == RTMP_DEV_INF_PCIE) + AsicSendCommandToMcu(pAd, CD_INT_POLLING_CMD, 0xff, 0x01, 0x00, FALSE); +#endif /* CARRIER_DETECTION_FIRMWARE_SUPPORT */ + } +} + +/* + ========================================================================== + Description: + To stop CS + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + ========================================================================== +*/ +VOID CarrierDetectionStop(IN PRTMP_ADAPTER pAd) +{ + CarrierDetectReset(pAd); +#ifdef CARRIER_DETECTION_FIRMWARE_SUPPORT + /* Stop firmware CS action */ + AsicSendCommandToMcu(pAd, CD_ONOFF_MCU_CMD, 0xff, 0x00, 0x00, FALSE); +#endif /* CARRIER_DETECTION_FIRMWARE_SUPPORT */ + 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); +} + +/* + ========================================================================== + 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 */ + RTMP_CARRIER_IO_WRITE8(pAd, 0, 1); +} + +#endif /* CARRIER_DETECTION_SUPPORT */ + diff --git a/mt7620/src/common/cmm_data.c b/mt7620/src/common/cmm_data.c new file mode 100644 index 0000000..059a9af --- /dev/null +++ b/mt7620/src/common/cmm_data.c @@ -0,0 +1,5013 @@ +/**************************************************************************** + * 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" + + +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}; + +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 */ +}; + +UCHAR MapUserPriorityToAccessCategory[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}; + + +/* + ======================================================================== + + 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 PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PUCHAR pData, + IN UINT Length) +{ + PNDIS_PACKET pPacket; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + ULONG FreeNum; + UINT8 TXWISize = pAd->chipCap.TXWISize; + UCHAR rtmpHwHdr[TXINFO_SIZE + pAd->chipCap.TXWISize]; /*RTMP_HW_HDR_LEN];*/ +#ifdef RTMP_MAC_PCI + unsigned long IrqFlags = 0; +// UCHAR IrqState; +#endif /* RTMP_MAC_PCI */ + BOOLEAN bUseDataQ = FALSE, FlgDataQForce = FALSE, FlgIsLocked = FALSE; + int retryCnt = 0; + + ASSERT(Length <= MGMT_DMA_BUFFER_SIZE); + + if ((QueIdx & MGMT_USE_QUEUE_FLAG) == MGMT_USE_QUEUE_FLAG) + { + bUseDataQ = TRUE; + QueIdx &= (~MGMT_USE_QUEUE_FLAG); + } + +#ifdef RTMP_MAC_PCI + /* 2860C use Tx Ring*/ +// IrqState = pAd->irq_disabled; + 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 */ + + do + { + /* 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) +#ifdef P2P_SUPPORT + || IS_P2P_ABSENCE(pAd) +#endif /* 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) + { + /* 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)) + { + /* 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), pData, Length); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n")); + break; + } + + + /*pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;*/ + /*pAd->CommonCfg.MlmeRate = RATE_2;*/ +#ifdef DOT11Z_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 P2P_SUPPORT + if (P2P_GO_ON(pAd)) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { + UAPSD_MR_QOS_NULL_HANDLE(pAd, pData, pPacket); + } +#endif /* UAPSD_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +#endif /* DOT11Z_TDLS_SUPPORT */ + +#ifdef RTMP_MAC_PCI + if (bUseDataQ) + { +/* Status = MlmeDataHardTransmit(pAd, QueIdx, pPacket); */ + FlgDataQForce = TRUE; + retryCnt--; + } +#endif /* RTMP_MAC_PCI */ + + Status = MlmeHardTransmit(pAd, QueIdx, pPacket, FlgDataQForce, FlgIsLocked); + 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 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 PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket, + IN BOOLEAN FlgDataQForce, + IN BOOLEAN FlgIsLocked) +{ +#ifdef CONFIG_AP_SUPPORT + MAC_TABLE_ENTRY *pEntry = NULL; + PHEADER_802_11 pHeader_802_11; + UINT8 TXWISize = pAd->chipCap.TXWISize; +#endif /* CONFIG_AP_SUPPORT */ + PACKET_INFO PacketInfo; + PUCHAR 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); + + /* + 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 == BTYPE_DATA) || + (pHeader_802_11->FC.Type == BTYPE_MGMT)) + { + if (pHeader_802_11->FC.SubType != SUBTYPE_QOS_NULL) + pEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); + } + + + + if ((pEntry != NULL) && + (pEntry->PsMode == PWR_SAVE) && + (((pHeader_802_11->FC.Type == BTYPE_DATA) && + (pHeader_802_11->FC.SubType != SUBTYPE_NULL_FUNC) && + (pHeader_802_11->FC.SubType != SUBTYPE_QOS_NULL)) || + ((pHeader_802_11->FC.Type == BTYPE_MGMT) && + (pHeader_802_11->FC.SubType == SUBTYPE_ACTION)) || + ((pHeader_802_11->FC.Type == BTYPE_MGMT) && + (pHeader_802_11->FC.SubType == SUBTYPE_ACTION_NO_ACK)))) + { + /* 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, + ("The station is in ps mode, queue the management frame!\n")); + RTMP_SET_PACKET_WCID(pPacket, pEntry->Aid); + RTMP_SET_PACKET_MGMT_PKT(pPacket, 1); /* is management frame */ + RTMP_SET_PACKET_MGMT_PKT_DATA_QUE(pPacket, 0); /* default to management queue */ + + if ((pAd->MACVersion == 0x28600100) || (FlgDataQForce == TRUE)) + RTMP_SET_PACKET_MGMT_PKT_DATA_QUE(pPacket, 1); /* force to data queue */ + + if ((pHeader_802_11->FC.Type == BTYPE_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; + } + + + AP_QueuePsActionPacket(pAd, pEntry, pPacket, FlgIsDeltsFrame, + FlgIsLocked, MgmtQid); + return NDIS_STATUS_SUCCESS; + } + else +#endif /* CONFIG_AP_SUPPORT */ + { +#ifdef RTMP_MAC_PCI + if ((pAd->MACVersion == 0x28600100) || (FlgDataQForce == TRUE)) + return MlmeHardTransmitTxRing(pAd,QueIdx,pPacket); + else +#endif /* RTMP_MAC_PCI */ + return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket); + } +} + + +NDIS_STATUS MlmeHardTransmitMgmtRing( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket) +{ + PACKET_INFO PacketInfo; + PUCHAR pSrcBufVA; + UINT SrcBufLen; + PHEADER_802_11 pHeader_802_11; + BOOLEAN bAckRequired, bInsertTimestamp; + UCHAR MlmeRate; + PTXWI_STRUC pFirstTxWI; + MAC_TABLE_ENTRY *pMacEntry = NULL; + UCHAR PID; + 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 = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE); + pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_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 == BTYPE_DATA) && + (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) + { + 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.*/ + if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED +#ifdef DOT11_N_SUPPORT + || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED +#endif /* DOT11_N_SUPPORT */ + ) + { + if (pAd->LatchRfRegs.Channel > 14) + pAd->CommonCfg.MlmeTransmit.field.MODE = 1; + else + pAd->CommonCfg.MlmeTransmit.field.MODE = 0; + } + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef P2P_SUPPORT + if (P2P_INF_ON(pAd)) + { + if (MAC_ADDR_EQUAL(pHeader_802_11->Addr2, pAd->P2pCfg.CurrentAddress) || + (pAd->LatchRfRegs.Channel > 14)) + { + pAd->CommonCfg.MlmeTransmit.field.MODE = 1; + pAd->CommonCfg.MlmeTransmit.field.MCS = MCS_RATE_6; + } + else + { + pAd->CommonCfg.MlmeTransmit.field.MODE = 0; + pAd->CommonCfg.MlmeTransmit.field.MCS = MCS_0; + } + } +#endif /* P2P_SUPPORT */ + /* 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; /* (pAd->StaCfg.Psm == PWR_SAVE);*/ +#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 ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))*/ + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if ((pHeader_802_11->FC.SubType == SUBTYPE_ACTION) || + ((pHeader_802_11->FC.Type == BTYPE_DATA) && + ((pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL) || + (pHeader_802_11->FC.SubType == SUBTYPE_NULL_FUNC)))) + { + 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 == BTYPE_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; + } + else /* BTYPE_MGMT or BTYPE_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) && (pHeader_802_11->FC.Type == BTYPE_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; + + for (apidx=0; apidxApCfg.BssidNum; apidx++) + { + if (RTMPEqualMemory(pHeader_802_11->Addr2, pAd->ApCfg.MBSSID[apidx].Bssid, MAC_ADDR_LEN)) + break; + } + + 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 == BTYPE_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)) + { + DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n")); +/* if (!IrqState)*/ + 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) + { + RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, + 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWISize), PID, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); + +#ifdef SPECIFIC_TX_POWER_SUPPORT + if (IS_RT6352(pAd)) + pFirstTxWI->TxPwrAdj = TxPwrAdj; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + } + else + { +#ifdef P2P_SUPPORT + /* P2P Test Case 6.1.12, only OFDM rate can be captured by sniffer */ + if ((pAd->P2pCfg.bLowRateQoSNULL == TRUE) && + ((pHeader_802_11->FC.Type == BTYPE_DATA) && + (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))) + { + DBGPRINT(RT_DEBUG_INFO, ("%s:: Using Low Rate to send QOS NULL!!\n", __FUNCTION__)); + pMacEntry->MaxHTPhyMode.field.MODE = 1; + pMacEntry->MaxHTPhyMode.field.MCS = MCS_RATE_54; + } +#endif /* P2P_SUPPORT */ + /* dont use low rate to send QoS Null data frame */ + RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, + bInsertTimestamp, FALSE, bAckRequired, FALSE, + 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWISize), + pMacEntry->MaxHTPhyMode.field.MCS, 0, + (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS, + IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode); + } + +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, (PUCHAR)pFirstTxWI, TYPE_TXWI); +#endif + + /* Now do hardware-depened kick out.*/ + HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen); + + /* 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) \ + 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) + + + + +/* + ======================================================================== + 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 + ======================================================================== +*/ +static UCHAR TxPktClassification( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket) +{ + UCHAR TxFrameType = TX_UNKOWN_FRAME; + UCHAR Wcid; + MAC_TABLE_ENTRY *pMacEntry = NULL; +#ifdef DOT11_N_SUPPORT + BOOLEAN bHTRate = FALSE; +#endif /* DOT11_N_SUPPORT */ + + Wcid = RTMP_GET_PACKET_WCID(pPacket); + if (Wcid == MCAST_WCID) + { /* Handle for RA is Broadcast/Multicast Address.*/ + return TX_MCAST_FRAME; + } + + /* Handle for unicast packets*/ + pMacEntry = &pAd->MacTab.Content[Wcid]; + 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; + } +#ifdef DOT11Z_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*/ + bHTRate = TRUE; + 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 */ + else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0) + return TX_AMPDU_FRAME; + else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED)) + return 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 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( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk) +{ + PACKET_INFO PacketInfo; + PNDIS_PACKET pPacket; + PMAC_TABLE_ENTRY pMacEntry = NULL; + + pPacket = pTxBlk->pPacket; + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen); + + pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket); + pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket); + pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket); + pTxBlk->FrameGap = IFS_HTTXOP; /* ASIC determine Frame Gap*/ +#ifdef CONFIG_AP_SUPPORT + pTxBlk->pMbss = NULL; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef P2P_SUPPORT + if (pTxBlk->apidx >= MIN_NET_DEVICE_FOR_P2P_GO) + pTxBlk->apidx = pTxBlk->apidx - MIN_NET_DEVICE_FOR_P2P_GO; +#endif /* P2P_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_SET_FLAG(pTxBlk, fTX_bForceLowRate);*/ + 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), ETH_LENGTH_OF_ADDRESS)) + { + 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 MESH_SUPPORT + if (IS_ENTRY_MESH(pMacEntry)) + { + PUCHAR pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket); + + /*if (pAd->MeshTab.bAutoTxRateSwitch)*/ + /* TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch);*/ + TX_BLK_SET_FLAG(pTxBlk, fTX_bMeshEntry); + + if (RTMP_GET_MESH_SOURCE(pPacket) == MESH_PROXY) + { + UINT8 MeshRouteId = RTMP_GET_MESH_ROUTE_ID(pPacket); + /* B/Mcast packet.*/ + if ((MeshRouteId == BMCAST_ROUTE_ID) && (*pSrcBufVA & 0x01)) + pTxBlk->pMeshDA = pSrcBufVA; /* Mesh DA*/ + else + { + PUCHAR pMeshDA = PathRouteAddrSearch(pAd, MeshRouteId); + if (pMeshDA) + pTxBlk->pMeshDA = pMeshDA; /* Mesh DA*/ + else + return FALSE; + } + } + else /* MESH_ORIGIN, MESH_FORWARD packet.*/ + pTxBlk->pMeshDA = pSrcBufVA; /* Mesh DA*/ + + /* 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); + } + else +#endif /* MESH_SUPPORT */ + { +#ifdef CONFIG_AP_SUPPORT +#ifdef P2P_SUPPORT + if (pTxBlk->OpMode == OPMODE_AP) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { +#ifdef WDS_SUPPORT + if(IS_ENTRY_WDS(pMacEntry)) + { + /*if (pAd->WdsTab.WdsEntry[pMacEntry->MatchWDSTabIdx].bAutoTxRateSwitch)*/ + /* TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch);*/ + TX_BLK_SET_FLAG(pTxBlk, fTX_bWDSEntry); + } + else +#endif /* WDS_SUPPORT */ +#ifdef APCLI_SUPPORT + if(IS_ENTRY_APCLI(pMacEntry)) + { + PNDIS_PACKET apCliPkt = NULL; + +#ifdef MAC_REPEATER_SUPPORT + if ((pAd->ApCfg.bMACRepeaterEn) && (pMacEntry->bReptCli)) + { + UCHAR tmpIdx; + + pAd->MatCfg.bMACRepeaterEn = pAd->ApCfg.bMACRepeaterEn; + + if(pAd->ApCfg.MACRepeaterOuiMode != 1) + { + tmpIdx = (64 + (MAX_EXT_MAC_ADDR_SIZE * pMacEntry->MatchAPCLITabIdx) + pMacEntry->MatchReptCliIdx); + apCliPkt = (PNDIS_PACKET)MATEngineTxHandle(pAd, pPacket, tmpIdx, pTxBlk->OpMode); + } + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + /* For each tx packet, update our MAT convert engine databases.*/ + apCliPkt = (PNDIS_PACKET)MATEngineTxHandle(pAd, pPacket, pMacEntry->MatchAPCLITabIdx, 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; + } + pTxBlk->pApCliEntry = &pAd->ApCfg.ApCliTab[pMacEntry->MatchAPCLITabIdx]; + TX_BLK_SET_FLAG(pTxBlk, fTX_bApCliPacket); + + /*if (pTxBlk->pApCliEntry->bAutoTxRateSwitch)*/ + /* TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch);*/ + + } + 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)) + { + /*if (IS_ENTRY_CLIENT(pMacEntry) && pAd->ApCfg.MBSSID[pMacEntry->apidx].bAutoTxRateSwitch)*/ + /* TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch);*/ + } + 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 +#ifdef P2P_SUPPORT + if (pTxBlk->OpMode == OPMODE_STA) +#else + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) +#endif /* P2P_SUPPORT */ + { +#ifdef DOT11Z_TDLS_SUPPORT + if(IS_ENTRY_TDLS(pMacEntry)) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bTdlsEntry); + } +#endif /* DOT11Z_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), ETH_LENGTH_OF_ADDRESS)) + { + 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); + +/* if (pAd->StaCfg.bAutoTxRateSwitch)*/ +/* TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch);*/ + } +#endif /* CONFIG_STA_SUPPORT */ + } + + if (pTxBlk->TxFrameType == TX_LEGACY_FRAME) + { + if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) || + ((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 + 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; + +} + + +/* + ======================================================================== + + 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 PRTMP_ADAPTER pAd, + IN BOOLEAN bIntContext, + IN UCHAR QIdx, /* BulkOutPipeId */ + IN UCHAR 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]; + UCHAR QueIdx, sQIdx, eQIdx; + unsigned long IrqFlags = 0; + BOOLEAN hasTxDesc = FALSE; + TX_BLK TxBlk; + TX_BLK *pTxBlk; + +#ifdef DBG_DIAGNOSE + BOOLEAN firstRound; + RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct; +#endif + + + if (QIdx == NUM_OF_TX_RING) + { + sQIdx = 0; + eQIdx = 3; /* 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 == 0) ? 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))) +#ifdef P2P_SUPPORT + || IS_P2P_ABSENCE(pAd) +#endif /* P2P_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 + if (firstRound == TRUE) + pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++; +#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 + 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_DIAGNOSE */ + + if (FreeNumber[QueIdx] <= 5) + { + /* 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)); + /*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 */ + + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); + +#ifdef CONFIG_AP_SUPPORT +#ifdef P2P_SUPPORT + if (RTMP_GET_PACKET_OPMODE(pPacket)) + { +#endif /* 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, + ("Transmit queued management 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*/ + MAC_TABLE_ENTRY *pMacEntry = NULL; + UCHAR RAWcid; + 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); + 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); + continue; + } + else + NdisGetSystemUpTime(&pMacEntry->TimeStamp_toTxRing); + } + } +#ifdef P2P_SUPPORT + } +#endif /* 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; + } + + pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket); + 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; +#ifdef P2P_SUPPORT + pTxBlk->OpMode = RTMP_GET_PACKET_OPMODE(pPacket); +#endif /* P2P_SUPPORT */ + InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket)); + + + 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 + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + Status = APHardTransmit(pAd, pTxBlk, QueIdx); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef P2P_SUPPORT + //if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_APCLI) + if (RTMP_GET_PACKET_OPMODE(pPacket)) + Status = APHardTransmit(pAd, pTxBlk, QueIdx); + else +#endif /* P2P_SUPPORT */ + Status = STAHardTransmit(pAd, pTxBlk, QueIdx); + } +#endif /* CONFIG_STA_SUPPORT */ + +#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))*/ +#ifdef VENDOR_FEATURE1_SUPPORT + if (++pAd->FifoUpdateDone >= 4) + { + NICUpdateFifoStaCounters(pAd); + pAd->FifoUpdateDone = 0; + } +#else + NICUpdateFifoStaCounters(pAd); +#endif /* VENDOR_FEATURE1_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + + } + + 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 */ + + } + +} + + +/* + ======================================================================== + + 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: + 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 + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + See also : BASmartHardTransmit() !!! + + ======================================================================== +*/ +VOID RTMPWriteTxWI( + IN PRTMP_ADAPTER pAd, + IN PTXWI_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 BOOLEAN CfAck, + IN HTTRANSMIT_SETTING *pTransmit) +{ + PMAC_TABLE_ENTRY pMac = NULL; + TXWI_STRUC TxWI; + PTXWI_STRUC pTxWI; + UINT8 TXWISize = pAd->chipCap.TXWISize; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + +#ifdef MAC_REPEATER_SUPPORT + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + if (WCID < MaxWcidNum) + 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; + + pTxWI->FRAG= FRAG; + + pTxWI->CFACK = CFACK; + pTxWI->TS= InsTimestamp; + pTxWI->AMPDU = AMPDU; + pTxWI->ACK = Ack; + pTxWI->txop= Txopmode; + + pTxWI->NSEQ = NSeq; + /* John tune the performace with Intel Client in 20 MHz performance*/ +#ifdef DOT11_N_SUPPORT + BASize = pAd->CommonCfg.TxBASize; + if (pAd->MACVersion == 0x28720200) + { + if( BASize >13 ) + BASize =13; + } +#if defined(RT2883) || defined(RT3883) + else if (IS_RT2883(pAd) || IS_RT3883(pAd)) + { + if (BASize > 31) + BASize =31; + } +#endif /* defined(RT2883) || defined(RT3883) */ + else + { + if( BASize >7 ) + BASize =7; + } + + pTxWI->BAWinSize = BASize; + pTxWI->ShortGI = pTransmit->field.ShortGI; + pTxWI->STBC = pTransmit->field.STBC; + +#ifdef TXBF_SUPPORT + if (pMac && pAd->chipCap.FlgHwTxBfCap) + { + if (pMac->TxSndgType == SNDG_TYPE_NDP || pMac->TxSndgType == SNDG_TYPE_SOUNDING || pTxWI->eTxBF) + pTxWI->STBC = 0; + } +#endif /* TXBF_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + + pTxWI->WirelessCliID = WCID; + pTxWI->MPDUtotalByteCount = Length; + pTxWI->PacketId = PID; + + /* If CCK or OFDM, BW must be 20*/ + pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (pTxWI->BW) + pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW); +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + pTxWI->MCS = pTransmit->field.MCS; + pTxWI->PHYMODE = pTransmit->field.MODE; + pTxWI->CFACK = CfAck; + +#ifdef DOT11_N_SUPPORT + if (pMac) + { + if (pAd->CommonCfg.bMIMOPSEnable) + { + if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) + { + /* Dynamic MIMO Power Save Mode*/ + pTxWI->MIMOps = 1; + } + else if (pMac->MmpsMode == MMPS_STATIC) + { + /* Static MIMO Power Save Mode*/ + if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7) + { + pTxWI->MCS = 7; + pTxWI->MIMOps = 0; + } + } + } + /*pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;*/ + { + pTxWI->MpduDensity = pMac->MpduDensity; + } + } +#endif /* DOT11_N_SUPPORT */ + + + pTxWI->PacketId = pTxWI->MCS; + NdisMoveMemory(pOutTxWI, &TxWI, TXWISize); +} + + +VOID RTMPWriteTxWI_Data( + IN PRTMP_ADAPTER pAd, + IN OUT PTXWI_STRUC pTxWI, + IN TX_BLK *pTxBlk) +{ + HTTRANSMIT_SETTING *pTransmit; + PMAC_TABLE_ENTRY pMacEntry; +#ifdef DOT11_N_SUPPORT + UCHAR BASize; +#endif /* DOT11_N_SUPPORT */ + UINT8 TXWISize = pAd->chipCap.TXWISize; + + 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); + + pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag); + pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired); + pTxWI->txop = pTxBlk->FrameGap; + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT + if (pMacEntry && + (pAd->StaCfg.BssType == BSS_INFRA) && + IS_ENTRY_DLS(pMacEntry)) + pTxWI->WirelessCliID = BSSID_WCID; + else +#endif /* QOS_DLS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + pTxWI->WirelessCliID = pTxBlk->Wcid; + + pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack); + + /* If CCK or OFDM, BW must be 20*/ + pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (pTxWI->BW) + pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW); +#endif /* DOT11N_DRAFT3 */ + pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE); + +#ifdef TXBF_SUPPORT + if(pTxBlk->TxSndgPkt > SNDG_TYPE_DISABLE) + pTxWI->AMPDU = FALSE; +#endif /* TXBF_SUPPORT */ + + BASize = pAd->CommonCfg.TxBASize; + + if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (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 = 0; /*The RA's BA Originator table index.*/ + RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority]; + BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize; + } + } + +#ifdef TXBF_SUPPORT + if (pTxBlk->TxSndgPkt == SNDG_TYPE_SOUNDING) + { + pTxWI->Sounding = 1; +/* DBGPRINT(RT_DEBUG_OFF, ("\n @@@@@ 1. pTxBlk->TxSndgPkt = %d @@@@@ .\n", pTxBlk->TxSndgPkt));*/ + DBGPRINT(RT_DEBUG_TRACE, ("ETxBF in RTMPWriteTxWI_Data(): sending normal sounding, eTxBF=%d\n", pTxWI->eTxBF)); + pTxWI->iTxBF = 0; + } + else if (pTxBlk->TxSndgPkt == SNDG_TYPE_NDP) + { + if (pTxBlk->TxNDPSndgMcs>=16) + pTxWI->NDPSndRate = 2; + else if (pTxBlk->TxNDPSndgMcs>=8) + pTxWI->NDPSndRate = 1; + else + pTxWI->NDPSndRate = 0; + + pTxWI->NDPSndBW = pTransmit->field.BW; + + pTxWI->iTxBF = 0; + } + else + { +#ifdef MFB_SUPPORT + if (pMacEntry && (pMacEntry->mrqCnt >0) && (pMacEntry->toTxMrq == TRUE)) + { + pTxWI->eTxBF = ~(pTransmit->field.eTxBF); + } + else +#endif /* MFB_SUPPORT */ + pTxWI->eTxBF = pTransmit->field.eTxBF; + pTxWI->iTxBF = pTransmit->field.iTxBF; + } +#endif /* TXBF_SUPPORT */ + + pTxWI->BAWinSize = BASize; + pTxWI->ShortGI = pTransmit->field.ShortGI; + pTxWI->STBC = pTransmit->field.STBC; +#ifdef TXBF_SUPPORT + if (pTxBlk->TxSndgPkt == SNDG_TYPE_NDP || pTxBlk->TxSndgPkt == SNDG_TYPE_SOUNDING || pTxWI->eTxBF) + pTxWI->STBC = 0; +#endif /* TXBF_SUPPORT */ + +#endif /* DOT11_N_SUPPORT */ + + pTxWI->MCS = pTransmit->field.MCS; + pTxWI->PHYMODE = pTransmit->field.MODE; + + +#ifdef DOT11_N_SUPPORT + if (pMacEntry) + { + if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) + { + /* Dynamic MIMO Power Save Mode*/ + pTxWI->MIMOps = 1; + } + else if (pMacEntry->MmpsMode == MMPS_STATIC) + { + /* Static MIMO Power Save Mode*/ + if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7) + { + pTxWI->MCS = 7; + pTxWI->MIMOps = 0; + } + } + + if ((pAd->CommonCfg.BBPCurrentBW == BW_20) && (pMacEntry->bIAmBadAtheros)) + pTxWI->MpduDensity = 7; + else + pTxWI->MpduDensity = pMacEntry->MpduDensity; + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef TXBF_SUPPORT + if (pTxBlk->TxSndgPkt > SNDG_TYPE_DISABLE) + { + pTxWI->MCS = 0; + pTxWI->AMPDU = FALSE; + } +#endif /* TXBF_SUPPORT */ + +#ifdef DBG_DIAGNOSE + if (pTxBlk->QueIdx== 0) + { + pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++; + pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++; + } +#endif /* DBG_DIAGNOSE */ + + /* for rate adapation*/ + pTxWI->PacketId = pTxWI->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(pTxWI->PHYMODE == MODE_CCK) + { + pTxWI->PacketId = 6; + } + } +#endif /* INF_AMAZON_SE */ + +#ifdef MCS_LUT_SUPPORT + if (RTMP_GET_PACKET_LOWRATE(pTxBlk->pPacket) || + pTxBlk->TxFrameType == TX_MCAST_FRAME) + { + pTxWI->TXLUT = 0; + } + else + pTxWI->TXLUT = pAd->bUseHwTxLURate; +#endif /* MCS_LUT_SUPPORT */ + +} + + +VOID RTMPWriteTxWI_Cache( + IN PRTMP_ADAPTER pAd, + IN OUT PTXWI_STRUC pTxWI, + IN TX_BLK *pTxBlk) +{ + PHTTRANSMIT_SETTING /*pTxHTPhyMode,*/ pTransmit; + PMAC_TABLE_ENTRY pMacEntry; +#ifdef DOT11_N_SUPPORT +#endif /* DOT11_N_SUPPORT */ + + + /* update TXWI */ + pMacEntry = pTxBlk->pMacEntry; + pTransmit = pTxBlk->pTransmit; + + /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/ + /*if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pMacEntry))*/ + /*if (TX_BLK_TEST_FLAG(pTxBlk, fTX_AutoRateSwitch))*/ + if (pMacEntry->bAutoTxRateSwitch) + { + pTxWI->txop = IFS_HTTXOP; + + /* If CCK or OFDM, BW must be 20*/ + pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); + pTxWI->ShortGI = pTransmit->field.ShortGI; + pTxWI->STBC = pTransmit->field.STBC; + +#ifdef TXBF_SUPPORT + if (pTxBlk->TxSndgPkt == SNDG_TYPE_NDP || pTxBlk->TxSndgPkt == SNDG_TYPE_SOUNDING || pTxWI->eTxBF) + pTxWI->STBC = 0; +#endif /* TXBF_SUPPORT */ + + pTxWI->MCS = pTransmit->field.MCS; + pTxWI->PHYMODE = pTransmit->field.MODE; + + /* set PID for TxRateSwitching*/ + pTxWI->PacketId = pTransmit->field.MCS; + + } + +#ifdef DOT11_N_SUPPORT + pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE); +#ifdef TXBF_SUPPORT + if(pTxBlk->TxSndgPkt > SNDG_TYPE_DISABLE) + pTxWI->AMPDU = FALSE; +#endif /* TXBF_SUPPORT */ + + pTxWI->MIMOps = 0; + +#ifdef DOT11N_DRAFT3 + if (pTxWI->BW) + pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW); +#endif /* DOT11N_DRAFT3 */ + + if (pAd->CommonCfg.bMIMOPSEnable) + { + /* MIMO Power Save Mode*/ + if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) + { + /* Dynamic MIMO Power Save Mode*/ + pTxWI->MIMOps = 1; + } + else if (pMacEntry->MmpsMode == MMPS_STATIC) + { + /* Static MIMO Power Save Mode*/ + if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7)) + { + pTxWI->MCS = 7; + pTxWI->MIMOps = 0; + } + } + } + + if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (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)) + { + pTxWI->BAWinSize = 7; + } + } + + if ((pAd->CommonCfg.BBPCurrentBW == BW_20) && (pMacEntry->bIAmBadAtheros)) + pTxWI->MpduDensity = 7; + +#endif /* DOT11_N_SUPPORT */ + +#ifdef DBG_DIAGNOSE + if (pTxBlk->QueIdx== 0) + { + pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++; + pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++; + } +#endif /* DBG_DIAGNOSE */ + +#ifdef TXBF_SUPPORT + if (pTxBlk->TxSndgPkt == SNDG_TYPE_SOUNDING) + { + pTxWI->Sounding = 1; + pTxWI->eTxBF = 0; + pTxWI->iTxBF = 0; + DBGPRINT(RT_DEBUG_TRACE, ("ETxBF in RTMPWriteTxWI_Cache(): sending normal sounding, eTxBF=%d\n", pTxWI->eTxBF)); + } + else if (pTxBlk->TxSndgPkt == SNDG_TYPE_NDP) + { + if (pTxBlk->TxNDPSndgMcs>=16) + pTxWI->NDPSndRate = 2; + else if (pTxBlk->TxNDPSndgMcs>=8) + pTxWI->NDPSndRate = 1; + else + pTxWI->NDPSndRate = 0; + pTxWI->Sounding = 0; + pTxWI->eTxBF = 0; + pTxWI->iTxBF = 0; + + pTxWI->NDPSndBW = pTransmit->field.BW; + +/* + DBGPRINT(RT_DEBUG_TRACE, + ("%s():ETxBF, sending ndp sounding(BW=%d, Rate=%d, eTxBF=%d)\n", + __FUNCTION__, pTxWI->NDPSndBW, pTxWI->NDPSndRate, pTxWI->eTxBF)); +*/ + } + else + { + pTxWI->Sounding = 0; +#ifdef MFB_SUPPORT + if (pMacEntry && pMacEntry->mrqCnt >0 && pMacEntry->toTxMrq == 1) + { + pTxWI->eTxBF = ~(pTransmit->field.eTxBF); + DBGPRINT_RAW(RT_DEBUG_TRACE,("ETxBF in AP_AMPDU_Frame_Tx(): invert eTxBF\n")); + } + else +#endif /* MFB_SUPPORT */ + pTxWI->eTxBF = pTransmit->field.eTxBF; + + pTxWI->iTxBF = pTransmit->field.iTxBF; + + if (pTxWI->eTxBF || pTxWI->iTxBF) + pTxWI->STBC = 0; + } + + if (pTxBlk->TxSndgPkt > SNDG_TYPE_DISABLE) + { + pTxWI->MCS = 0; + pTxWI->AMPDU = FALSE; + } +#endif /* TXBF_SUPPORT */ + + pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + +#ifdef MCS_LUT_SUPPORT + if (RTMP_GET_PACKET_LOWRATE(pTxBlk->pPacket) || + pTxBlk->TxFrameType == TX_MCAST_FRAME) + { + pTxWI->TXLUT = 0; + } + else + pTxWI->TXLUT = pAd->bUseHwTxLURate; +#endif /* MCS_LUT_SUPPORT */ + +} + + +/* + ======================================================================== + + 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(...) + */ + AsicBBPReadWithRxChain(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue, RX_CHAIN_0); + + /* set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)*/ + /*AsicBBPWriteWithRxChain(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)), RX_CHAIN_ALL);*/ + RTMPSetAGCInitValue(pAd, BW_20); + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); + /*RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); abort all TX rings*/ +} + + +/* + ======================================================================== + + Routine Description: + Resume MSDU transmission + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPResumeMsduTransmission( + IN PRTMP_ADAPTER pAd) +{ +/* UCHAR IrqState;*/ + + 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")); + } + AsicBBPWriteWithRxChain(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue, RX_CHAIN_ALL); + + 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, + 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) +#ifdef P2P_SUPPORT + && (OpMode == OPMODE_AP) +#endif /* P2P_SUPPORT */ + ) + VLAN_Size = (pAd->ApCfg.MBSSID[FromWhichBSSID].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].\ + 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) +#ifdef P2P_SUPPORT + && (OpMode == OPMODE_STA) +#endif /* P2P_SUPPORT */ + ) + { + /* avoid local heap overflow, use dyanamic allocation */ + 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) + { + memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize); + Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize; + /*WpaEAPOLKeyAction(pAd, Elem);*/ + REPORT_MGMT_FRAME_TO_MLME(pAd, BSSID_WCID, Elem->Msg, Elem->MsgLen, 0, 0, 0, 0, OPMODE_STA); +/* kfree(Elem);*/ + os_free_mem(NULL, Elem); + } + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef P2P_SUPPORT + if (OpMode == OPMODE_AP) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { + UCHAR WhichBSSID = FromWhichBSSID; +#ifdef P2P_SUPPORT + if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_P2P_GO) + WhichBSSID = FromWhichBSSID - MIN_NET_DEVICE_FOR_P2P_GO; +#endif /* P2P_SUPPORT */ + 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 +#ifdef P2P_SUPPORT + if (OpMode == OPMODE_AP) + { + AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket)); + } + else + { + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket)); + } +#else + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket)); +#endif /* P2P_SUPPORT */ +#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, pPacket, pData, DataSize, OpMode); + + return nMSDU; +} + +VOID Indicate_AMSDU_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + UINT nMSDU; + + RTMP_UPDATE_OS_PACKET_INFO(pAd, pRxBlk, FromWhichBSSID); + RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); + nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize, pRxBlk->OpMode); +} +#endif /* DOT11_N_SUPPORT */ + +/* + ========================================================================== + 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( + IN PRTMP_ADAPTER pAd, + PUCHAR 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; +} + +MAC_TABLE_ENTRY *MacTableInsertEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR apidx, + IN UCHAR OpMode, + IN BOOLEAN CleanAll) +{ + UCHAR HashIdx; + int i, FirstWcid; + MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry; + BOOLEAN Cancelled; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; +#ifdef MAC_REPEATER_SUPPORT + BOOLEAN bAPCLI = FALSE; +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef MAC_REPEATER_SUPPORT + if ((apidx >= MIN_NET_DEVICE_FOR_APCLI) && + (apidx < MIN_NET_DEVICE_FOR_MESH) && + (pAd->ApCfg.bMACRepeaterEn == TRUE)) + { + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; + bAPCLI = TRUE; + } +#endif /* MAC_REPEATER_SUPPORT */ + + /* if FULL, return*/ + if (pAd->MacTab.Size >= MaxWcidNum) + return NULL; + +#ifdef MAC_REPEATER_SUPPORT + if ((pAd->ApCfg.bMACRepeaterEn == TRUE) && + (apidx < MIN_NET_DEVICE_FOR_WDS) && + (pAd->ApCfg.EntryClientCount > MAX_LEN_OF_MAC_TABLE)) + return NULL; +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef MAC_REPEATER_SUPPORT + if (bAPCLI && (pAd->ApCfg.bMACRepeaterEn == TRUE)) + FirstWcid = (MAX_LEN_OF_MAC_TABLE + (MAX_EXT_MAC_ADDR_SIZE * (apidx - MIN_NET_DEVICE_FOR_APCLI))); + else +#endif /* MAC_REPEATER_SUPPORT */ + 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< MaxWcidNum; 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 */ + 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; + } + + do + { +#ifdef CONFIG_STA_SUPPORT +#ifdef P2P_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_P2P_GO) + { + SET_ENTRY_CLIENT(pEntry); + pEntry->isCached = FALSE; + break; + } +#endif /* P2P_SUPPORT */ +#ifdef DOT11Z_TDLS_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_TDLS) + { + SET_ENTRY_TDLS(pEntry); + pEntry->isCached = FALSE; + break; + } +#endif /* DOT11Z_TDLS_SUPPORT */ +#ifdef QOS_DLS_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_DLS) + { + SET_ENTRY_DLS(pEntry); + pEntry->isCached = FALSE; + break; + } +#endif /* QOS_DLS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef MESH_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_MESH) + { + SET_ENTRY_MESH(pEntry); + pEntry->isCached = FALSE; + break; + } +#endif /* MESH_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_APCLI) + { + SET_ENTRY_APCLI(pEntry); + + pEntry->isCached = FALSE; +#ifdef P2P_SUPPORT + SET_P2P_CLI_ENTRY(pEntry); + pAd->P2pCfg.MyGOwcid = i; +#endif /* P2P_SUPPORT */ + break; + } +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_WDS) + { + SET_ENTRY_WDS(pEntry); + pEntry->isCached = FALSE; + break; + } +#endif /* WDS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef P2P_SUPPORT + if (OpMode == OPMODE_AP) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* 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; + } +#ifdef P2P_SUPPORT + SET_P2P_GO_ENTRY(pEntry); +#endif /* P2P_SUPPORT */ + } +#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->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 +#ifdef P2P_SUPPORT + if (OpMode == OPMODE_AP) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { + if (IS_ENTRY_CLIENT(pEntry)) /* Only Clent entry need the retry timer.*/ + { + RTMPInitTimer(pAd, &pEntry->RetryTimer, GET_TIMER_FUNCTION(WPARetryExec), pEntry, FALSE); + + /* 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; + + 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 */ +#ifdef DOT11Z_TDLS_SUPPORT + else if (IS_ENTRY_TDLS(pEntry)) + pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_TDLS); +#endif /* DOT11Z_TDLS_SUPPORT */ +#ifdef P2P_SUPPORT + else if (apidx == MIN_NET_DEVICE_FOR_P2P_GO) + pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_P2P_GO); +#endif /* P2P_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 MESH_SUPPORT + if (IS_ENTRY_MESH(pEntry)) + { + pEntry->AuthMode = pAd->MeshTab.AuthMode; /*Ndis802_11AuthModeOpen;*/ + pEntry->WepStatus = pAd->MeshTab.WepStatus; /*Ndis802_11EncryptionDisabled;*/ + DBGPRINT(RT_DEBUG_OFF, ("-->Insert Entry wcid=%d, authmode=%d \n", i, pEntry->AuthMode)); + if (pEntry->AuthMode < Ndis802_11AuthModeWPA) + { + /*pEntry->WpaState = AS_NOTUSE;*/ + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + } + else + { + /*pEntry->WpaState = AS_PTKSTART;*/ + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + } + + pEntry->MatchMeshTabIdx = pEntry->apidx; + break; + } +#endif /* MESH_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { + pEntry->AuthMode = pAd->ApCfg.ApCliTab[pEntry->apidx].AuthMode; + pEntry->WepStatus = pAd->ApCfg.ApCliTab[pEntry->apidx].WepStatus; + pEntry->MatchAPCLITabIdx = 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->MatchWDSTabIdx = pEntry->apidx; + break; + } +#endif /* WDS_SUPPORT */ +#ifdef P2P_SUPPORT + if (OpMode == OPMODE_AP) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { + MBSS_MR_APIDX_SANITY_CHECK(pAd, apidx); + pEntry->AuthMode = pAd->ApCfg.MBSSID[apidx].AuthMode; + pEntry->WepStatus = pAd->ApCfg.MBSSID[apidx].WepStatus; + pEntry->GroupKeyWepStatus = pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus; + + 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 +#ifdef P2P_SUPPORT + if (OpMode == OPMODE_STA) +#else + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) +#endif /* P2P_SUPPORT */ + { + pEntry->AuthMode = pAd->StaCfg.AuthMode; + pEntry->WepStatus = pAd->StaCfg.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); + COPY_MAC_ADDR(pEntry->HdrAddr1, pAddr); + + do + { +#ifdef MESH_SUPPORT + if (IS_ENTRY_MESH(pEntry)) + { + COPY_MAC_ADDR(pEntry->HdrAddr2, pAd->MeshTab.CurrentAddress); + COPY_MAC_ADDR(pEntry->HdrAddr3, pAd->MeshTab.CurrentAddress); + break; + } +#endif // MESH_SUPPORT // +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { + COPY_MAC_ADDR(pEntry->HdrAddr2, pAd->ApCfg.ApCliTab[pEntry->apidx].CurrentAddress); + COPY_MAC_ADDR(pEntry->HdrAddr3, pAddr); + break; + } +#endif // APCLI_SUPPORT // +#ifdef WDS_SUPPORT + if (IS_ENTRY_WDS(pEntry)) + { + COPY_MAC_ADDR(pEntry->HdrAddr2, pAd->ApCfg.MBSSID[MAIN_MBSSID].Bssid); + COPY_MAC_ADDR(pEntry->HdrAddr3, pAd->ApCfg.MBSSID[MAIN_MBSSID].Bssid); + break; + } +#endif // WDS_SUPPORT // +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT +#ifdef P2P_SUPPORT + if (apidx == MIN_NET_DEVICE_FOR_P2P_GO) + { + COPY_MAC_ADDR(pEntry->HdrAddr2, pAd->P2PCurrentAddress); + COPY_MAC_ADDR(pEntry->HdrAddr3, pAd->P2PCurrentAddress); + break; + } +#endif /* P2P_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + if (OpMode == OPMODE_AP) + { + COPY_MAC_ADDR(pEntry->HdrAddr2, pAd->ApCfg.MBSSID[apidx].Bssid); + COPY_MAC_ADDR(pEntry->HdrAddr3, pAd->ApCfg.MBSSID[apidx].Bssid); + break; + } +#endif // CONFIG_AP_SUPPORT // +#ifdef CONFIG_STA_SUPPORT + if (OpMode == OPMODE_STA) + { + COPY_MAC_ADDR(pEntry->HdrAddr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pEntry->HdrAddr3, pAddr); + break; + } +#endif // CONFIG_STA_SUPPORT // + } while (FALSE); + + 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; + { + 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 STREAM_MODE_SUPPORT + /* Enable Stream mode for first three entries in MAC table */ +#ifdef RT3883 + if (IS_RT3883(pAd)) + { + UINT32 streamWord = StreamModeRegVal(pAd); + + RTMP_IO_WRITE32(pAd, TX_CHAIN_ADDR0_L, 0xFFFFFFFF); + RTMP_IO_WRITE32(pAd, TX_CHAIN_ADDR0_H, streamWord | 0xFFFF); + if ((i >= FirstWcid) && (i <= (FirstWcid + 2))) + { + pEntry->StreamModeMACReg = TX_CHAIN_ADDR1_L + (i - FirstWcid) * 8; + RTMP_IO_WRITE32(pAd, pEntry->StreamModeMACReg, + (ULONG)(pAddr[0]) | (ULONG)(pAddr[1] << 8) | + (ULONG)(pAddr[2] << 16) | (ULONG)(pAddr[3] << 24)); + RTMP_IO_WRITE32(pAd, pEntry->StreamModeMACReg+4, + streamWord | (ULONG)(pAddr[4]) | (ULONG)(pAddr[5] << 8)); + /* AsicSetStreamMode(pAd, pAddr, i - FirstWcid + 1, TRUE); */ + } else { + pEntry->StreamModeMACReg = 0; + } + } +#endif /* RT3883 */ + +#endif /* STREAM_MODE_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT +#ifdef UAPSD_SUPPORT + /* init U-APSD enhancement related parameters */ + UAPSD_MR_ENTRY_INIT(pEntry); +#endif /* UAPSD_SUPPORT */ +#else +#ifdef CONFIG_AP_SUPPORT +#ifdef P2P_SUPPORT + if (OpMode == OPMODE_AP) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* 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 /* DOT11Z_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 CONFIG_AP_SUPPORT +#ifdef P2P_SUPPORT + if (OpMode == OPMODE_AP) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { +#ifdef WSC_AP_SUPPORT + pEntry->bWscCapable = FALSE; + pEntry->Receive_EapolStart_EapRspId = 0; +#endif /* WSC_AP_SUPPORT */ +#ifdef EASY_CONFIG_SETUP + pEntry->bRaAutoWpsCapable = FALSE; +#endif /* EASY_CONFIG_SETUP */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + NdisAllocateSpinLock(pAd, &pEntry->TxSndgLock); +#endif /* TXBF_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Aid = %d, Total= %d\n",i, pEntry->Aid, 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 +#ifdef P2P_SUPPORT + if (OpMode == OPMODE_AP) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_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 */ + + + } +#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 */ + } + + NdisReleaseSpinLock(&pAd->MacTabLock); + return pEntry; +} + +/* + ========================================================================== + Description: + Delete a specified client from MAC table + ========================================================================== + */ +BOOLEAN MacTableDeleteEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT wcid, + IN PUCHAR pAddr) +{ + USHORT HashIdx; + MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry; + BOOLEAN Cancelled; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn == TRUE) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + if (wcid >= MaxWcidNum) + return FALSE; + + NdisAcquireSpinLock(&pAd->MacTabLock); + + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + /*pEntry = pAd->MacTab.Hash[HashIdx];*/ + pEntry = &pAd->MacTab.Content[wcid]; + + if (pEntry && !IS_ENTRY_NONE(pEntry)) + { + /* ENTRY PREEMPTION: Cancel all timers */ + RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); + RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); + + if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) + { + +#ifdef DOT11_N_SUPPORT + /* free resources of BA*/ + BASessionTearDownALL(pAd, pEntry->Aid); +#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 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 P2P_SUPPORT + && (IS_P2P_GO_ENTRY(pEntry)) +#endif /* P2P_SUPPORT */ + ) + { +#ifdef DOT1X_SUPPORT + INT PmkCacheIdx = -1; +#endif /* DOT1X_SUPPORT */ + + RTMPReleaseTimer(&pEntry->RetryTimer, &Cancelled); + +#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].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].MSSIDDev); +#endif /* IGMP_SNOOP_SUPPORT */ + pAd->ApCfg.MBSSID[pEntry->apidx].StaCount--; + pAd->ApCfg.EntryClientCount--; + +#ifdef HOSTAPD_SUPPORT + if(pEntry && pAd->ApCfg.MBSSID[pEntry->apidx].Hostapd == TRUE ) + { + RtmpOSWrielessEventSendExt(pAd->net_dev, RT_WLAN_EVENT_EXPIRED, -1, pEntry->Addr, + NULL, 0,pEntry->apidx); + } +#endif + } +#ifdef APCLI_SUPPORT + else if (IS_ENTRY_APCLI(pEntry)) + { + RTMPReleaseTimer(&pEntry->RetryTimer, &Cancelled); + } +#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 +#ifdef DOT11Z_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 /* DOT11Z_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; + pWscControl->RegData.ReComputePke = 1; + NdisZeroMemory(&(pWscControl->EntryAddr[0]), MAC_ADDR_LEN); + } + } + pEntry->Receive_EapolStart_EapRspId = 0; + pEntry->bWscCapable = FALSE; +#ifdef EASY_CONFIG_SETUP + pEntry->bRaAutoWpsCapable = FALSE; +#endif /* EASY_CONFIG_SETUP */ +#ifdef WAC_SUPPORT + pEntry->bSamsungAutoWpsCapable = FALSE; +#ifdef WAC_QOS_PRIORITY + pEntry->bSamsungForcePriority = FALSE; +#endif /* WAC_QOS_PRIORITY */ +#endif /* WAC_SUPPORT */ + } +#endif /* WSC_AP_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + +// NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); + NdisZeroMemory(pEntry->Addr, MAC_ADDR_LEN); + /* invalidate the entry */ + SET_ENTRY_NONE(pEntry); + +#ifdef P2P_SUPPORT + if (IS_P2P_GO_ENTRY(pEntry)) + { + if (pEntry->WpaState == AS_PTKINITDONE) + SET_P2P_ENTRY_NONE(pEntry); + /* Legacy is leaving */ + if (pEntry->bP2pClient == FALSE) + { +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT + P2pSendWirelessEvent(pAd, RT_P2P_LEGACY_DISCONNECTED, NULL, pEntry->Addr); +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ + } + } +#endif /* P2P_SUPPORT */ + pAd->MacTab.Size --; +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + NdisFreeSpinLock(&pEntry->TxSndgLock); +#endif /* TXBF_SUPPORT */ +#ifdef P2P_SUPPORT + if (P2P_GO_ON(pAd)) + { + UINT32 i, p2pEntryCnt=0; + MAC_TABLE_ENTRY *pEntry; + PWSC_CTRL pWscControl = &pAd->ApCfg.MBSSID[0].WscControl; + + for (i=0; iMacTab.Content[i]; + if (IS_P2P_GO_ENTRY(pEntry)) + p2pEntryCnt++; + } + + if ((p2pEntryCnt == 0) && + (pWscControl->WscState == WSC_STATE_CONFIGURED) && + (pAd->flg_p2p_OpStatusFlags == P2P_GO_UP)) + { +#ifdef RTMP_MAC_PCI + P2pLinkDown(pAd, P2P_DISCONNECTED); +#endif /* RTMP_MAC_PCI */ +#ifdef DPA_S + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_LINK_LOSS, NULL, NULL, 0); +#endif /* DPA_S */ + } + DBGPRINT(RT_DEBUG_ERROR, ("MacTableDeleteEntry1 - Total= %d. p2pEntry = %d.\n", pAd->MacTab.Size, p2pEntryCnt)); + } +#endif /* P2P_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 + /*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( + IN PRTMP_ADAPTER pAd) +{ + int i; + BOOLEAN Cancelled; +#ifdef CONFIG_AP_SUPPORT +#ifdef RTMP_MAC_PCI + unsigned long IrqFlags=0; +#endif /* RTMP_MAC_PCI */ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + HEADER_802_11 DeAuthHdr; + USHORT Reason; + UCHAR apidx = MAIN_MBSSID; +#endif /* CONFIG_AP_SUPPORT */ + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + + DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n")); + /*NdisAcquireSpinLock(&pAd->MacTabLock);*/ + + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + for (i=1; iMacTab.Content[i])) + { + /* Delete a entry via WCID */ + + /*MacTableDeleteEntry(pAd, i, pAd->MacTab.Content[i].Addr);*/ + RTMPReleaseTimer(&pAd->MacTab.Content[i].EnqueueStartForPSKTimer, &Cancelled); +#ifdef CONFIG_STA_SUPPORT +#ifdef ADHOC_WPA2PSK_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + RTMPReleaseTimer(&pAd->MacTab.Content[i].WPA_Authenticator.MsgRetryTimer, &Cancelled); + } +#endif /* ADHOC_WPA2PSK_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + pAd->MacTab.Content[i].EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* Before reset MacTable, send disassociation packet to client.*/ + if (pAd->MacTab.Content[i].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 frame tO %02x:%02x:%02x:%02x:%02x:%02x \n",Reason, PRINT_MAC(pAd->MacTab.Content[i].Addr))); + MgtMacHeaderInit(pAd, &DeAuthHdr, SUBTYPE_DEAUTH, 0, pAd->MacTab.Content[i].Addr, +#ifdef P2P_SUPPORT + pAd->ApCfg.MBSSID[pAd->MacTab.Content[i].apidx].Bssid, +#endif /* P2P_SUPPORT */ + pAd->ApCfg.MBSSID[pAd->MacTab.Content[i].apidx].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, pAd->MacTab.Content[i].Addr); + } + else + { + /* Delete a entry via WCID */ + MacTableDeleteEntry(pAd, i, pAd->MacTab.Content[i].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; + pAd->ApCfg.MBSSID[apidx].WscControl.RegData.ReComputePke = 1; +#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 %ld...\n",pAd->MacTab.McastPsQueue.Number)); + if (pAd->MacTab.McastPsQueue.Number > 0) + APCleanupPsQueue(pAd, &pAd->MacTab.McastPsQueue); + DBGPRINT(RT_DEBUG_TRACE, ("2McastPsQueue.Number %ld...\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; +} + +/* + ========================================================================== + 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; +} + + +BOOLEAN RTMPCheckEtherType( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN PMAC_TABLE_ENTRY pMacEntry, + IN UCHAR OpMode, + OUT PUCHAR pUserPriority, + OUT PUCHAR pQueIdx) +{ + USHORT TypeLen; + UCHAR Byte0, Byte1; + PUCHAR pSrcBuf; + UINT32 pktLen; + UINT16 srcPort, dstPort; +#ifdef CONFIG_AP_SUPPORT + MULTISSID_STRUCT *pMbss; +#endif /* CONFIG_AP_SUPPORT */ + BOOLEAN bWmmReq; + +#ifdef CONFIG_AP_SUPPORT +/* if (IS_ENTRY_CLIENT(pMacEntry))*/ +/* pMbss = pMacEntry->pMbss;*/ +/* else*/ +/* pMbss = &pAd->ApCfg.MBSSID[MAIN_MBSSID];*/ +#ifdef P2P_SUPPORT + if (OpMode == OPMODE_AP) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { + /* for APClient, WDS, Mesh, they use MAIN BSS */ + UCHAR apidx; + apidx = RTMP_GET_PACKET_NET_DEVICE(pPacket); + if (apidx >= MAX_MBSSID_NUM(pAd)) + apidx = MAIN_MBSSID; + pMbss = &pAd->ApCfg.MBSSID[apidx]; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef P2P_SUPPORT + pMbss = &pAd->ApCfg.MBSSID[MAIN_MBSSID]; +#endif /* P2P_SUPPORT */ + /* + for bc/mc packets, if it has VLAN tag or DSCP field, we also need + to get UP for IGMP use. + */ + bWmmReq = ( +#ifdef CONFIG_AP_SUPPORT + ( +#ifdef P2P_SUPPORT + (OpMode == OPMODE_AP) && +#endif /* P2P_SUPPORT */ + (pMbss->bWmmCapable)) || +#endif /* CONFIG_AP_SUPPORT */ + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)) + && ((pMacEntry) && + ((VALID_WCID(pMacEntry->Aid) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)) + || (pMacEntry->Aid == MCAST_WCID))); + + pSrcBuf = GET_OS_PKT_DATAPTR(pPacket); + pktLen = GET_OS_PKT_LEN(pPacket); + + ASSERT(pSrcBuf); + + RTMP_SET_PACKET_SPECIFIC(pPacket, 0); + + /* get Ethernet protocol field*/ + TypeLen = (pSrcBuf[12] << 8) | pSrcBuf[13]; + + pSrcBuf += LENGTH_802_3; /* Skip the Ethernet Header.*/ + + 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)) + */ + 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 + { + /*It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.*/ + } + } + + /* If it's a VLAN packet, get the real Type/Length field.*/ + if (TypeLen == 0x8100) + { +#ifdef CONFIG_AP_SUPPORT + USHORT VLAN_VID = 0; + + /* 0x8100 means VLAN packets */ + + /* Dest. MAC Address (6-bytes) + + Source MAC Address (6-bytes) + + Length/Type = 802.1Q Tag Type (2-byte) + + Tag Control Information (2-bytes) + + Length / Type (2-bytes) + + data payload (0-n bytes) + + Pad (0-p bytes) + + Frame Check Sequence (4-bytes) */ + + /* No matter unicast or multicast */ + /*if (IS_ENTRY_CLIENT(pMacEntry))*/ +#ifdef WDS_VLAN_SUPPORT + if (IS_ENTRY_WDS(pMacEntry)) + { + UINT32 WdsId; + + WdsId = RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_WDS; + if (WdsId < MAX_WDS_ENTRY) + VLAN_VID = pAd->WdsTab.WdsEntry[WdsId].VLAN_VID; + } + else +#endif /* WDS_VLAN_SUPPORT */ + { + VLAN_VID = pMbss->VLAN_VID; + } /* End of if */ + + 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; + } /* End of if */ + } /* End of if */ +#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 */ + if (bWmmReq) + { + *pUserPriority = (*pSrcBuf & 0xe0) >> 5; +#ifdef RTMP_RBUS_SUPPORT +#ifdef VIDEO_TURBINE_SUPPORT + /* Ralink_VideoTurbine Out-band QoS */ + { + struct sk_buff *pSkbPkt = RTPKT_TO_OSPKT(pPacket); + if(pSkbPkt->cb[40]==0x0E) + { + *pUserPriority = (pSkbPkt->cb[41] & 0xe0) >> 5; + } + } +#endif /* VIDEO_TURBINE_SUPPORT */ +#endif /* RTMP_RBUS_SUPPORT */ + *pQueIdx = MapUserPriorityToAccessCategory[*pUserPriority]; + } + + pSrcBuf += 4; /* Skip the VLAN Header.*/ + } + else if (TypeLen == 0x0800) + { + if (bWmmReq) + { + if ((*pSrcBuf & 0xf0) == 0x40) /* IPv4 */ + { + /* + Version - 4-bit Internet Protocol version number. + Length - 4-bit IP header length. + Traffic Class - 8-bit TOS field. + */ + *pUserPriority = (*(pSrcBuf + 1) & 0xe0) >> 5; + } + +#ifdef RTMP_RBUS_SUPPORT +#ifdef VIDEO_TURBINE_SUPPORT + /* Ralink_VideoTurbine Out-band QoS */ + { + struct sk_buff *pSkbPkt = RTPKT_TO_OSPKT(pPacket); + if(pSkbPkt->cb[40]==0x0E) + { + *pUserPriority = (pSkbPkt->cb[41] & 0xe0) >> 5; + } + } +#endif /* VIDEO_TURBINE_SUPPORT */ +#endif /* RTMP_RBUS_SUPPORT */ + *pQueIdx = MapUserPriorityToAccessCategory[*pUserPriority]; + } + } + else if (TypeLen == 0x86dd) + { + if (bWmmReq) + { + if ((*pSrcBuf & 0xf0) == 0x60) /* IPv6 */ + { + /* + Version - 4-bit Internet Protocol version number. + Traffic Class - 8-bit traffic class field. + */ + *pUserPriority = ((*pSrcBuf) & 0x0e) >> 1; + } + +#ifdef RTMP_RBUS_SUPPORT +#ifdef VIDEO_TURBINE_SUPPORT + /* Ralink_VideoTurbine Out-band QoS */ + { + struct sk_buff *pSkbPkt = RTPKT_TO_OSPKT(pPacket); + if(pSkbPkt->cb[40]==0x0E) + { + *pUserPriority = (pSkbPkt->cb[41] & 0xe0) >> 5; + } + } +#endif /* VIDEO_TURBINE_SUPPORT */ +#endif /* RTMP_RBUS_SUPPORT */ + *pQueIdx = MapUserPriorityToAccessCategory[*pUserPriority]; + } + } + + switch (TypeLen) + { + case 0x0800: + { + /* return AC_BE if packet is not IPv4*/ + if (bWmmReq && (*pSrcBuf & 0xf0) != 0x40) + { + *pUserPriority = 0; + *pQueIdx = QID_AC_BE; + } + else + RTMP_SET_PACKET_IPV4(pPacket, 1); + + ASSERT((pktLen > 34)); + if (*(pSrcBuf + 9) == 0x11) + { /* udp packet*/ + ASSERT((pktLen > 34)); /* 14 for ethernet header, 20 for IP header*/ + + pSrcBuf += 20; /* Skip the IP header*/ + 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); + } + } + } + break; + case 0x86dd: + { + /* return AC_BE if packet is not IPv6 */ + if (bWmmReq && + ((*pSrcBuf & 0xf0) != 0x60)) + { + *pUserPriority = 0; + *pQueIdx = QID_AC_BE; + } + } + break; + case 0x0806: + { + /*ARP Packet.*/ + RTMP_SET_PACKET_DHCP(pPacket, 1); + } + break; + case 0x888e: + { + /* EAPOL Packet.*/ + RTMP_SET_PACKET_EAPOL(pPacket, 1); + } + break; +#ifdef WAPI_SUPPORT + case 0x88b4: + { + /* WAI Packet.*/ + /*hex_dump("WAI Packet", pSrcBuf, pktLen);*/ + RTMP_SET_PACKET_WAI(pPacket, 1); + } + break; +#endif /* WAPI_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT + case 0x890d: + { + RTMP_SET_PACKET_TDLS(pPacket, 1); + *pUserPriority = 5; + *pQueIdx = QID_AC_VI; + } + break; +#endif /* DOT11Z_TDLS_SUPPORT */ + + 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[*pQueIdx]) + { + *pUserPriority = 0; + *pQueIdx = QID_AC_BE; + } + +#ifdef WAC_SUPPORT +#ifdef WAC_QOS_PRIORITY + if (bWmmReq && (pMacEntry->bSamsungForcePriority)) + { + *pUserPriority = 7; + *pQueIdx = QID_AC_VO; + } +#endif /* WAC_QOS_PRIORITY */ +#endif /* WAC_SUPPORT */ + + return TRUE; + +} + + +VOID Update_Rssi_Sample( + IN PRTMP_ADAPTER pAd, + IN RSSI_SAMPLE *pRssi, + IN PRXWI_STRUC pRxWI) +{ + CHAR rssi0 = pRxWI->RSSI0; + CHAR rssi1 = pRxWI->RSSI1; + CHAR rssi2 = pRxWI->RSSI2; + UCHAR snr0 = pRxWI->SNR0; + UCHAR snr1 = pRxWI->SNR1; + CHAR Phymode = pRxWI->PHYMODE; + BOOLEAN bInitial = FALSE; + + if (!(pRssi->AvgRssi0 | pRssi->AvgRssi0X8 | pRssi->LastRssi0)) + { + bInitial = TRUE; + } + + if (rssi0 != 0) + { + + pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0); + + 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 (snr0 != 0 && Phymode != MODE_CCK) + { + pRssi->LastSnr0 = ConvertToSnr(pAd, (UCHAR)snr0); + + 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; + /*pRssi->LastNoiseLevel0 = pRssi->AvgRssi0 - pRssi->AvgSnr0;*/ + } + + if (rssi1 != 0) + { + pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1); + + 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 (snr1 != 0 && Phymode != MODE_CCK) + { + pRssi->LastSnr1 = ConvertToSnr(pAd, (UCHAR)snr1); + + 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; + /*pRssi->LastNoiseLevel1 = pRssi->AvgRssi1 - pRssi->AvgSnr1;*/ + } + + if (rssi2 != 0) + { + pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, 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( + IN PRTMP_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; + + /* + 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 +#ifdef P2P_SUPPORT + if (IS_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 */ + + if (pRxBlk->DataSize > MAX_RX_PKT_LEN) + { + + /* 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 */ + + RT_80211_TO_8023_PACKET(pAd, VLAN_VID, VLAN_Priority, + pRxBlk, Header802_3, FromWhichBSSID, TPID); + + /* 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) + { +#ifdef MAC_REPEATER_SUPPORT /* This should be moved to some where else */ + if (pRxBlk->RxD.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, dhcpHdr, pCliHwAddr; + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; + + bootpHdr = pUdpHdr + 8; + dhcpHdr = bootpHdr + 236; + pCliHwAddr = (bootpHdr+28); + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, FALSE, pCliHwAddr); + if (pReptEntry) + NdisMoveMemory(pCliHwAddr, pReptEntry->OriginalAddress, MAC_ADDR_LEN); + 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 +#ifdef P2P_SUPPORT + if (IS_OPMODE_AP(pRxBlk)) + { + UCHAR WhichBSSID = FromWhichBSSID; + + if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_P2P_GO) + WhichBSSID = FromWhichBSSID - MIN_NET_DEVICE_FOR_P2P_GO; + + 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 */ + + AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID); + } + else + { + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID); + } +#else + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID); +#endif /* P2P_SUPPORT */ +#endif /* CONFIG_STA_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)) + { + /* handle A-MSDU*/ + Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID); + } + else +#endif /* DOT11_N_SUPPORT */ + { + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + } + } +} + + +VOID CmmRxRalinkFrameIndicate( + IN PRTMP_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 packet*/ + 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 +#ifdef P2P_SUPPORT + if (IS_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); + + /* 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 +#ifdef P2P_SUPPORT + if (IS_OPMODE_AP(pRxBlk)) + { + /* pPacket2 = duplicate_pkt_with_VLAN(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID, TPID); */ + RT_VLAN_PKT_DUPLICATE(pPacket2, pAd, VLAN_VID, VLAN_Priority, + (pData2-LENGTH_802_3), LENGTH_802_3, pData2, + Payload2Size, FromWhichBSSID, TPID); + } + else + { + pPacket2 = duplicate_pkt(get_netdev_from_bssid(pAd, FromWhichBSSID), + (pData2-LENGTH_802_3), LENGTH_802_3, pData2, + Payload2Size, FromWhichBSSID); + } +#else + 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 /* P2P_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + if (!pPacket2) + { + /* release packet*/ + 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) +#ifdef P2P_SUPPORT + if (IS_OPMODE_AP(pRxBlk)) +#endif /* P2P_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 */ + 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 +#ifdef P2P_SUPPORT + if (IS_OPMODE_AP(pRxBlk)) + { + AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID); + } + else + { + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID); + } +#else + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID); +#endif /* P2P_SUPPORT */ +#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 +#ifdef P2P_SUPPORT + if (IS_OPMODE_AP(pRxBlk)) + { + AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID); + } + else + { + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID); + } +#else + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID); +#endif /* P2P_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + } +} + + +#define RESET_FRAGFRAME(_fragFrame) \ + { \ + _fragFrame.RxSize = 0; \ + _fragFrame.Sequence = 0; \ + _fragFrame.LastFrag = 0; \ + _fragFrame.Flags = 0; \ + } + + +PNDIS_PACKET RTMPDeFragmentDataFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PHEADER_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; + + + 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); + pAd->FragFrame.RxSize = DataSize + HeaderRoom; + NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize); + 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; /* give up this frame*/ + } + else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE) + { + /* 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; /* give up this frame*/ + } + + + /* Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.*/ + /* In this case, we will dropt 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; /* give up this frame*/ + } + + 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; + 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; + } + else + { + RESET_FRAGFRAME(pAd->FragFrame); + } + } + + return pRetPacket; +} + +VOID Indicate_EAPOL_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + +#ifdef CONFIG_AP_SUPPORT +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (pRxBlk->pRxWI->WirelessCliID >= MaxWcidNum) + { + DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: invalid wcid.\n")); + /* release packet*/ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + pEntry = &pAd->MacTab.Content[pRxBlk->pRxWI->WirelessCliID]; + if (pEntry) + { + APRxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); + return; + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef P2P_SUPPORT + if (IS_OPMODE_AP(pRxBlk)) + { + if (pRxBlk->pRxWI->WirelessCliID >= MAX_LEN_OF_MAC_TABLE) + { + DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: invalid wcid.\n")); + // release packet + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + pEntry = &pAd->MacTab.Content[pRxBlk->pRxWI->WirelessCliID]; + if (pEntry) + { + APRxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); + return; + } + } + else +#endif /* P2P_SUPPORT */ + { + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); + return; + } + } +#endif /* CONFIG_STA_SUPPORT */ + + if (pEntry == NULL) + { + DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n")); + /* release packet*/ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } +} + +#define BCN_TBTT_OFFSET 64 /*defer 64 us*/ +VOID ReSyncBeaconTime( + IN PRTMP_ADAPTER pAd) +{ + + UINT32 Offset; + + + 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)) + { + BCN_TIME_CFG_STRUC csr; + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); + csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; /* ASIC register in units of 1/16 TU = 64us*/ + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); + } + else + { + if (Offset == (BCN_TBTT_OFFSET-1)) + { + BCN_TIME_CFG_STRUC csr; + + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); + csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; /* ASIC register in units of 1/16 TU*/ + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); + } + } +} + +#ifdef SOFT_ENCRYPT +BOOLEAN RTMPExpandPacketForSwEncrypt( + IN PRTMP_ADAPTER pAd, + IN PTX_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 PRTMP_ADAPTER pAd, + IN PTX_BLK pTxBlk, + IN PUCHAR pHdr) +{ + PHEADER_802_11 pHeader_802_11; + PMAC_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 PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR TxRate, + IN UCHAR PID, + IN UCHAR apidx, + IN BOOLEAN bQosNull, + IN BOOLEAN bEOSP, + IN UCHAR OldUP) +{ +#ifdef DOT11Z_TDLS_SUPPORT + MAC_TABLE_ENTRY *pEntry; +#endif /* DOT11Z_TDLS_SUPPORT */ + NDIS_STATUS NState; + PHEADER_802_11 pNullFr; + PUCHAR pFrame; + ULONG Length; + + /* since TxRate may change, we have to change Duration each time */ + NState = MlmeAllocateMemory(pAd, (PUCHAR *)&pFrame); + pNullFr = (PHEADER_802_11) pFrame; + Length = sizeof(HEADER_802_11); + + if (NState == NDIS_STATUS_SUCCESS) + { +#ifdef CONFIG_AP_SUPPORT + MgtMacHeaderInit(pAd, pNullFr, SUBTYPE_NULL_FUNC, 0, pAddr, +#ifdef P2P_SUPPORT + pAd->ApCfg.MBSSID[apidx].Bssid, +#endif /* P2P_SUPPORT */ + pAd->ApCfg.MBSSID[apidx].Bssid); +#endif /* CONFIG_AP_SUPPORT */ + + pNullFr->FC.Type = BTYPE_DATA; + pNullFr->FC.FrDs = 1; + pNullFr->Duration = RTMPCalcDuration(pAd, TxRate, 14); + +#ifdef DOT11Z_TDLS_SUPPORT + pEntry = MacTableLookup(pAd, pAddr); + 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 */ + +#ifdef UAPSD_SUPPORT + 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; + } /* End of if */ +#endif /* UAPSD_SUPPORT */ + + DBGPRINT(RT_DEBUG_INFO, ("send NULL Frame @%d Mbps to AID#%d...\n", RateIdToMbps[TxRate], PID & 0x3f)); + MiniportMMRequest(pAd, MapUserPriorityToAccessCategory[7], (PUCHAR)pNullFr, Length); + MlmeFreeMemory(pAd, pFrame); + } +} + +#ifdef P2P_SUPPORT +BOOLEAN RxDoneInterruptHandle( + IN PRTMP_ADAPTER pAd) +{ + //NDIS_STATUS Status; + UINT32 RxProcessed, RxPending; + BOOLEAN bReschedule = FALSE; + UCHAR *pData; + PRXWI_STRUC pRxWI; + PNDIS_PACKET pRxPacket; + PHEADER_802_11 pHeader; + RX_BLK RxCell, *pRxCell; +//#ifdef CONFIG_AP_SUPPORT +// MULTISSID_STRUCT *pMbss; +//#endif // CONFIG_AP_SUPPORT // +#ifdef WDS_SUPPORT + MAC_TABLE_ENTRY *pEntry = NULL; +#endif + RT28XX_RXD_STRUC *pRxD; + UINT8 RXWISize = pAd->chipCap.RXWISize; + +#ifdef LINUX +#ifdef RTMP_RBUS_SUPPORT +#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE) + classifier_cur_cycle = read_c0_count(); +#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)) + { + break; + } + +#ifdef UAPSD_SUPPORT + UAPSD_TIMING_RECORD_INDEX(RxProcessed); +#endif // UAPSD_SUPPORT // + +#ifdef RTMP_MAC_PCI + if (RxProcessed++ > MAX_RX_PROCESS_CNT) + { + // need to reschedule rx handle + bReschedule = TRUE; + 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 // + +#ifdef VENDOR_FEATURE1_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 >= 4) + { + NICUpdateFifoStaCounters(pAd); + pAd->FifoUpdateDone = 0; + } +#else + NICUpdateFifoStaCounters(pAd); +#endif // VENDOR_FEATURE1_SUPPORT // +#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 + */ + + pRxCell = &RxCell; + pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending); + if (pRxPacket == NULL) + break; + + /* get rx ring descriptor and data buffer */ + pRxD = &(RxCell.RxD); + pData = GET_OS_PKT_DATAPTR(pRxPacket); + pRxWI = (PRXWI_STRUC) pData; + pHeader = (PHEADER_802_11) (pData + RXWISize) ; + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHeader, DIR_READ, TRUE); + RTMPWIEndianChange(pAd, (PUCHAR)pRxWI, TYPE_RXWI); +#endif + // build RxCell + pRxCell->pRxWI = pRxWI; + pRxCell->pHeader = pHeader; + pRxCell->pRxPacket = pRxPacket; + pRxCell->pData = (UCHAR *) pHeader; + pRxCell->DataSize = pRxWI->MPDUtotalByteCount; + pRxCell->Flags = 0; + + // Increase Total receive byte counter after real data received no mater any error or not + pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount; + pAd->RalinkCounters.OneSecReceivedByteCount += pRxWI->MPDUtotalByteCount; + pAd->RalinkCounters.RxCount ++; + pAd->RalinkCounters.OneSecRxCount ++; + +#ifdef STATS_COUNT_SUPPORT + INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount); +#endif // STATS_COUNT_SUPPORT // + + if (P2P_GO_ON(pAd) || P2P_CLI_ON(pAd)) + { + if (NdisEqualMemory(pAd->P2PCurrentAddress, pHeader->Addr1, MAC_ADDR_LEN) || + (pHeader->FC.SubType == SUBTYPE_PROBE_REQ) || + (pHeader->FC.SubType == SUBTYPE_BEACON + && NdisEqualMemory(pAd->ApCfg.ApCliTab[0].CfgApCliBssid, pHeader->Addr2, MAC_ADDR_LEN)) || + NdisEqualMemory(pAd->ApCfg.ApCliTab[BSS0].ApCliMlmeAux.Bssid, pHeader->Addr2, MAC_ADDR_LEN)) + { + bReschedule = APHandleRxDonePacket(pAd, pRxPacket, pRxCell); + } + else + bReschedule = STAHandleRxDonePacket(pAd, pRxPacket, pRxCell); + } + else + { + bReschedule = STAHandleRxDonePacket(pAd, pRxPacket, pRxCell); + } + } + +#ifdef UAPSD_SUPPORT + /* dont remove the function or UAPSD will fail */ + UAPSD_MR_SP_RESUME(pAd); + UAPSD_SP_CloseInRVDone(pAd); +#endif // UAPSD_SUPPORT // + + return bReschedule; +} +#endif /* P2P_SUPPORT */ + diff --git a/mt7620/src/common/cmm_data_pci.c b/mt7620/src/common/cmm_data_pci.c new file mode 100644 index 0000000..bb4b03a --- /dev/null +++ b/mt7620/src/common/cmm_data_pci.c @@ -0,0 +1,1827 @@ +/**************************************************************************** + * 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: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +/* + All functions in this file must be PCI-depended, or you should out your function + in other files. + +*/ +#include "rt_config.h" + + +VOID DBGPRINT_TX_RING( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx) +{ + UINT32 Ac0Base; + UINT32 Ac0HwIdx = 0, Ac0SwIdx = 0, AC0freeIdx; + int i; + //PULONG pTxD; + PTXD_STRUC pTxD; + PULONG ptemp; + + DBGPRINT_RAW(RT_DEBUG_WARN, ("=====================================================\n " )); + switch (QueIdx) + { + case QID_AC_BE: + RTMP_IO_READ32(pAd, TX_BASE_PTR0, &Ac0Base); + RTMP_IO_READ32(pAd, TX_CTX_IDX0, &Ac0SwIdx); + RTMP_IO_READ32(pAd, TX_DTX_IDX0, &Ac0HwIdx); + DBGPRINT_RAW(RT_DEBUG_WARN, ("All QID_AC_BE DESCRIPTOR \n " )); + for (i=0;iTxRing[QID_AC_BE].Cell[i].AllocVa; + pTxD = (PTXD_STRUC)pAd->TxRing[QID_AC_BE].Cell[i].AllocVa; + DBGPRINT_RAW(RT_DEBUG_WARN, ("[%02d] %08lx: %08lx: %08lx: %08lx, DMADONE = %x\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3), pTxD->DMADONE)); + } + DBGPRINT_RAW(RT_DEBUG_WARN, (" \n " )); + break; + case QID_AC_BK: + RTMP_IO_READ32(pAd, TX_BASE_PTR1, &Ac0Base); + RTMP_IO_READ32(pAd, TX_CTX_IDX1, &Ac0SwIdx); + RTMP_IO_READ32(pAd, TX_DTX_IDX1, &Ac0HwIdx); + DBGPRINT_RAW(RT_DEBUG_WARN, ("All QID_AC_BK DESCRIPTOR \n " )); + for (i=0;iTxRing[QID_AC_BK].Cell[i].AllocVa; + pTxD = (PTXD_STRUC)pAd->TxRing[QID_AC_BK].Cell[i].AllocVa; + DBGPRINT_RAW(RT_DEBUG_WARN, ("[%02d] %08lx: %08lx: %08lx: %08lx, DMADONE = %x\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3), pTxD->DMADONE)); + } + DBGPRINT_RAW(RT_DEBUG_WARN, (" \n " )); + break; + case QID_AC_VI: + RTMP_IO_READ32(pAd, TX_BASE_PTR2, &Ac0Base); + RTMP_IO_READ32(pAd, TX_CTX_IDX2, &Ac0SwIdx); + RTMP_IO_READ32(pAd, TX_DTX_IDX2, &Ac0HwIdx); + DBGPRINT_RAW(RT_DEBUG_WARN, ("All QID_AC_VI DESCRIPTOR \n " )); + for (i=0;iTxRing[QID_AC_VI].Cell[i].AllocVa; + pTxD = (PTXD_STRUC)pAd->TxRing[QID_AC_VI].Cell[i].AllocVa; + DBGPRINT_RAW(RT_DEBUG_WARN, ("[%02d] %08lx: %08lx: %08lx: %08lx, DMADONE = %x\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3), pTxD->DMADONE)); + } + DBGPRINT_RAW(RT_DEBUG_WARN, (" \n " )); + break; + case QID_AC_VO: + RTMP_IO_READ32(pAd, TX_BASE_PTR3, &Ac0Base); + RTMP_IO_READ32(pAd, TX_CTX_IDX3, &Ac0SwIdx); + RTMP_IO_READ32(pAd, TX_DTX_IDX3, &Ac0HwIdx); + DBGPRINT_RAW(RT_DEBUG_WARN, ("All QID_AC_VO DESCRIPTOR \n " )); + for (i=0;iTxRing[QID_AC_VO].Cell[i].AllocVa; + pTxD = (PTXD_STRUC)pAd->TxRing[QID_AC_VO].Cell[i].AllocVa; + DBGPRINT_RAW(RT_DEBUG_WARN, ("[%02d] %08lx: %08lx: %08lx: %08lx, DMADONE = %x\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3), pTxD->DMADONE)); + } + DBGPRINT_RAW(RT_DEBUG_WARN, (" \n " )); + break; + case QID_MGMT: + RTMP_IO_READ32(pAd, TX_BASE_PTR5, &Ac0Base); + RTMP_IO_READ32(pAd, TX_CTX_IDX5, &Ac0SwIdx); + RTMP_IO_READ32(pAd, TX_DTX_IDX5, &Ac0HwIdx); + DBGPRINT_RAW(RT_DEBUG_WARN, (" All QID_MGMT DESCRIPTOR \n " )); + for (i=0;iMgmtRing.Cell[i].AllocVa; + pTxD = (PTXD_STRUC)pAd->MgmtRing.Cell[i].AllocVa; + DBGPRINT_RAW(RT_DEBUG_WARN, ("[%02d] %08lx: %08lx: %08lx: %08lx, DMADONE = %x\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3), pTxD->DMADONE)); + } + DBGPRINT_RAW(RT_DEBUG_WARN, (" \n " )); + break; + + default: + DBGPRINT_ERR(("DBGPRINT_TX_RING(Ring %d) not supported\n", QueIdx)); + break; + } + + if (QueIdx < NUM_OF_TX_RING) { + AC0freeIdx = pAd->TxRing[QueIdx].TxSwFreeIdx; + + DBGPRINT(RT_DEBUG_WARN,("TxRing%d, TX_DTX_IDX=%d, TX_CTX_IDX=%d\n", QueIdx, Ac0HwIdx, Ac0SwIdx)); + DBGPRINT_RAW(RT_DEBUG_WARN,(" TxSwFreeIdx[%d]", AC0freeIdx)); + DBGPRINT_RAW(RT_DEBUG_WARN,(" pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount)); + } else if (QueIdx == QID_MGMT) { + AC0freeIdx = pAd->MgmtRing.TxSwFreeIdx; + + DBGPRINT(RT_DEBUG_WARN,("TxRing%d, TX_DTX_IDX=%d, TX_CTX_IDX=%d\n", QueIdx, Ac0HwIdx, Ac0SwIdx)); + DBGPRINT_RAW(RT_DEBUG_WARN,(" TxSwFreeIdx[%d]", AC0freeIdx)); + DBGPRINT_RAW(RT_DEBUG_WARN,(" pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount)); + } + +} + +USHORT RtmpPCI_WriteSingleTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN BOOLEAN bIsLast, + OUT USHORT *FreeNumber) +{ + + UCHAR *pDMAHeaderBufVA; + USHORT TxIdx, RetTxIdx; + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; +#endif + UINT32 BufBasePaLow; + PRTMP_TX_RING pTxRing; + USHORT hwHeaderLen; + 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; + + NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWISize + hwHeaderLen); + + 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; +#else + pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; +#endif + NdisZeroMemory(pTxD, TXD_SIZE); + + pTxD->SDPtr0 = BufBasePaLow; + pTxD->SDLen0 = TXINFO_SIZE + TXWISize + hwHeaderLen; /* include padding*/ + pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, RTMP_PCI_DMA_TODEVICE); + pTxD->SDLen1 = pTxBlk->SrcBufLen; + pTxD->LastSec0 = !(pTxD->SDLen1); + pTxD->LastSec1 = (bIsLast && pTxD->SDLen1) ? 1 : 0; + + if (pTxBlk->TxFrameType == TX_MCAST_FRAME) + RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_HCCA); + else + RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI); + RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE + 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); + 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; +} + + +USHORT RtmpPCI_WriteMultiTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR frameNum, + OUT USHORT *FreeNumber) +{ + BOOLEAN bIsLast; + UCHAR *pDMAHeaderBufVA; + USHORT TxIdx, RetTxIdx; + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; +#endif + UINT32 BufBasePaLow; + PRTMP_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-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD;*/ + hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; + else if (pTxBlk->TxFrameType == TX_RALINK_FRAME) + /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD;*/ + hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD; + else + /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);*/ + hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + + firstDMALen = TXINFO_SIZE + TXWISize + hwHdrLen; + } + else + { + firstDMALen = pTxBlk->MpduHeaderLen; + } + + NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, 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; +#else + pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; +#endif + NdisZeroMemory(pTxD, TXD_SIZE); + + pTxD->SDPtr0 = BufBasePaLow; + pTxD->SDLen0 = firstDMALen; /* include padding*/ + pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, RTMP_PCI_DMA_TODEVICE);; + pTxD->SDLen1 = pTxBlk->SrcBufLen; + pTxD->LastSec0 = !(pTxD->SDLen1); + pTxD->LastSec1 = (bIsLast && pTxD->SDLen1) ? 1 : 0; + + RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); + +#ifdef RT_BIG_ENDIAN + if (frameNum == 0) + RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA+ TXINFO_SIZE + TXWISize), DIR_WRITE, FALSE); + + if (frameNum != 0) + RTMPWIEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), 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 PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN USHORT totalMPDUSize, + IN USHORT FirstTxIdx) +{ + + PTXWI_STRUC pTxWI; + PRTMP_TX_RING pTxRing; + + + /* get Tx Ring Resource*/ + pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; + pTxWI = (PTXWI_STRUC) pTxRing->Cell[FirstTxIdx].DmaBuf.AllocVa; + pTxWI->MPDUtotalByteCount = totalMPDUSize; +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, (PUCHAR)pTxWI, TYPE_TXWI); +#endif /* RT_BIG_ENDIAN */ + +} + +USHORT RtmpPCI_WriteFragTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR fragNum, + OUT USHORT *FreeNumber) +{ + UCHAR *pDMAHeaderBufVA; + USHORT TxIdx, RetTxIdx; + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; +#endif + UINT32 BufBasePaLow; + PRTMP_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 = TXINFO_SIZE + TXWISize + hwHeaderLen; + NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen); + + /* Build Tx Descriptor*/ +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; +#else + pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; +#endif + NdisZeroMemory(pTxD, TXD_SIZE); + + if (fragNum == pTxBlk->TotalFragNum) + { + pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; + pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; + } + + pTxD->SDPtr0 = BufBasePaLow; + pTxD->SDLen0 = firstDMALen; /* include padding*/ + pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, RTMP_PCI_DMA_TODEVICE); + pTxD->SDLen1 = pTxBlk->SrcBufLen; + if (pTxD->SDLen1 > 0) + { + pTxD->LastSec0 = 0; + pTxD->LastSec1 = 1; + } + else + { + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 0; + } + RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); + +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI); + RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE + 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 PUCHAR pSrcBufVA, + IN UINT SrcBufLen) +{ + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; +#endif + ULONG SwIdx = pAd->MgmtRing.TxCpuIdx; + +#ifdef RT_BIG_ENDIAN + pDestTxD = (PTXD_STRUC)pAd->MgmtRing.Cell[SwIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SwIdx].AllocVa; +#endif + + pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket; + pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL; + + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 0; + pTxD->SDLen1 = 0; + pTxD->SDPtr0 = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, RTMP_PCI_DMA_TODEVICE); + pTxD->SDLen0 = SrcBufLen; + RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_MGMT); + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif + +/*==================================================================*/ +/* DBGPRINT_RAW(RT_DEBUG_TRACE, ("MLMEHardTransmit\n")); + for (i = 0; i < (TXWI_SIZE+24); i++) + { + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("%x:", *(pSrcBufVA+i))); + if ( i%4 == 3) + DBGPRINT_RAW(RT_DEBUG_TRACE, (" :: ")); + if ( i%16 == 15) + DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n ")); + } + DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n "));*/ +/*=======================================================================*/ + + 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, RXD_SIZE); + + /* Increase TX_CTX_IDX, but write to register later.*/ + INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE); + + RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); + + return 0; +} + + +#ifdef CONFIG_STA_SUPPORT +/* + ======================================================================== + + Routine Description: + Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound + + Arguments: + pRxD Pointer to the Rx descriptor + + Return Value: + NDIS_STATUS_SUCCESS No err + NDIS_STATUS_FAILURE Error + + Note: + + ======================================================================== +*/ +NDIS_STATUS RTMPCheckRxError( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHeader, + IN PRXWI_STRUC pRxWI, + IN PRT28XX_RXD_STRUC pRxD) +{ + PCIPHER_KEY pWpaKey; + INT dBm; + + /* Phy errors & CRC errors*/ + if (/*(pRxD->PhyErr) ||*/ (pRxD->Crc)) + { + /* Check RSSI for Noise Hist statistic collection.*/ + dBm = (INT) (pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta; + 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 += (pRxD->SDL0 + 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 +#ifdef MESH_SUPPORT + && !MESH_ON(pAd) +#endif /* MESH_SUPPORT */ + ) + { + return(NDIS_STATUS_FAILURE); + } +#endif /* CLIENT_WDS */ + } + + /* + 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 (pRxD->U2M == 0) + return(NDIS_STATUS_FAILURE); + */ + + /* drop decyption fail frame*/ + if (pRxD->CipherErr) + { + if (pRxD->CipherErr == 2) + {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV ok but MICErr "));} + else if (pRxD->CipherErr == 1) + {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV Err "));} + else if (pRxD->CipherErr == 3) + DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: Key not valid ")); + + if (((pRxD->CipherErr & 1) == 1) && INFRA_ON(pAd)) + RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + + DBGPRINT_RAW(RT_DEBUG_TRACE,(" %d (len=%d, Mcast=%d, MyBss=%d, Wcid=%d, KeyId=%d)\n", + pRxD->CipherErr, + pRxD->SDL0, + pRxD->Mcast | pRxD->Bcast, + pRxD->MyBss, + pRxWI->WirelessCliID, +/* CipherName[pRxD->CipherAlg],*/ + pRxWI->KeyIndex)); + + + /* MIC Error*/ + + if (pRxD->CipherErr == 2) + { + pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex]; +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP) + WpaSendMicFailureToWpaSupplicant(pAd->net_dev, + (pWpaKey->Type == PAIRWISEKEY) ? TRUE:FALSE); + else +#endif /* WPA_SUPPLICANT_SUPPORT */ + RTMPReportMicError(pAd, pWpaKey); + + if (((pRxD->CipherErr & 2) == 2) && INFRA_ON(pAd)) + RTMPSendWirelessEvent(pAd, IW_MIC_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + + DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n")); + } + + if (pHeader == NULL) + return(NDIS_STATUS_SUCCESS); + return(NDIS_STATUS_FAILURE); + } + + return(NDIS_STATUS_SUCCESS); +} +#endif /* CONFIG_STA_SUPPORT */ + + +BOOLEAN RTMPFreeTXDUponTxDmaDone( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx) +{ + PRTMP_TX_RING pTxRing; + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; +#endif + PNDIS_PACKET pPacket; + UCHAR FREE = 0; + TXD_STRUC TxD, *pOriTxD; + /*ULONG IrqFlags;*/ + BOOLEAN bReschedule = FALSE; + UINT8 TXWISize = pAd->chipCap.TXWISize; + + + ASSERT(QueIdx < NUM_OF_TX_RING); + if (QueIdx >= NUM_OF_TX_RING) + return FALSE; + + pTxRing = &pAd->TxRing[QueIdx]; + + RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, &pTxRing->TxDmaIdx); + while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx) + { +/* RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);*/ +#ifdef RALINK_ATE +#ifdef RALINK_QA + PHEADER_802_11 pHeader80211; + + if ((ATE_ON(pAd)) && (pAd->ate.bQATxStart == TRUE)) + { + if (pAd->ate.QID == QueIdx) + { + 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) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); + pOriTxD = pTxD; + NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); + pTxD = &TxD; +#else + pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); + pOriTxD = pDestTxD ; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + pTxD->DMADONE = 0; + + pHeader80211 = (PHEADER_802_11)((UCHAR *)(pTxRing->Cell[pTxRing->TxSwFreeIdx].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(pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocPa, RXD_SIZE); + + INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); + + /* get TX_DTX_IDX again */ + RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &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)); + } + +#ifndef RT_BIG_ENDIAN + NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); +#else + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + *pDestTxD = TxD; +#endif /* RT_BIG_ENDIAN */ + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocPa, RXD_SIZE); + + INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); + continue; + } + } +#endif /* RALINK_QA */ +#endif /* RALINK_ATE */ + + /* static rate also need NICUpdateFifoStaCounters() function.*/ + /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/ +#ifdef VENDOR_FEATURE1_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->FifoUpdateRx >= 4) + { + NICUpdateFifoStaCounters(pAd); + pAd->FifoUpdateRx = 0; + } +#else + NICUpdateFifoStaCounters(pAd); +#endif /* VENDOR_FEATURE1_SUPPORT */ + + /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */ + FREE++; +#ifndef RT_BIG_ENDIAN + pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); + pOriTxD = pTxD; + NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); + pTxD = &TxD; +#else + pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); + pOriTxD = pDestTxD ; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + +/* pTxD->DMADONE = 0; */ +#ifdef DOT11Z_TDLS_SUPPORT +#ifdef UAPSD_SUPPORT + UAPSD_SP_PacketCheck(pAd, + pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket, + ((UCHAR *)pTxRing->Cell[\ + pTxRing->TxSwFreeIdx].DmaBuf.AllocVa) + TXWISize); +#endif /* UAPSD_SUPPORT */ +#else +#ifdef CONFIG_AP_SUPPORT +#ifdef UAPSD_SUPPORT +#ifdef P2P_SUPPORT + if (P2P_GO_ON(pAd)) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { + UAPSD_SP_PacketCheck(pAd, + pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket, + ((UCHAR *)pTxRing->Cell[\ + pTxRing->TxSwFreeIdx].DmaBuf.AllocVa) + TXWISize); + } +#endif /* UAPSD_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +#endif /* DOT11Z_TDLS_SUPPORT */ + +#ifdef RALINK_ATE + /* Execution of this block is not allowed when ATE is running. */ + if (!(ATE_ON(pAd))) +#endif /* RALINK_ATE */ + { + pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket; + if (pPacket) + { +#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); + + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + /*Always assign pNdisPacket as NULL after clear*/ + pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL; + + pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket; + if (pPacket) + { +#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); + + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + /*Always assign pNextNdisPacket as NULL after clear*/ + pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL; + } + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocPa, RXD_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 */ + RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx); +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + *pDestTxD = TxD; +#else + NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); +#endif + +#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); + pOriTxD = pTxD; + NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); + pTxD = &TxD; +#else + pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa); + pOriTxD = pDestTxD ; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + pTxD->DMADONE = 0; +#ifndef RT_BIG_ENDIAN + NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); +#else + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + *pDestTxD = TxD; +#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, TX_CTX_IDX0 + QueIdx * RINGREG_DIFF, pAd->TxRing[QueIdx].TxCpuIdx); + pAd->RalinkCounters.KickTxCount++; + } + } +#endif /* RALINK_ATE */ +/* RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);*/ + } + + + 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 PRTMP_ADAPTER pAd, + IN INT_SOURCE_CSR_STRUC TxRingBitmap) +{ +/* UCHAR Count = 0;*/ + unsigned long IrqFlags; + BOOLEAN bReschedule = FALSE; + + /* Make sure Tx ring resource won't be used by other threads*/ + /*NdisAcquireSpinLock(&pAd->TxRingLock);*/ + + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + + if (TxRingBitmap.field.Ac0DmaDone) + bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE); + + if (TxRingBitmap.field.HccaDmaDone) + bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_HCCA); + + if (TxRingBitmap.field.Ac3DmaDone) + bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VO); + + if (TxRingBitmap.field.Ac2DmaDone) + bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VI); + + if (TxRingBitmap.field.Ac1DmaDone) + bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK); + + /* Make sure to release Tx ring resource*/ + /*NdisReleaseSpinLock(&pAd->TxRingLock);*/ + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + + /* 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( + IN PRTMP_ADAPTER pAd) +{ + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; +#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, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx); + while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx) + { + FREE++; +#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 +/* pTxD->DMADONE = 0; */ + pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].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 +#ifdef DOT11Z_TDLS_SUPPORT + UAPSD_QoSNullTxMgmtTxDoneHandle(pAd, + pPacket, + LMR_FRAME_GET()); +#else +#ifdef CONFIG_AP_SUPPORT +#ifdef P2P_SUPPORT + if (P2P_GO_ON(pAd)) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { + UAPSD_QoSNullTxMgmtTxDoneHandle(pAd, + pPacket, + LMR_FRAME_GET()); + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* DOT11Z_TDLS_SUPPORT */ +#endif /* UAPSD_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#endif /* CONFIG_AP_SUPPORT */ + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL; + + pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket; + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL; + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocPa, + RXD_SIZE); + + 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); + +} + + +/* + ======================================================================== + + Routine Description: + Arguments: + Adapter Pointer to our adapter. Dequeue all power safe delayed braodcast frames after beacon. + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID RTMPHandleTBTTInterrupt( + IN PRTMP_ADAPTER pAd) +{ +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + +#ifdef P2P_SUPPORT + if (P2P_INF_ON(pAd) && P2P_GO_ON(pAd)) +#else + if (pAd->OpMode == OPMODE_AP) +#endif /* P2P_SUPPORT */ + { + ReSyncBeaconTime(pAd); + +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pObj->tbtt_work); +#else + RTMP_OS_TASKLET_SCHE(&pObj->tbtt_task); +#endif /* WORKQUEUE_BH */ + + 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( + IN PRTMP_ADAPTER pAd) +{ +#ifdef CONFIG_AP_SUPPORT +#ifdef P2P_SUPPORT + if (P2P_INF_ON(pAd) && P2P_GO_ON(pAd)) +#else + if (pAd->OpMode == OPMODE_AP) +#endif /* P2P_SUPPORT */ + { + APUpdateAllBeaconFrame(pAd); + + RTMP_IO_WRITE32(pAd, MCU_INT_STATUS, 0x14); + 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; + + RTMP_IO_READ32(pAd, PBF_CFG, &macValue); + macValue &= (~0x0C); + RTMP_IO_WRITE32(pAd, PBF_CFG, macValue); + + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + + while (pAd->MacTab.McastPsQueue.Head) + { + bPS = TRUE; + if (pAd->TxSwQueue[QID_HCCA].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_HCCA], 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); + /* End of for */ + } + pAd->MacTab.PsQIdleCount = 0; + + // Dequeue outgoing framea from TxSwQueue0..3 queue and process it + if (bPS == TRUE) + { + RTMPDeQueuePacket(pAd, FALSE, QID_HCCA, /*MAX_TX_IN_TBTT*/MAX_PACKETS_IN_MCAST_PS_QUEUE); + pAd->MacTab.fMcastPsQEnable = TRUE; + } + } + } + else +#endif /* CONFIG_AP_SUPPORT */ + { + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPHandlePreTBTTInterrupt...\n")); + } + } + +#ifdef MESH_SUPPORT + MeshUpdateBeaconFrame(pAd, MESH_BEACON_IDX(pAd)); +#endif /* MESH_SUPPORT */ + +} + +VOID RTMPHandleRxCoherentInterrupt( + IN PRTMP_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); + + DBGPRINT_TX_RING(pAd, QID_AC_BE); + DBGPRINT_TX_RING(pAd, QID_AC_BK); + DBGPRINT_TX_RING(pAd, QID_AC_VI); + DBGPRINT_TX_RING(pAd, QID_AC_VO); + DBGPRINT_TX_RING(pAd, QID_MGMT); + + 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( + IN PRTMP_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 PRTMP_ADAPTER pAd, + OUT PRT28XX_RXD_STRUC pSaveRxD, + OUT BOOLEAN *pbReschedule, + IN OUT UINT32 *pRxPending) +{ + PRXD_STRUC pRxD; +#ifdef RT_BIG_ENDIAN + PRXD_STRUC pDestRxD; + RXD_STRUC RxD; +#endif + PNDIS_PACKET pRxPacket = NULL; + PNDIS_PACKET pNewPacket; + PVOID AllocVa; + NDIS_PHYSICAL_ADDRESS AllocPa; + BOOLEAN bReschedule = FALSE; + RTMP_DMACB *pRxCell; + + RTMP_SEM_LOCK(&pAd->RxRingLock); + + if (*pRxPending == 0) + { + /* Get how may packets had been received*/ + RTMP_IO_READ32(pAd, RX_DRX_IDX , &pAd->RxRing.RxDmaIdx); + + if (pAd->RxRing.RxSwReadIdx == pAd->RxRing.RxDmaIdx) + { + /* no more rx packets*/ + bReschedule = FALSE; + goto done; + } + + /* get rx pending count*/ + if (pAd->RxRing.RxDmaIdx > pAd->RxRing.RxSwReadIdx) + *pRxPending = pAd->RxRing.RxDmaIdx - pAd->RxRing.RxSwReadIdx; + else + *pRxPending = pAd->RxRing.RxDmaIdx + RX_RING_SIZE - pAd->RxRing.RxSwReadIdx; + +#ifdef DESC_32B_SUPPORT + pRxCell = &pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx]; + dma_cache_sync(NULL, pRxCell->AllocVa, RXD_SIZE, DMA_FROM_DEVICE); +#endif /* DESC_32B_SUPPORT */ + } + + pRxCell = &pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx]; + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pRxCell->AllocPa, RXD_SIZE); + +#ifdef RT_BIG_ENDIAN + pDestRxD = (PRXD_STRUC) pRxCell->AllocVa; + RxD = *pDestRxD; + pRxD = &RxD; + 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; + /* DMAIndx had done but DDONE bit not ready*/ + bReschedule = TRUE; + goto done; + } + +#ifdef DESC_32B_SUPPORT + prefetch(&pAd->RxRing.Cell[(pAd->RxRing.RxSwReadIdx + 1) % RX_RING_SIZE].AllocVa); +#endif /* DESC_32B_SUPPORT */ + + /* return rx descriptor*/ + NdisMoveMemory(pSaveRxD, pRxD, RXD_SIZE); + + pNewPacket = RTMP_AllocateRxPacketBuffer(pAd, ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, RX_BUFFER_AGGRESIZE, FALSE, &AllocVa, &AllocPa); + + 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; + + 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 */ + pRxD->SDP0 = AllocPa; + +#ifdef RX_DMA_SCATTER + pRxD->SDL0 = RX_BUFFER_AGGRESIZE; +#endif /* RX_DMA_SCATTER */ + } + else + { + /*DBGPRINT(RT_DEBUG_TRACE,("No Rx Buffer\n"));*/ + pRxPacket = NULL; + bReschedule = TRUE; + } + + /* had handled one rx packet*/ + *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 + +#ifdef DESC_32B_SUPPORT + dma_cache_sync(NULL, pRxCell->AllocVa, RXD_SIZE, DMA_TO_DEVICE); +#endif /* DESC_32B_SUPPORT */ + + INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE); + + pAd->RxRing.RxCpuIdx = (pAd->RxRing.RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxSwReadIdx-1); + RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.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 (pAd->RxRing.RxSwReadIdx & 0x01) + { + RTMP_DMACB *pRxCellLast; +#ifdef RT_BIG_ENDIAN + PRXD_STRUC pDestRxDLast; +#endif + /* 16B-align */ + + /* update last BD 32B-align, DMA Done bit = 0 */ + pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].LastBDInfo.DDONE = 0; +#ifdef RT_BIG_ENDIAN + pRxCellLast = &pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx - 1]; + pDestRxDLast = (PRXD_STRUC) pRxCellLast->AllocVa; + RTMPDescriptorEndianChange((PUCHAR)&pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].LastBDInfo, TYPE_RXD); + WriteBackToDescriptor((PUCHAR)pDestRxDLast, (PUCHAR)&pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].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(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE); + pAd->RxRing.RxCpuIdx = (pAd->RxRing.RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxSwReadIdx-1); + RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); + } + else + { + /* 32B-align */ + /* do not set DDONE bit and backup it */ + if (pAd->RxRing.RxSwReadIdx >= (RX_RING_SIZE-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(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE); + pAd->RxRing.RxCpuIdx = (pAd->RxRing.RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxSwReadIdx-1); + RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); + } + else + { + /* backup current BD */ + pRxCell = &pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx + 1]; + pRxCell->LastBDInfo = *pRxD; + + /* update CPU index */ + INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE); + } + } +#endif /* CACHE_LINE_32B */ + +done: + RTMP_SEM_UNLOCK(&pAd->RxRingLock); + *pbReschedule = bReschedule; + return pRxPacket; +} + + +NDIS_STATUS MlmeHardTransmitTxRing( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket) +{ + PACKET_INFO PacketInfo; + PUCHAR pSrcBufVA; + UINT SrcBufLen; + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; +#endif + PHEADER_802_11 pHeader_802_11; + BOOLEAN bAckRequired, bInsertTimestamp; + ULONG SrcBufPA; + /*UCHAR TxBufIdx;*/ + UCHAR MlmeRate; + ULONG SwIdx = pAd->TxRing[QueIdx].TxCpuIdx; + PTXWI_STRUC pFirstTxWI; + /*ULONG i;*/ + /*HTTRANSMIT_SETTING MlmeTransmit; Rate for this MGMT frame.*/ + ULONG FreeNum; + MAC_TABLE_ENTRY *pMacEntry = NULL; + 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); + + + if (pSrcBufVA == NULL) + { + /* The buffer shouldn't be NULL*/ + return NDIS_STATUS_FAILURE; + } + + /* Make sure MGMT ring resource won't be used by other threads*/ + /*NdisAcquireSpinLock(&pAd->TxRingLock);*/ + + FreeNum = GET_TXRING_FREENO(pAd, QueIdx); + + if (FreeNum == 0) + { + /*NdisReleaseSpinLock(&pAd->TxRingLock);*/ + return NDIS_STATUS_FAILURE; + } + + SwIdx = pAd->TxRing[QueIdx].TxCpuIdx; + +#ifdef RT_BIG_ENDIAN + pDestTxD = (PTXD_STRUC)pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa; +#endif + + if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket) + { + DBGPRINT(RT_DEBUG_OFF, ("MlmeHardTransmit Error\n")); + /*NdisReleaseSpinLock(&pAd->TxRingLock);*/ + 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 =(PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE); + pHeader_802_11 = (PHEADER_802_11)(pSrcBufVA + TXINFO_SIZE + TXWISize); + if (pHeader_802_11->Addr1[0] & 0x01) + { + MlmeRate = pAd->CommonCfg.BasicMlmeRate; + } + else + { + MlmeRate = pAd->CommonCfg.MlmeRate; + } + + if ((pHeader_802_11->FC.Type == BTYPE_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 != BTYPE_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 == BTYPE_CNTL) /* must be PS-POLL*/ + { + bAckRequired = FALSE; + } + else /* BTYPE_MGMT or BTYPE_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; + + for (apidx=0; apidxApCfg.BssidNum; apidx++) + { + if (RTMPEqualMemory(pHeader_802_11->Addr2, pAd->ApCfg.MBSSID[apidx].Bssid, MAC_ADDR_LEN)) + break; + } + + 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")); + /*NdisReleaseSpinLock(&pAd->TxRingLock);*/ + 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) + { + RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, + 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWISize), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); + +#ifdef SPECIFIC_TX_POWER_SUPPORT + if (IS_RT6352(pAd)) + pFirstTxWI->TxPwrAdj = TxPwrAdj; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + } + else + { + RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, + bInsertTimestamp, FALSE, bAckRequired, FALSE, + 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWISize), + pMacEntry->MaxHTPhyMode.field.MCS, 0, + (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS, + IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode); + } + + pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket; + pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL; +/* pFirstTxWI->MPDUtotalByteCount = SrcBufLen - TXWI_SIZE;*/ +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, (PUCHAR)pFirstTxWI, TYPE_TXWI); +#endif + SrcBufPA = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, RTMP_PCI_DMA_TODEVICE); + + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 0; + pTxD->SDLen1 = 0; + pTxD->SDPtr0 = SrcBufPA; + pTxD->SDLen0 = SrcBufLen; + RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_EDCA); + +#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, RXD_SIZE); + + /* Increase TX_CTX_IDX, but write to register later.*/ + INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE); + + RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx*0x10, pAd->TxRing[QueIdx].TxCpuIdx); + + /* Make sure to release MGMT ring resource*/ +/* NdisReleaseSpinLock(&pAd->TxRingLock);*/ + + return NDIS_STATUS_SUCCESS; +} + + + + +/* + ======================================================================== + + 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 RTMPWriteTxDescriptor( + IN PRTMP_ADAPTER pAd, + IN PTXD_STRUC pTxD, + 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); + + pTxD->WIV = (bWIV) ? 1: 0; + pTxD->QSEL= (QueueSEL); + /*RT2860c?? fixed using EDCA queue for test... We doubt Queue1 has problem. 2006-09-26 Jan*/ + /*pTxD->QSEL= FIFO_EDCA;*/ + if (pAd->bGenOneHCCA == TRUE) + pTxD->QSEL= FIFO_HCCA; + pTxD->DMADONE = 0; +} diff --git a/mt7620/src/common/cmm_dfs.c b/mt7620/src/common/cmm_dfs.c new file mode 100644 index 0000000..a681752 --- /dev/null +++ b/mt7620/src/common/cmm_dfs.c @@ -0,0 +1,3243 @@ +/* + *************************************************************************** + * 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_DEBUG +NewDFSDebugResult TestResult[1000]; +#endif + +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*/ + NEW_DFS_FCC, + { + {0, 0, 10, 8, 16, 6, 2000, 5, 2900, 29000, 5, 0, 0}, + {1, 0, 70, 42, 126, 20, 5000, 5, 2900, 29000, 10, 0, 0}, + {2, 0, 100, 42, 160, 20, 5000, 25, 2900, 10100, 20, 0, 0}, + {3, 2, 200, 20, 150, 900, 2200, 50, 1000, 999999999, 200, 0, 999999999}, + } + }, + + { + NEW_DFS_EU, + { + {0, 0, 10, 10, 18, 4, 4095, 5, 7800, 101000, 5, 0, 0}, + {1, 0, 70, 42, 90, 20, 4095, 3, 4900, 101000, 10, 0, 0}, + {2, 0, 100, 42, 160, 20, 4095, 5, 4900, 101000, 20, 0, 0}, + {3, 3, 200, 20, 150, 200, 4095, 100, 4900, 11000, 200, 0, 0}, + {4, 8, 0, 8, 17, 7, 70, 2, 32500, 200500, 10, 0, 0}, + /*{5, 1, 0, 12, 16, 8, 700, 5, 33000, 135000, 100, 0, 0},*/ + } + }, + + { + NEW_DFS_JAP, + { + {0, 0, 10, 8, 16, 4, 2000, 5, 2900, 85000, 5, 0, 0}, + {1, 0, 70, 48, 126, 20, 5000, 5, 2900, 85000, 10, 0, 0}, + {2, 0, 100, 48, 160, 20, 5000, 25, 2900, 85000, 20, 0, 0}, + {3, 2, 200, 20, 150, 900, 2200, 50, 1000, 999999999, 200, 0, 999999999}, + } + }, + + { + NEW_DFS_JAP_W53, + { + {0, 0, 10, 8, 16, 8, 2000, 5, 28000, 85000, 10}, + {1, 0, 32, 24, 64, 20, 2000, 5, 28000, 85000, 10}, + {2, 0, 100, 42, 160, 20, 2000, 25, 28000, 85000, 10}, + /*{3, 2, 200, 20, 150, 300, 2000, 50, 15000, 45000, 200},*/ + } + }, +}; + +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); + +static BOOLEAN DfsEventDataFetch( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + OUT PDFS_EVENT pDfsEvent); + +static VOID DfsCheckBusyIdle( + IN PRTMP_ADAPTER pAd); + +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); +} + +#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; + + 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_DONT_SWITCH) + printk("Dont Switch Channel\n"); + + if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_SILENCE) + printk("Silence\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_SW_SILENCE) + printk("SW detection Silence\n"); + return TRUE; +} + +INT Set_ResetRadarHwDetect_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR channel = 0; + /*Set BBP_R140=0x02 and Read BBP_R141 to store at channel */ + RTMP_DFS_IO_READ8(pAd, 0x2, &channel); + /* reset the radar channel for new counting */ + RTMP_DFS_IO_WRITE8(pAd, 0x2, channel); + printk("==>reset the radar channel for new counting channel =0x%x\n",channel); + return TRUE; +} + + +INT Set_DfsLowerLimit_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + + pRadarDetect->DfsLowerLimit = simple_strtol(arg, 0, 10); + return TRUE; +} + +INT Set_DfsUpperLimit_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + + pRadarDetect->DfsUpperLimit = simple_strtol(arg, 0, 10); + 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; +} + + +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); + NewRadarDetectionStart(pAd); + } + 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_Fcc5Thrd_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam; + pDfsSwParam->fcc_5_threshold = simple_strtol(arg, 0, 10); + return TRUE; +} + +INT Set_ChBusyThrd_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int i; + PUCHAR p1 = arg, p2; + ULONG value; + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + + pRadarDetect->fdf_num = 0; + for (i = 0; i < MAX_FDF_NUMBER; i++) + { + p2 = p1; + while((*p2 != ':') && (*p2 != '\0')) + { + p2++; + } + + if (*p2 == ':') + { + if (*p1 == '-') + { + p1++; + A2Dec(value, p1); + value *= -1; + } + else + A2Dec(value, p1); + + pRadarDetect->ch_busy_threshold[i] = value; + printk("pRadarDetect->ch_busy_threshold[%d] = %d\n", i, pRadarDetect->ch_busy_threshold[i]); + pRadarDetect->fdf_num++; + p1 = p2 + 1; + } + else + { + pRadarDetect->ch_busy_threshold[i] = simple_strtol(p1, 0, 10); + printk("pRadarDetect->ch_busy_threshold[%d] = %d\n", i, pRadarDetect->ch_busy_threshold[i]); + pRadarDetect->fdf_num++; + break; + } + } + printk("pRadarDetect->fdf_num = %d\n", pRadarDetect->fdf_num); + + return TRUE; +} + + +INT Set_RssiThrd_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int i; + PUCHAR p1 = arg, p2; + ULONG value; + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + + pRadarDetect->fdf_num = 0; + for (i = 0; i < MAX_FDF_NUMBER; i++) + { + p2 = p1; + while((*p2 != ':') && (*p2 != '\0')) + { + p2++; + } + + if (*p2 == ':') + { + if (*p1 == '-') + { + p1++; + A2Dec(value, p1); + value *= -1; + } + else + A2Dec(value, p1); + + pRadarDetect->rssi_threshold[i] = value; + printk("pRadarDetect->rssi_threshold[%d] = %d\n", i, pRadarDetect->rssi_threshold[i]); + pRadarDetect->fdf_num++; + p1 = p2 + 1; + } + else + { + pRadarDetect->rssi_threshold[i] = simple_strtol(p1, 0, 10); + printk("pRadarDetect->rssi_threshold[%d] = %d\n", i, pRadarDetect->rssi_threshold[i]); + pRadarDetect->fdf_num++; + break; + } + } + printk("pRadarDetect->fdf_num = %d\n", pRadarDetect->fdf_num); + + return TRUE; + pRadarDetect->rssi_threshold[0] = simple_strtol(arg, 0, 10); + + 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_Ch0LErr_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam; + pDfsSwParam->dfs_width_ch0_err_L = simple_strtol(arg, 0, 10); + return TRUE; +} + +INT Set_DeclareThres_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam; + pDfsSwParam->dfs_declare_thres = simple_strtol(arg, 0, 10); + return TRUE; +} + +INT Set_CheckLoop_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam; + pDfsSwParam->dfs_check_loop = simple_strtol(arg, 0, 10); + return TRUE; +} + +INT Set_MaxPeriod_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam; + pDfsSwParam->dfs_max_period = simple_strtol(arg, 0, 10); + return TRUE; +} + +INT Set_PeriodErr_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam; + pDfsSwParam->dfs_period_err = simple_strtol(arg, 0, 10); + return TRUE; +} + +INT Set_Ch0HErr_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam; + pDfsSwParam->dfs_width_ch0_err_H = simple_strtol(arg, 0, 10); + return TRUE; +} + +INT Set_Ch1Shift_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam; + pDfsSwParam->dfs_width_diff_ch1_Shift = simple_strtol(arg, 0, 10); + return TRUE; +} + +INT Set_Ch2Shift_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam; + pDfsSwParam->dfs_width_diff_ch2_Shift = simple_strtol(arg, 0, 10); + return TRUE; +} + + +#ifdef DFS_DEBUG +INT Set_CEPrintDebug_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int i; + PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam; + + if (simple_strtol(arg, 0, 10) == 0) + { + pDfsSwParam->DebugPortPrint = 1; + } + + if (simple_strtol(arg, 0, 10) == 1) + { + if (pDfsSwParam->DebugPortPrint == 3) + { + for (i = 0; i < 384; i++) + { + printk("%02x ", pDfsSwParam->DebugPort[i]); + if (((i+1) % 18) == 0) + printk("\n"); + } + pDfsSwParam->DebugPortPrint = 0; + } + } + return TRUE; +} +#endif /* DFS_DEBUG */ + + +INT Set_RadarSim_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam; +int i=0, id=0; +int dfs_data[] = { 208, 142172, + 160, 260514, + 208, 363873, + 160, 482216, + 208, 585575, + 164, 703918, + 208, 807277, + 160, 925620, + 208, 1028979, + 164, 1147321}; + + pDfsSwParam->dfs_w_counter++; + for (i = 0; i < 10; i++) + { + pDfsSwParam->DFS_W[id][pDfsSwParam->dfs_w_idx[id]].counter = pDfsSwParam->dfs_w_counter; + pDfsSwParam->DFS_W[id][pDfsSwParam->dfs_w_idx[id]].timestamp = dfs_data[2*i+1]; + pDfsSwParam->DFS_W[id][pDfsSwParam->dfs_w_idx[id]].width = dfs_data[2*i]; + 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; + } + pDfsSwParam->hw_idx[0] = pDfsSwParam->dfs_w_idx[0]; + SWRadarCheck(pAd, 0); + 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 Set_Ch0EventExpire_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PDFS_PROGRAM_PARAM pDfsProgramParam = &pAd->CommonCfg.RadarDetect.DfsProgramParam; + + ULONG a = 0; + PSTRING p; + + if ((arg[0] == '0') && (arg[1] == 'x')) + { + p = &arg[2]; + } + else + p = &arg[0]; + + while (*p != '\0') + { + a = a * 0x10; + if (*p >= 0x30 && *p <= 0x39) + a += (ULONG)(*p - 0x30); + else if (*p >= 0x41 && *p <= 0x46) + a += (ULONG)(*p - 0x37); + else if (*p >= 0x61 && *p <= 0x66) + a += (ULONG)(*p - 0x57); + else + { + printk("invalid hex value\n"); + return FALSE; + } + p++; + } + pDfsProgramParam->RadarEventExpire[0] = a; + + RTMP_DFS_IO_WRITE8(pAd, 0x0, 0); + RTMP_DFS_IO_WRITE8(pAd,0x39, (a & 0xff)); + RTMP_DFS_IO_WRITE8(pAd,0x3a, ((a >> 8) & 0xff) ); + RTMP_DFS_IO_WRITE8(pAd,0x3b, ((a >> 16) & 0xff)); + RTMP_DFS_IO_WRITE8(pAd,0x3c, ((a >> 24) & 0xff)); + + + return TRUE; +} + +INT Set_Ch1EventExpire_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PDFS_PROGRAM_PARAM pDfsProgramParam = &pAd->CommonCfg.RadarDetect.DfsProgramParam; + + ULONG a = 0; + PSTRING p; + + if ((arg[0] == '0') && (arg[1] == 'x')) + { + p = &arg[2]; + } + else + p = &arg[0]; + + while (*p != '\0') + { + a = a * 0x10; + if (*p >= 0x30 && *p <= 0x39) + a += (ULONG)(*p - 0x30); + else if (*p >= 0x41 && *p <= 0x46) + a += (ULONG)(*p - 0x37); + else if (*p >= 0x61 && *p <= 0x66) + a += (ULONG)(*p - 0x57); + else + { + printk("invalid hex value\n"); + return FALSE; + } + p++; + } + pDfsProgramParam->RadarEventExpire[1] = a; + + RTMP_DFS_IO_WRITE8(pAd, 0x0, 1); + RTMP_DFS_IO_WRITE8(pAd,0x39, (a & 0xff)); + RTMP_DFS_IO_WRITE8(pAd,0x3a, ((a >> 8) & 0xff) ); + RTMP_DFS_IO_WRITE8(pAd,0x3b, ((a >> 16) & 0xff)); + RTMP_DFS_IO_WRITE8(pAd,0x3c, ((a >> 24) & 0xff)); + + return TRUE; +} + +INT Set_Ch2EventExpire_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PDFS_PROGRAM_PARAM pDfsProgramParam = &pAd->CommonCfg.RadarDetect.DfsProgramParam; + + ULONG a = 0; + PSTRING p; + + if ((arg[0] == '0') && (arg[1] == 'x')) + { + p = &arg[2]; + } + else + p = &arg[0]; + + while (*p != '\0') + { + a = a * 0x10; + if (*p >= 0x30 && *p <= 0x39) + a += (ULONG)(*p - 0x30); + else if (*p >= 0x41 && *p <= 0x46) + a += (ULONG)(*p - 0x37); + else if (*p >= 0x61 && *p <= 0x66) + a += (ULONG)(*p - 0x57); + else + { + printk("invalid hex value\n"); + return FALSE; + } + p++; + } + pDfsProgramParam->RadarEventExpire[2] = a; + + RTMP_DFS_IO_WRITE8(pAd, 0x0, 2); + RTMP_DFS_IO_WRITE8(pAd,0x39, (a & 0xff)); + RTMP_DFS_IO_WRITE8(pAd,0x3a, ((a >> 8) & 0xff) ); + RTMP_DFS_IO_WRITE8(pAd,0x3b, ((a >> 16) & 0xff)); + RTMP_DFS_IO_WRITE8(pAd,0x3c, ((a >> 24) & 0xff)); + + + return TRUE; +} + +INT Set_Ch3EventExpire_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PDFS_PROGRAM_PARAM pDfsProgramParam = &pAd->CommonCfg.RadarDetect.DfsProgramParam; + + ULONG a = 0; + PSTRING p; + + if ((arg[0] == '0') && (arg[1] == 'x')) + { + p = &arg[2]; + } + else + p = &arg[0]; + + while (*p != '\0') + { + a = a * 0x10; + if (*p >= 0x30 && *p <= 0x39) + a += (ULONG)(*p - 0x30); + else if (*p >= 0x41 && *p <= 0x46) + a += (ULONG)(*p - 0x37); + else if (*p >= 0x61 && *p <= 0x66) + a += (ULONG)(*p - 0x57); + else + { + printk("invalid hex value\n"); + return FALSE; + } + p++; + } + pDfsProgramParam->RadarEventExpire[3] = a; + + RTMP_DFS_IO_WRITE8(pAd, 0x0, 3); + RTMP_DFS_IO_WRITE8(pAd,0x39, (a & 0xff)); + RTMP_DFS_IO_WRITE8(pAd,0x3a, ((a >> 8) & 0xff) ); + RTMP_DFS_IO_WRITE8(pAd,0x3b, ((a >> 16) & 0xff)); + RTMP_DFS_IO_WRITE8(pAd,0x3c, ((a >> 24) & 0xff)); + + + return TRUE; +} + +INT Set_CEPrint_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam; + int i, j, id = simple_strtol(arg, 0, 10); + int n = pDfsSwParam->dfs_w_last_idx[id]; + + if ((id >= 0) && (id <= 3)) + { + printk("Last Idx = %d\n", n); + for (i = 0; i < NEW_DFS_DBG_PORT_ENT_NUM; i++) + { + printk("Cnt=%u, w= %u Time=%u\n", (unsigned int)(pDfsSwParam->DFS_W[id][i].counter), + pDfsSwParam->DFS_W[id][i].width, + (unsigned int)pDfsSwParam->DFS_W[id][i].timestamp); + if (pDfsSwParam->DFS_W[id][i].counter == 0) + break; + } + } + + if ((id >= 10) && (id < 13)) + { + id -= 10; + for (i = 0; i < NEW_DFS_MPERIOD_ENT_NUM; i++) + { + printk("T=%u, w1= %u(%u), w2= %u(%u)\n", (unsigned int)(pDfsSwParam->DFS_T[id][i].period), + pDfsSwParam->DFS_T[id][i].width, pDfsSwParam->DFS_T[id][i].idx, + pDfsSwParam->DFS_T[id][i].width2, pDfsSwParam->DFS_T[id][i].idx2); + if (pDfsSwParam->DFS_T[id][i].period == 0) + break; + } + + } + if (id == 77) + { + for (i = 0; i < 4; i++) + { + for (j = 0; j < NEW_DFS_DBG_PORT_ENT_NUM; j++) + { + pDfsSwParam->DFS_W[i][j].counter = 0; + pDfsSwParam->DFS_W[i][j].width = 0; + pDfsSwParam->DFS_W[i][j].timestamp = 0; + } + for (j = 0; j < NEW_DFS_MPERIOD_ENT_NUM; j++) + { + pDfsSwParam->DFS_T[i][j].period = 0; + pDfsSwParam->DFS_T[i][j].width = 0; + pDfsSwParam->DFS_T[i][j].width2 = 0; + pDfsSwParam->DFS_T[i][j].idx = 0; + pDfsSwParam->DFS_T[i][j].idx2 = 0; + } + } + } +#ifdef DFS_DEBUG + if (id > 20) + { + pDfsSwParam->BBP127Repeat = id - 20; + } + + if (id == 5) + { + + for (i = 0; i < NEW_DFS_DBG_PORT_ENT_NUM; i++) + { + printk("Cnt=%u, w= %u Time=%lu, start_idx = %u end_idx = %u\n", (unsigned int)(pDfsSwParam->CE_DebugCh0[i].counter), + (unsigned int)pDfsSwParam->CE_DebugCh0[i].width, pDfsSwParam->CE_DebugCh0[i].timestamp, + pDfsSwParam->CE_DebugCh0[i].start_idx, pDfsSwParam->CE_DebugCh0[i].end_idx); + } + + for (i = 0; i < NEW_DFS_MPERIOD_ENT_NUM; i++) + { + printk("T=%lu, w1= %u(%u), w2= %u(%u)\n", (pDfsSwParam->CE_TCh0[i].period), + pDfsSwParam->CE_TCh0[i].width, pDfsSwParam->CE_TCh0[i].idx, + pDfsSwParam->CE_TCh0[i].width2, pDfsSwParam->CE_TCh0[i].idx2); + } + + } +#endif /* DFS_DEBUG */ + + return TRUE; +} + + +INT Set_RfReg_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + + printk("1 %x\n", pAd->LatchRfRegs.R1); + printk("2 %x\n", pAd->LatchRfRegs.R2); + printk("3 %x\n", pAd->LatchRfRegs.R3); + printk("4 %x\n", pAd->LatchRfRegs.R4); + 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); + pRadarDetect->PollTime = 3; + pRadarDetect->DfsRssiHigh = -30; + pRadarDetect->DfsRssiLow = -90; + pRadarDetect->DFSWatchDogIsRunning=FALSE; + pRadarDetect->use_tasklet = 1; + pRadarDetect->McuRadarDebug = 0; + pRadarDetect->radarDeclared = 0; + pRadarDetect->dfs_func = HARDWARE_DFS_V2; + + if (pAd->chipCap.DfsEngineNum > 4) + pRadarDetect->bDfsSwDisable = TRUE; /* Default close s/w detection for new DFS*/ + + pDfsProgramParam->DeltaDelay = 0x3; + pDfsProgramParam->ChEnable = pRadarDetect->EnabledChMask; + pDfsProgramParam->RadarEventExpire[3] = 0x99999999; + pDfsProgramParam->Symmetric_Round = 1; + pDfsProgramParam->VGA_Mask = 45; + pDfsProgramParam->Packet_End_Mask = 45; + pDfsProgramParam->Rx_PE_Mask = 45; + /*pAd->CommonCfg.ce_sw_check = CE_SW_CHECK;*/ + /*pDfsSwParam->ce_sw_id_check = 0;*/ + /*pDfsSwParam->ce_sw_t_diff = 14;*/ + + /* from dfs_mcu.c, one time init */ + dfs_sw_init(pAd); + +} + +void NewRadarDetectionStart(PRTMP_ADAPTER pAd) +{ + pNewDFSTable pDFS2Table; + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + /*PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam;*/ + + 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; + + pDFS2Table = &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; + + pDFS2Table = &NewDFSTable1[1]; + DBGPRINT(RT_DEBUG_TRACE,("DFS start, use CE table\n")); + } + else /* JAP*/ + { + + if ((pAd->CommonCfg.Channel >= 52) && (pAd->CommonCfg.Channel <= 64)) + { + pDFS2Table = &NewDFSTable1[3]; + + if (pRadarDetect->ch_busy_idle_ratio == 0) + pRadarDetect->ch_busy_idle_ratio = 3; + } + else + { + pDFS2Table = &NewDFSTable1[2]; + /*pDfsProgramParam->Symmetric_Round = 1;*/ + + if (pRadarDetect->ch_busy_idle_ratio == 0) + pRadarDetect->ch_busy_idle_ratio = 2; + } + DBGPRINT(RT_DEBUG_TRACE,("DFS start, use JAP table\n")); + } + + NewRadarDetectionProgram(pAd, pDFS2Table); + + /*the usage of dfs_sw_init*/ + /*dfs_sw_init(pAd);*/ + +#ifdef RTMP_MAC_PCI + /* enable debug mode*/ + BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R126, 3); +#ifdef RTMP_RBUS_SUPPORT + request_tmr_service(NEW_DFS_WATCH_DOG_TIME, &NewTimerCB_Radar, pAd); +#else + if(pRadarDetect->DFSWatchDogIsRunning == FALSE) + { + RTMP_HW_TIMER_INT_SET(pAd, 1); /* 1ms Timer interrupt */ + RTMP_HW_TIMER_INT_ENABLE(pAd); + pRadarDetect->DFSWatchDogIsRunning = TRUE; + } +#endif /* RTMP_RBUS_SUPPORT */ +#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*/ + RTMP_DFS_IO_WRITE8(pAd, 0x1, 0); + + /* Clear Status */ + RTMP_DFS_IO_WRITE8(pAd, 0x2, pRadarDetect->EnabledChMask); + +#ifdef RTMP_MAC_PCI +#ifdef RTMP_RBUS_SUPPORT + unregister_tmr_service(); +#else + { + RTMP_HW_TIMER_INT_SET(pAd, 0); + RTMP_HW_TIMER_INT_DISABLE(pAd); + pRadarDetect->DFSWatchDogIsRunning=FALSE; + } +#endif /* RTMP_RBUS_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + +} + + +/* 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; + + 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]; + /*printk("start_idx = %d, end_idx=%d, counter=%d\n", start_idx, end_idx, pEnd->counter);*/ + + /*if (pDfsSwParam->dfs_w_counter != pEnd->counter)*/ + /* return 0;*/ + + 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)) + { +#ifdef DFS_DEBUG + if (PeriodMatched < 5) + { + pDfsSwParam->CounterStored[PeriodMatched] = pDfsSwParam->DFS_W[id][pDfsSwParam->DFS_T[id][idx1].idx].counter; + pDfsSwParam->CounterStored2[PeriodMatched] = loop; + pDfsSwParam->CounterStored3 = idx[1]; + } +#endif + /*printk("%d %d\n", loop, pDfsSwParam->DFS_T[id][idx[1]-loop].period);*/ + PeriodMatched++; + } + + } + + + if (PeriodMatched > pDfsSwParam->dfs_declare_thres) + { +#ifdef DFS_DEBUG + if (PeriodMatched == 3) + { + pDfsSwParam->T_Matched_3++; + /*printk("counter=%d %d %d\n", pDfsSwParam->CounterStored[0], pDfsSwParam->CounterStored[1], pDfsSwParam->CounterStored[2]);*/ + /*printk("idx[1]=%d, loop =%d %d %d\n", pDfsSwParam->CounterStored3, pDfsSwParam->CounterStored2[0], pDfsSwParam->CounterStored2[1], pDfsSwParam->CounterStored2[2]);*/ + } + else if (PeriodMatched == 4) + { + pDfsSwParam->T_Matched_4++; + /*printk("counter=%d %d %d %d\n", pDfsSwParam->CounterStored[0], pDfsSwParam->CounterStored[1], pDfsSwParam->CounterStored[2], pDfsSwParam->CounterStored[3]);*/ + /*printk("idx[1]=%d, loop =%d %d %d %d\n", pDfsSwParam->CounterStored3, pDfsSwParam->CounterStored2[0], pDfsSwParam->CounterStored2[1], pDfsSwParam->CounterStored2[2], pDfsSwParam->CounterStored2[3]);*/ + } + else + { + pDfsSwParam->T_Matched_5++; + /*printk("counter=%d %d %d %d %d\n", pDfsSwParam->CounterStored[0], pDfsSwParam->CounterStored[1], pDfsSwParam->CounterStored[2], pDfsSwParam->CounterStored[3], pDfsSwParam->CounterStored[4]);*/ + /*printk("idx[1]=%d, loop =%d %d %d %d %d\n", pDfsSwParam->CounterStored3, pDfsSwParam->CounterStored2[0], pDfsSwParam->CounterStored2[1], pDfsSwParam->CounterStored2[2], pDfsSwParam->CounterStored2[3], pDfsSwParam->CounterStored2[4]);*/ + } + + pDfsSwParam->DebugPortPrint = 1; + +#endif + + { + 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)); + + } + + + } +#ifdef DFS_DEBUG + else if (PeriodMatched == 2) + { + pDfsSwParam->T_Matched_2++; + } +#endif + + + } + + } /* 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)) + { +#ifdef DFS_DEBUG + if (PeriodMatched < 5) + { + pDfsSwParam->CounterStored[PeriodMatched] = pDfsSwParam->DFS_W[id][pDfsSwParam->DFS_T[id][idx1].idx].counter; + pDfsSwParam->CounterStored2[PeriodMatched] = loop; + pDfsSwParam->CounterStored3 = idx[1]; + } +#endif + /*printk("%d %d\n", loop, pDfsSwParam->DFS_T[id][idx[1]-loop].period);*/ + PeriodMatched++; + } + + } + + + if (PeriodMatched > pDfsSwParam->dfs_declare_thres) + { +#ifdef DFS_DEBUG + if (PeriodMatched == 3) + { + pDfsSwParam->T_Matched_3++; + /*printk("counter=%d %d %d\n", pDfsSwParam->CounterStored[0], pDfsSwParam->CounterStored[1], pDfsSwParam->CounterStored[2]);*/ + /*printk("idx[1]=%d, loop =%d %d %d\n", pDfsSwParam->CounterStored3, pDfsSwParam->CounterStored2[0], pDfsSwParam->CounterStored2[1], pDfsSwParam->CounterStored2[2]);*/ + } + else if (PeriodMatched == 4) + { + pDfsSwParam->T_Matched_4++; + /*printk("counter=%d %d %d %d\n", pDfsSwParam->CounterStored[0], pDfsSwParam->CounterStored[1], pDfsSwParam->CounterStored[2], pDfsSwParam->CounterStored[3]);*/ + /*printk("idx[1]=%d, loop =%d %d %d %d\n", pDfsSwParam->CounterStored3, pDfsSwParam->CounterStored2[0], pDfsSwParam->CounterStored2[1], pDfsSwParam->CounterStored2[2], pDfsSwParam->CounterStored2[3]);*/ + } + else + { + pDfsSwParam->T_Matched_5++; + /*printk("counter=%d %d %d %d %d\n", pDfsSwParam->CounterStored[0], pDfsSwParam->CounterStored[1], pDfsSwParam->CounterStored[2], pDfsSwParam->CounterStored[3], pDfsSwParam->CounterStored[4]);*/ + /*printk("idx[1]=%d, loop =%d %d %d %d %d\n", pDfsSwParam->CounterStored3, pDfsSwParam->CounterStored2[0], pDfsSwParam->CounterStored2[1], pDfsSwParam->CounterStored2[2], pDfsSwParam->CounterStored2[3], pDfsSwParam->CounterStored2[4]);*/ + } + + pDfsSwParam->DebugPortPrint = 1; +#endif + 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; + } +#ifdef DFS_DEBUG + else if (PeriodMatched == 2) + { + pDfsSwParam->T_Matched_2++; + /*printk("counter=%d %d\n", pDfsSwParam->CounterStored[0], pDfsSwParam->CounterStored[1]);*/ + /*printk("idx[1]=%d, loop =%d %d\n", pDfsSwParam->CounterStored3, pDfsSwParam->CounterStored2[0], pDfsSwParam->CounterStored2[1]);*/ + } +#endif + + + } + } + + } + + } /* 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, T_all=0, F1, F2, F3 = 0, Fmax = 0, freq_diff_min, freq_diff_max; + UINT8 bbp141=0, dfs_stg2=0, dfs_typ5=0; + UINT F_MAX, F_MID, F_MIN; + + DBGPRINT(RT_DEBUG_TRACE, ("--->StagerRadarCheck()\n")); + /* 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, &bbp141); + T_all += bbp141; + RTMP_DFS_IO_READ8(pAd, 0x2e, &bbp141); + T_all += bbp141<<8; + RTMP_DFS_IO_READ8(pAd, 0x2f, &bbp141); + T_all += bbp141<<16; + RTMP_DFS_IO_READ8(pAd, 0x30, &bbp141); + T_all += bbp141<<24; + + RTMP_DFS_IO_READ8(pAd, 0x33, &bbp141); + T1 += bbp141; + RTMP_DFS_IO_READ8(pAd, 0x34, &bbp141); + T1 += bbp141<<8; + RTMP_DFS_IO_READ8(pAd, 0x35, &bbp141); + T1 += bbp141<<16; + RTMP_DFS_IO_READ8(pAd, 0x36, &bbp141); + T1 += bbp141<<24; + + RTMP_DFS_IO_READ8(pAd, 0x3d, &bbp141); + T2 += bbp141; + RTMP_DFS_IO_READ8(pAd, 0x3e, &bbp141); + T2 += bbp141<<8; + RTMP_DFS_IO_READ8(pAd, 0x3f, &bbp141); + T2 += bbp141<<16; + RTMP_DFS_IO_READ8(pAd, 0x40, &bbp141); + T2 += bbp141<<24; + + T3 = T_all - T1 -T2; + + 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) + { + dfs_typ5 = 1; + 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 VOID DfsCheckBusyIdle( + IN PRTMP_ADAPTER pAd) +{ + int busy_delta, idle_delta; + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + + RTMP_IO_READ32(pAd, CH_IDLE_STA, &pRadarDetect->idle_time); + RTMP_IO_READ32(pAd, CH_BUSY_STA, &pRadarDetect->busy_time); + + /*ch_busy_sta_index begining at 0.*/ + busy_delta = pRadarDetect->busy_time - pRadarDetect->ch_busy_sta[pRadarDetect->ch_busy_sta_index]; + idle_delta = pRadarDetect->idle_time - pRadarDetect->ch_idle_sta[pRadarDetect->ch_busy_sta_index]; + + if (busy_delta < 0) + { + busy_delta = ~busy_delta; + busy_delta = (busy_delta >> CH_BUSY_SAMPLE_POWER); + busy_delta = ~busy_delta; + } + else + busy_delta = busy_delta >> CH_BUSY_SAMPLE_POWER; + + if (idle_delta < 0) + { + idle_delta = ~idle_delta; + idle_delta = idle_delta >> CH_BUSY_SAMPLE_POWER; + idle_delta = ~idle_delta; + } + else + idle_delta = idle_delta >> CH_BUSY_SAMPLE_POWER; + + pRadarDetect->ch_busy_sum += busy_delta; + pRadarDetect->ch_idle_sum += idle_delta; + + /* not sure if this is necessary??*/ + if (pRadarDetect->ch_busy_sum < 0) + pRadarDetect->ch_busy_sum = 0; + if (pRadarDetect->ch_idle_sum < 0) + pRadarDetect->ch_idle_sum = 0; + + pRadarDetect->ch_busy_sta[pRadarDetect->ch_busy_sta_index] = pRadarDetect->busy_time; + pRadarDetect->ch_idle_sta[pRadarDetect->ch_busy_sta_index] = pRadarDetect->idle_time; + + pRadarDetect->ch_busy_sta_index++; + pRadarDetect->ch_busy_sta_index &= CH_BUSY_MASK; + + if ((pRadarDetect->ch_idle_sum >> pRadarDetect->ch_busy_idle_ratio) < pRadarDetect->ch_busy_sum ) + { + + if (!(pRadarDetect->McuRadarDebug & RADAR_DEBUG_DONT_CHECK_BUSY)) + pRadarDetect->ch_busy = 1; + } + else + { + if (!(pRadarDetect->McuRadarDebug & RADAR_DEBUG_DONT_CHECK_RSSI)) + { + if ((pAd->ApCfg.RssiSample.AvgRssi0) && (pAd->ApCfg.RssiSample.AvgRssi0 > pRadarDetect->DfsRssiHigh)) + pRadarDetect->ch_busy = 2; + else if ((pAd->ApCfg.RssiSample.AvgRssi0) && (pAd->ApCfg.RssiSample.AvgRssi0 < pRadarDetect->DfsRssiLow)) + pRadarDetect->ch_busy = 3; + else + pRadarDetect->ch_busy = 0; + } + } + + if (pRadarDetect->print_ch_busy_sta) + DBGPRINT(RT_DEBUG_TRACE, + ("%d %d %d %d\n", pRadarDetect->ch_idle_sum, pRadarDetect->ch_busy_sum, pAd->ApCfg.RssiSample.AvgRssi0, pRadarDetect->ch_busy)); + +} + +static BOOLEAN DfsChannelCheck( + IN PRTMP_ADAPTER pAd, + IN UINT8 DfsChannel) +{ + pNewDFSTable pDFS2Table; + UINT8 i; + UINT32 W, T; + BOOLEAN radarDeclared = 0; + UCHAR BBP_1 = 0, BBP_2 = 0, BBP_3 = 0, BBP_4 = 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) + pDFS2Table = &NewDFSTable1[0]; + else if (pAd->CommonCfg.RDDurRegion == CE) + { + pDFS2Table = &NewDFSTable1[1]; + } + else /* Japan*/ + { + if ((pAd->CommonCfg.Channel >= 52) && (pAd->CommonCfg.Channel <= 64)) + { + pDFS2Table = &NewDFSTable1[3]; + } + else + { + pDFS2Table = &NewDFSTable1[2]; + } + } + /*check which channe(0~3) is detecting radar signals*/ + for (i = 0; i < pAd->chipCap.DfsEngineNum; i++) + { + + if (DfsChannel & (0x1 << i)) + { + /* select channel*/ + RTMP_DFS_IO_WRITE8(pAd, 0x0, i); + + /* Read reports - Period */ + RTMP_DFS_IO_READ8(pAd, 0x2d, &BBP_1); + RTMP_DFS_IO_READ8(pAd, 0x2e, &BBP_2); + RTMP_DFS_IO_READ8(pAd, 0x2f, &BBP_3); + RTMP_DFS_IO_READ8(pAd, 0x30, &BBP_4); + T = BBP_1 | (BBP_2 << 8) | (BBP_3 << 16) | (BBP_4 << 24); + + /* Read reports - Width */ + RTMP_DFS_IO_READ8(pAd, 0x31, &BBP_1); + RTMP_DFS_IO_READ8(pAd, 0x32, &BBP_2); + W = BBP_1 | ((BBP_2 & 0xf) << 8); + + if (DfsSwCheckOnHwDetection(pAd, pDFS2Table, i, T, W) == FALSE) + continue; + + printk("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)) && (pDFS2Table->entry[i].mode != 0) ) + { + ULONG B, W2; + + RTMP_DFS_IO_READ8(pAd, 0x33, &BBP_1); + RTMP_DFS_IO_READ8(pAd, 0x34, &BBP_2); + RTMP_DFS_IO_READ8(pAd, 0x35, &BBP_3); + RTMP_DFS_IO_READ8(pAd, 0x36, &BBP_4); + B = BBP_1 | (BBP_2 << 8) | (BBP_3 << 16) | (BBP_4 << 24); + DBGPRINT(RT_DEBUG_TRACE, ("Burst = %lu(0x%lx)\n", B, B)); + + RTMP_DFS_IO_READ8(pAd, 0x37, &BBP_1); + RTMP_DFS_IO_READ8(pAd, 0x38, &BBP_2); + W2 = BBP_1 | (BBP_2 << 8); + DBGPRINT(RT_DEBUG_TRACE, ("The second Width = %lu(0x%lx)\n", W2, W2)); + } + + } + } + return radarDeclared; +} + +static BOOLEAN DfsEventDataFetch( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + OUT PDFS_EVENT pDfsEvent) +{ + pDfsEvent->EngineId = pData[0]; + if (pDfsEvent->EngineId == 0xff) /* end of event */ + return FALSE; + + pDfsEvent->TimeStamp = pData[1]; + pDfsEvent->TimeStamp |= (pData[2] << 8); + pDfsEvent->TimeStamp |= (pData[3] << 16); + + pDfsEvent->Width = pData[4]; + pDfsEvent->Width |= (pData[5] << 8); + + /* Check if event is valid */ + if (!DFS_EVENT_SANITY_CHECK(pAd, *pDfsEvent)) + return FALSE; + + return TRUE; +} + +VOID NewRadarDetectionProgram(PRTMP_ADAPTER pAd, pNewDFSTable pDFS2Table) +{ + UINT8 idx, TalbeIdx, DFSR3; + 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) + { + pDFS2Table->entry[idx].mode = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].mode; + pDFS2Table->entry[idx].avgLen = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].avgLen; + pDFS2Table->entry[idx].ELow = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].ELow; + pDFS2Table->entry[idx].EHigh = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].EHigh; + pDFS2Table->entry[idx].WLow = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].WLow; + pDFS2Table->entry[idx].WHigh = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].WHigh; + pDFS2Table->entry[idx].EpsilonW = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].EpsilonW; + pDFS2Table->entry[idx].TLow = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].TLow; + pDFS2Table->entry[idx].THigh = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].THigh; + pDFS2Table->entry[idx].EpsilonT = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].EpsilonT; + pDFS2Table->entry[idx].BLow = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].BLow; + pDFS2Table->entry[idx].BHigh = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].BHigh; + + DBGPRINT(RT_DEBUG_TRACE, ("TalbeIdx = %d; idx = %d; DFSParam = %2d; %3d; %3d; %3d; %3d; %4d; %3d; %6lu; %7lu; %4d; %2lu; %2lu\n", TalbeIdx, idx, + pDFS2Table->entry[idx].mode, pDFS2Table->entry[idx].avgLen, pDFS2Table->entry[idx].ELow, + pDFS2Table->entry[idx].EHigh, pDFS2Table->entry[idx].WLow, pDFS2Table->entry[idx].WHigh, + pDFS2Table->entry[idx].EpsilonW, pDFS2Table->entry[idx].TLow, pDFS2Table->entry[idx].THigh, + pDFS2Table->entry[idx].EpsilonT, pDFS2Table->entry[idx].BLow, pDFS2Table->entry[idx].BHigh)); + } + } + + /* 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 = pDFS2Table->type; + + DFSR3 = pDfsProgramParam->Symmetric_Round << 4; + /* Full 40Mhz*/ + if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) + { + /* BW 40*/ + DFSR3 |= 0x80; + } + + /* Delta Delay*/ + DFSR3 |= (pDfsProgramParam->DeltaDelay & 0xf); + RTMP_DFS_IO_WRITE8(pAd, 0x3, DFSR3); + DBGPRINT(RT_DEBUG_TRACE,("R3 = 0x%x\n", DFSR3)); + + /* 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, (pDFS2Table->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, ((pDFS2Table->entry[idx].avgLen << 4) & 0x30)); + } + else + { + RTMP_DFS_IO_WRITE8(pAd, 0x11, (pDFS2Table->entry[idx].avgLen & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x12, ((pDFS2Table->entry[idx].avgLen >> 8) & 0x1)); + } + + /* reg 0x13~0x14, Energy Low[7:0] & Energy Low[11:8]*/ + RTMP_DFS_IO_WRITE8(pAd, 0x13, (pDFS2Table->entry[idx].ELow & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x14, ((pDFS2Table->entry[idx].ELow >> 8) & 0xf)); + + + /* reg 0x15~0x16, Energy High[7:0] & Energy High[11:8]*/ + RTMP_DFS_IO_WRITE8(pAd, 0x15, (pDFS2Table->entry[idx].EHigh & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x16, ((pDFS2Table->entry[idx].EHigh >> 8) & 0xf)); + + + /* reg 0x28~0x29, Width Low[7:0] & Width Low[11:8]*/ + RTMP_DFS_IO_WRITE8(pAd, 0x28, (pDFS2Table->entry[idx].WLow & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x29, ((pDFS2Table->entry[idx].WLow >> 8) & 0xf)); + + /* reg 0x2a~0x2b, Width High[7:0] & Width High[11:8]*/ + RTMP_DFS_IO_WRITE8(pAd, 0x2a, (pDFS2Table->entry[idx].WHigh & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x2b, ((pDFS2Table->entry[idx].WHigh >> 8) & 0xf)); + + /* reg 0x2c, Width Delta[7:0], (Width Measurement Uncertainty)*/ + RTMP_DFS_IO_WRITE8(pAd, 0x2c, (pDFS2Table->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, (pDFS2Table->entry[idx].TLow & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x18, ((pDFS2Table->entry[idx].TLow >> 8) & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x19, ((pDFS2Table->entry[idx].TLow >> 16) & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x1a, ((pDFS2Table->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, (pDFS2Table->entry[idx].THigh & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x1c, ((pDFS2Table->entry[idx].THigh >> 8) & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x1d, ((pDFS2Table->entry[idx].THigh >> 16) & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x1e, ((pDFS2Table->entry[idx].THigh >> 24) & 0xff)); + + /* reg 0x27, Period Delt[7:0], (Period Measurement Uncertainty)*/ + RTMP_DFS_IO_WRITE8(pAd, 0x27, (pDFS2Table->entry[idx].EpsilonT & 0xff)); + + if (pDfsProgramParam->RadarEventExpire[idx] != 0) + { + RTMP_DFS_IO_WRITE8(pAd,0x39, (pDfsProgramParam->RadarEventExpire[idx] & 0xff)); + RTMP_DFS_IO_WRITE8(pAd,0x3a, ((pDfsProgramParam->RadarEventExpire[idx] >> 8) & 0xff) ); + RTMP_DFS_IO_WRITE8(pAd,0x3b, ((pDfsProgramParam->RadarEventExpire[idx] >> 16) & 0xff)); + RTMP_DFS_IO_WRITE8(pAd,0x3c, ((pDfsProgramParam->RadarEventExpire[idx] >> 24) & 0xff)); + } + + } + + /* reset status */ + RTMP_DFS_IO_WRITE8(pAd, 0x2, pRadarDetect->EnabledChMask); + /* Enable detection*/ + RTMP_DFS_IO_WRITE8(pAd, 0x1, (pDfsProgramParam->ChEnable)); + + pRadarDetect->bDfsInit = TRUE; + +} + +BOOLEAN DfsSwCheckOnHwDetection( + IN PRTMP_ADAPTER pAd, + IN pNewDFSTable pDFS2Table, + 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 (pDFS2Table->type == NEW_DFS_JAP) + { + /* Double check on pusle Width and Period*/ + if (DfsChannel < 3) + { + /*check short pulse*/ + if (RadarWidth < 375) + { + /* block the illegal period */ + if ((RadarPeriod < 2800) || + (RadarPeriod > 5000 && RadarPeriod < 6400) || + (RadarPeriod > 6800 && RadarPeriod < 27560)|| + (RadarPeriod > 27960 && RadarPeriod < 28360) || + (RadarPeriod > 28700 && RadarPeriod < 79900) || + (RadarPeriod > 80100)) + { + /*(0~140), (250~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 > 375) + { + if ((RadarPeriod<3500) || (RadarPeriod>10400)) + { + /* block the illegal period */ + /*(0~175) and (520us~) 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 (pDFS2Table->type == NEW_DFS_EU) + { + if (DfsChannel == 4) /* to do: check dfs mode 8or9*/ + { + if (StagerRadarCheck(pAd, DfsChannel) == FALSE) + 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; + + for (i=0; iChannelListNum; i++) + { + if (pAd->CommonCfg.Channel == 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 */ + + /*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->fcc_5_threshold = 1000; + pDfsSwParam->fcc_5_idx = 0; + pDfsSwParam->fcc_5_last_idx = 0; + 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; + + /* clear long pulse table */ + pDfsSwParam->FCC_5[pDfsSwParam->fcc_5_idx].counter = 0; + pDfsSwParam->fcc_5_idx = 0; + pDfsSwParam->fcc_5_last_idx = 0; + + /*pDfsSwParam->dfs_width_diff_Shift = DFS_SW_RADAR_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); + else + pDfsSwParam->dfs_period_err = DFS_SW_RADAR_PERIOD_ERR; + if (pAd->CommonCfg.RDDurRegion == CE) + { + 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_declare_thres = DFS_SW_RADAR_DECLARE_THRES;*/ + 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); + else + pDfsSwParam->dfs_period_err = DFS_SW_RADAR_PERIOD_ERR; + + if (pAd->CommonCfg.RDDurRegion == CE) + { + 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_declare_thres = DFS_SW_RADAR_DECLARE_THRES;*/ + 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 pDFS2Table; + 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) + pDFS2Table = &NewDFSTable1[0]; + else if (pAd->CommonCfg.RDDurRegion == CE) + { + pDFS2Table = &NewDFSTable1[1]; + } + else /* Japan*/ + { + if ((pAd->CommonCfg.Channel >= 52) && (pAd->CommonCfg.Channel <= 64)) + { + pDFS2Table = &NewDFSTable1[3]; + } + else + { + pDFS2Table = &NewDFSTable1[2]; + } + } + + 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: + pDFS2Table->entry[x].mode = (USHORT)value; + break; + case 2: + pDFS2Table->entry[x].avgLen = (USHORT)value; + break; + case 3: + pDFS2Table->entry[x].ELow = (USHORT)value; + break; + + case 4: + pDFS2Table->entry[x].EHigh = (USHORT)value; + break; + + case 5: + pDFS2Table->entry[x].WLow = (USHORT)value; + break; + + case 6: + pDFS2Table->entry[x].WHigh = (USHORT)value; + break; + + case 7: + pDFS2Table->entry[x].EpsilonW = (USHORT)value; + break; + + case 8: + pDFS2Table->entry[x].TLow = (ULONG)value; + break; + + case 9: + pDFS2Table->entry[x].THigh = (ULONG)value; + break; + + case 0xa: + pDFS2Table->entry[x].EpsilonT = (USHORT)value; + break; + + case 0xb: + pDFS2Table->entry[x].BLow= (USHORT)value; + break; + case 0xc: + pDFS2Table->entry[x].BHigh = (USHORT)value; + break; + + default: + break; + } + + } + else if (idx == (DfsEngineNum*16 +1)) + { + pDfsProgramParam->Symmetric_Round = (ULONG)value; + } + else if (idx == (DfsEngineNum*16 +2)) + { + pDfsProgramParam->VGA_Mask = (ULONG)value; + } + else if (idx == (DfsEngineNum*16 +3)) + { + pDfsProgramParam->Packet_End_Mask = (ULONG)value; + } + else if (idx == (DfsEngineNum*16 +4)) + { + pDfsProgramParam->Rx_PE_Mask = (ULONG)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", + (x*16+1), (unsigned int)pDFS2Table->entry[x].mode, + (x*16+2), (unsigned int)pDFS2Table->entry[x].avgLen, + (x*16+3), (unsigned int)pDFS2Table->entry[x].ELow, + (x*16+4), (unsigned int)pDFS2Table->entry[x].EHigh, + (x*16+5), (unsigned int)pDFS2Table->entry[x].WLow, + (x*16+6), (unsigned int)pDFS2Table->entry[x].WHigh, + (x*16+7), (unsigned int)pDFS2Table->entry[x].EpsilonW, + (x*16+8), (unsigned int)pDFS2Table->entry[x].TLow, + (x*16+9), (unsigned int)pDFS2Table->entry[x].THigh, + (x*16+0xa), (unsigned int)pDFS2Table->entry[x].EpsilonT, + (x*16+0xb), (unsigned int)pDFS2Table->entry[x].BLow, + (x*16+0xc), (unsigned int)pDFS2Table->entry[x].BHigh); + } + + 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; + PDFS_SW_DETECT_PARAM pDfsSwParam = &pRadarDetect->DfsSwParam; + + if (!DFS_CHECK_FLAGS(pAd, pRadarDetect) || + (pRadarDetect->PollTime == 0)) + return; + + /* to prevent possible re-entries*/ + pRadarDetect->bDfsInit = FALSE; + + if (pRadarDetect->RadarTimeStampLow++ == 0xffffffff) + pRadarDetect->RadarTimeStampHigh++; + + /*511ms*/ + if ((pRadarDetect->RadarTimeStampLow & 0x1ff) == 0) + DfsCheckBusyIdle(pAd); + + /*if ((pRadarDetect->McuRadarTick++ >= pRadarDetect->PollTime) &&*/ + if ((pRadarDetect->McuRadarTick++ >= 30) && /* 30ms */ + (!pRadarDetect->ch_busy) && + (!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 + * Poll Status register + * Set BBP_R140=0x02 and Read BBP_R141 to store at channel + */ + RTMP_DFS_IO_READ8(pAd, 0x2, &channel); + /*Check if any interrupt trigger by Radar Global Status(Radar Signals)*/ + if ((channel & pRadarDetect->EnabledChMask) && (!pRadarDetect->ch_busy)) + { + radarDeclared = DfsChannelCheck(pAd, channel); + } + + /*reset the radar channel for new counting (Write clear) */ + if (channel & pRadarDetect->EnabledChMask) + RTMP_DFS_IO_WRITE8(pAd, 0x2, channel); + + if (pRadarDetect->McuRadarDebug & RADAR_SIMULATE) + { + radarDeclared = 1; + pRadarDetect->McuRadarDebug &= ~RADAR_SIMULATE; + } + + if ((radarDeclared || pRadarDetect->radarDeclared) && (pRadarDetect->ch_busy_countdown == -1)) + pRadarDetect->ch_busy_countdown = 20; + 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)) + { + /* 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; + + /* clear long pulse table */ + pDfsSwParam->FCC_5[pDfsSwParam->fcc_5_idx].counter = 0; + pDfsSwParam->fcc_5_idx = 0; + pDfsSwParam->fcc_5_last_idx = 0; + } + pRadarDetect->bDfsInit = TRUE; +} + +static VOID SwCheckDfsEvent( + IN PRTMP_ADAPTER pAd) +{ + INT k, limit = 64; + UCHAR BBPR126 = 0, 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 of channel 3*/ + BBP_IO_READ8_BY_REG_ID(pAd, BBP_R126, &BBPR126); + /*Power up the DFS event buffer and Disable the capture.*/ + BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R126, (BBPR126 & 0xfe) | 0x2); + + pDfsSwParam->dfs_w_counter++; + + for (k = 0; k < limit; k++) + { + UINT8 idx; + UINT8 EventBuff[DFS_EVENT_SIZE] = {0}; + + /* Read a event from event buffer */ + for (idx = 0; idx < DFS_EVENT_SIZE; idx++) + BBP_IO_READ8_BY_REG_ID(pAd, BBP_R127, &EventBuff[idx]); + + if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_SHOW_RAW_EVENT) + { + DFS_EVENT_BUFF_PRINT(0, EventBuff, DFS_EVENT_SIZE); + } + + /* fetch event data */ + if (DfsEventDataFetch(pAd, EventBuff, &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; + } + } + } + + /* enable debug mode*/ + if (pDfsSwParam->dfs_w_counter & 1) + BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R126, 3); + else + BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R126, 7); + + 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); + } + + BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R126, (BBPR126 | 0x3)); +} +#endif /* RTMP_MAC_PCI */ + +#endif /*CONFIG_AP_SUPPORT*/ +#endif /* DFS_SUPPORT */ + diff --git a/mt7620/src/common/cmm_info.c b/mt7620/src/common/cmm_info.c new file mode 100644 index 0000000..4f4b7a7 --- /dev/null +++ b/mt7620/src/common/cmm_info.c @@ -0,0 +1,7960 @@ +/**************************************************************************** + * 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" + + +INT Show_SSID_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_WirelessMode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_TxBurst_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_TxPreamble_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_TxPower_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_Channel_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_BGProtection_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_RTSThreshold_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_FragThreshold_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +#ifdef DOT11_N_SUPPORT +INT Show_HtBw_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_HtMcs_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_HtGi_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_HtOpMode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_HtExtcha_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_HtMpduDensity_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_HtBaWinSize_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_HtRdg_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_HtAmsdu_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_HtAutoBa_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); +#endif /* DOT11_N_SUPPORT */ + +INT Show_CountryRegion_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_CountryRegionABand_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_CountryCode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +#ifdef AGGREGATION_SUPPORT +INT Show_PktAggregate_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); +#endif /* AGGREGATION_SUPPORT */ + +#ifdef WMM_SUPPORT +INT Show_WmmCapable_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); +#endif /* WMM_SUPPORT */ + +INT Show_IEEE80211H_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +#ifdef CONFIG_STA_SUPPORT +INT Show_NetworkType_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +#ifdef WSC_STA_SUPPORT +INT Show_WpsPbcBand_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); +#endif /* WSC_STA_SUPPORT */ + +INT Show_WPAPSK_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_AutoReconnect_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +#endif /* CONFIG_STA_SUPPORT */ + +INT Show_AuthMode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_EncrypType_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_Key1_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_Key2_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_Key3_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_Key4_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_PMK_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_STA_RAInfo_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +#ifdef WSC_STA_SUPPORT +INT Show_WpsManufacturer_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_WpsModelName_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_WpsDeviceName_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_WpsModelNumber_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); + +INT Show_WpsSerialNumber_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); +#endif // WSC_STA_SUPPORT // + +#ifdef SINGLE_SKU +INT Show_ModuleTxpower_Proc( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pBuf, + IN ULONG BufLen); +#endif /* SINGLE_SKU */ + +extern INT Set_AP_WscConfStatus_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +extern INT Set_AP_AuthMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +extern INT Set_AP_EncrypType_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +extern INT Set_AP_SSID_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +extern INT Set_AP_WPAPSK_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +static struct { + PSTRING name; + INT (*show_proc)(PRTMP_ADAPTER pAdapter, 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 + +#ifdef WMM_SUPPORT + {"WmmCapable", Show_WmmCapable_Proc}, +#endif + {"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} +}; + +/* + ========================================================================== + Description: + Get Driver version. + + Return: + ========================================================================== +*/ +INT Set_DriverVersion_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + DBGPRINT(RT_DEBUG_TRACE, ("Driver version-%s\n", AP_DRIVER_VERSION)); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + DBGPRINT(RT_DEBUG_TRACE, ("Driver version-%s\n", STA_DRIVER_VERSION)); +#endif /* CONFIG_STA_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 PRTMP_ADAPTER pAd, + IN PSTRING arg, + IN BOOLEAN FlgIsDiffMbssModeUsed) +{ + INT success = TRUE; + UINT32 i = 0; + +#ifdef CONFIG_AP_SUPPORT +#ifdef MBSS_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if (FlgIsDiffMbssModeUsed == 0) + success = RT_CfgSetWirelessMode(pAd, arg); + else + success = RT_CfgSetMbssWirelessMode(pAd, arg); +#else + success = RT_CfgSetWirelessMode(pAd, arg); +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + i = i; /* aviod compile warning */ + +#ifdef CONFIG_STA_SUPPORT + success = RT_CfgSetWirelessMode(pAd, arg); +#endif /* CONFIG_STA_SUPPORT */ + + 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].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].PhyMode = pAd->CommonCfg.PhyMode; +#endif /* MBSS_SUPPORT */ + } + + /* TODO: Is the function BuildChannelList() still necessary here, due to it also been called in RTMPSetPhyMode()!*/ + BuildChannelList(pAd); + RTMPSetPhyMode(pAd, pAd->CommonCfg.PhyMode); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + LONG WirelessMode = pAd->CommonCfg.PhyMode; + + /* clean up previous SCAN result */ + BssTableInit(&pAd->ScanTab); + if (pAd->StaCfg.LastScanTime > 10 * OS_HZ) + pAd->StaCfg.LastScanTime -= (10 * OS_HZ); + + RTMPSetPhyMode(pAd, WirelessMode); +#ifdef DOT11_N_SUPPORT + if (WirelessMode >= PHY_11ABGN_MIXED) + { + 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 */ + + /* it is needed to set SSID to take effect*/ +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif /* DOT11_N_SUPPORT */ + +#ifdef RT305x + RTMP_CHIP_SPECIFIC(pAd, RT305x_WLAN_MODE_CHANGE, NULL, 0); +#endif /* RT305x */ + +#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].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) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + INT MaxPhyMode = PHY_11G; + LONG WirelessMode; + + + /* sanity check */ +#ifdef DOT11_N_SUPPORT + if (!RTMP_TEST_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DOT_11N)) + MaxPhyMode = PHY_11N_5G; +#endif /* DOT11_N_SUPPORT */ + + WirelessMode = simple_strtol(arg, 0, 10); + if (WirelessMode > MaxPhyMode) + return FALSE; /* out of range */ + + if ((WirelessMode == PHY_11ABG_MIXED) +#ifdef DOT11_N_SUPPORT + || (WirelessMode == PHY_11ABGN_MIXED) + || (WirelessMode == PHY_11AGN_MIXED) +#endif /* DOT11_N_SUPPORT */ + ) + { + DBGPRINT(RT_DEBUG_ERROR, ("mbss> Wrong phy mode for AP!\n")); + return FALSE; + } + + /* assign wireless mode for the BSS */ + pAd->ApCfg.MBSSID[pObj->ioctl_if].PhyMode = WirelessMode; + + /* + If the band is different with other BSS, we will correct it in + RT_CfgSetMbssWirelessMode() + */ + 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( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + return Set_Cmm_WirelessMode_Proc(pAd, arg, 0); +} + + +/* + ========================================================================== + 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; + + 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 = pAd->CommonCfg.Channel; + + if (MONITOR_ON(pAd)) + { +#ifdef DOT11_N_SUPPORT + N_ChannelCheck(pAd); + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && + pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + { + N_SetCenCh(pAd); + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + DBGPRINT(RT_DEBUG_TRACE, ("BW_40, control_channel(%d), CentralChannel(%d) \n", + pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, ("BW_20, Channel(%d)\n", pAd->CommonCfg.Channel)); + } + + } + } +#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 (((pAd->CommonCfg.PhyMode == PHY_11A) +#ifdef DOT11_N_SUPPORT + || (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) +#endif /* DOT11_N_SUPPORT */ + ) + && (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) + { + 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; + } + } + 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 APCLI_AUTO_CONNECT_SUPPORT + pAd->ApCfg.ApCliAutoConnectChannelSwitching = FALSE; +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + return success; +} + + +/* + ========================================================================== + 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; + } + 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) +{ + ULONG aggre; + UINT status; + + aggre = simple_strtol(arg, 0, 10); + + if (aggre == 1) + { + if(pAd->PPAEnable==TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("INF_AMAZON_SE_PPA already enabled \n")); + } + else + { + if (ppa_hook_directpath_register_dev_fn) + { + UINT32 g_if_id; + + if (pAd->pDirectpathCb == NULL) + { +/* pAd->pDirectpathCb = (PPA_DIRECTPATH_CB *) kmalloc (sizeof(PPA_DIRECTPATH_CB), GFP_ATOMIC);*/ + os_alloc_mem(NULL, (UCHAR **)&(pAd->pDirectpathCb), sizeof(PPA_DIRECTPATH_CB)); + DBGPRINT(RT_DEBUG_TRACE, ("Realloc memory for pDirectpathCb ??\n")); + } + + /* 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; + DBGPRINT(RT_DEBUG_TRACE, ("register INF_AMAZON_SE_PPA success :ret:%d id:%d:%d\n",status,pAd->g_if_id,g_if_id)); + pAd->PPAEnable=TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("register INF_AMAZON_SE_PPA fail :ret:%d\n",status)); + } + + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("INF_AMAZON_SE_PPA enable fail : there is no INF_AMAZON_SE_PPA module . \n")); + } + } + + + } + else if (aggre == 0) + { + if(pAd->PPAEnable==FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("INF_AMAZON_SE_PPA already disable \n")); + } + else + { + if (ppa_hook_directpath_register_dev_fn) + { + UINT32 g_if_id; + g_if_id=pAd->g_if_id; + + DBGPRINT(RT_DEBUG_TRACE, ("g_if_id=%d \n",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==1) + { + pAd->g_if_id=0; + DBGPRINT(RT_DEBUG_TRACE, ("unregister INF_AMAZON_SE_PPA success :ret:%d\n",status)); + pAd->PPAEnable=FALSE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("unregister INF_AMAZON_SE_PPA fail :ret:%d\n",status)); + } + + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("INF_AMAZON_SE_PPA enable fail : there is no INF_AMAZON_SE_PPA module . \n")); + } + } + + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Invalid argument %d \n",aggre)); + return FALSE; /*Invalid argument */ + } + + 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 P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_WscGenPinCode_Proc:: This command is from apcli interface now.\n", apidx)); + } +#endif /* P2P_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type != INT_P2P) +#endif /* P2P_SUPPORT */ +{ + 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; + pWscControl->WscEnrolleePinCode = WscRandomGeneratePinCode(pAd, apidx); + } + +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + PWSC_CTRL pApWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + pApWscControl->WscEnrolleePinCodeLen = pWscControl->WscEnrolleePinCodeLen; + pApWscControl->WscEnrolleePinCode = pWscControl->WscEnrolleePinCode; + } +#endif /* P2P_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscGenPinCode_Proc:: Enrollee PinCode\t\t%08u\n", pWscControl->WscEnrolleePinCode)); + + return TRUE; +} + +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 P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + RT_CfgSetWscPinCode(pAd, arg, pWscControl); + + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + RT_CfgSetWscPinCode(pAd, arg, pWscControl); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscVendorPinCode_Proc() for p2p(%d)\n", apidx)); + return TRUE; + } +#endif /* P2P_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type != INT_P2P) +#endif /* P2P_SUPPORT */ + pWscControl = &pAd->StaCfg.WscControl; + } +#endif /* CONFIG_STA_SUPPORT */ + + if (!pWscControl) + return FALSE; + else + return RT_CfgSetWscPinCode(pAd, arg, pWscControl); +} +#endif /* WSC_INCLUDED */ + +#ifdef DBG +/* + ========================================================================== + Description: + For Debug information + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Debug_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + DBGPRINT(RT_DEBUG_TRACE, ("==> Set_Debug_Proc *******************\n")); + + if(simple_strtol(arg, 0, 10) <= RT_DEBUG_LOUD) + RTDebugLevel = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("<== Set_Debug_Proc(RTDebugLevel = %ld)\n", RTDebugLevel)); + + return TRUE; +} +#endif + +INT Show_DescInfo_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ +#ifdef RTMP_MAC_PCI + INT i, QueIdx=0; +/* ULONG RegValue;*/ + PRT28XX_RXD_STRUC pRxD; + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PRT28XX_RXD_STRUC pDestRxD; + RXD_STRUC RxD; + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; +#endif /* RT_BIG_ENDIAN */ + PRTMP_TX_RING pTxRing = &pAd->TxRing[QueIdx]; + PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing; + PRTMP_RX_RING pRxRing = &pAd->RxRing; + + 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 = (PRT28XX_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) +{ + /*UCHAR i;*/ + /*MAC_TABLE_ENTRY *pEntry;*/ + + 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)); + + /* Reset HotSpot counter*/ + +#ifdef RALINK_QA + pAd->ate.U2M = 0; + pAd->ate.OtherData = 0; + pAd->ate.OtherCount = 0; +#endif /* RALINK_QA */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef GEMTEK_ATE + DBGPRINT(RT_DEBUG_OFF, (KERN_EMERG "Gemtek:Success\n")); +#endif /* GEMTEK_ATE */ +#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; +} + +/* + ======================================================================== + + Routine Description: + Add WPA key process. + In Adhoc WPANONE, bPairwise = 0; KeyIdx = 0; + + 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: + + ======================================================================== +*/ + +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( + IN PRTMP_ADAPTER pAdapter, + IN LONG Rates) +{ + NDIS_802_11_RATES aryRates; + + memset(&aryRates, 0x00, sizeof(NDIS_802_11_RATES)); + switch (pAdapter->CommonCfg.PhyMode) + { + case PHY_11A: /* A only*/ + switch (Rates) + { + case 6000000: /*6M*/ + aryRates[0] = 0x0c; /* 6M*/ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_0; + break; + case 9000000: /*9M*/ + aryRates[0] = 0x12; /* 9M*/ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_1; + break; + case 12000000: /*12M*/ + aryRates[0] = 0x18; /* 12M*/ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_2; + break; + case 18000000: /*18M*/ + aryRates[0] = 0x24; /* 18M*/ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_3; + break; + case 24000000: /*24M*/ + aryRates[0] = 0x30; /* 24M*/ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_4; + break; + case 36000000: /*36M*/ + aryRates[0] = 0x48; /* 36M*/ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_5; + break; + case 48000000: /*48M*/ + aryRates[0] = 0x60; /* 48M*/ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_6; + break; + case 54000000: /*54M*/ + aryRates[0] = 0x6c; /* 54M*/ + pAdapter->StaCfg.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*/ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; + break; + } + break; + case PHY_11BG_MIXED: /* B/G Mixed*/ + case PHY_11B: /* B only*/ + case PHY_11ABG_MIXED: /* A/B/G Mixed*/ + default: + switch (Rates) + { + case 1000000: /*1M*/ + aryRates[0] = 0x02; + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_0; + break; + case 2000000: /*2M*/ + aryRates[0] = 0x04; + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_1; + break; + case 5000000: /*5.5M*/ + aryRates[0] = 0x0b; /* 5.5M*/ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_2; + break; + case 11000000: /*11M*/ + aryRates[0] = 0x16; /* 11M*/ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_3; + break; + case 6000000: /*6M*/ + aryRates[0] = 0x0c; /* 6M*/ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_0; + break; + case 9000000: /*9M*/ + aryRates[0] = 0x12; /* 9M*/ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_1; + break; + case 12000000: /*12M*/ + aryRates[0] = 0x18; /* 12M*/ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_2; + break; + case 18000000: /*18M*/ + aryRates[0] = 0x24; /* 18M*/ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_3; + break; + case 24000000: /*24M*/ + aryRates[0] = 0x30; /* 24M*/ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_4; + break; + case 36000000: /*36M*/ + aryRates[0] = 0x48; /* 36M*/ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_5; + break; + case 48000000: /*48M*/ + aryRates[0] = 0x60; /* 48M*/ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_6; + break; + case 54000000: /*54M*/ + aryRates[0] = 0x6c; /* 54M*/ + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_7; + break; + case -1: /*Auto*/ + default: + if (pAdapter->CommonCfg.PhyMode == PHY_11B) + { /*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*/ + } + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; + break; + } + break; + } + + NdisZeroMemory(pAdapter->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES); + NdisMoveMemory(pAdapter->CommonCfg.DesireRate, &aryRates, sizeof(NDIS_802_11_RATES)); + DBGPRINT(RT_DEBUG_TRACE, (" RTMPSetDesiredRates (%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x)\n", + pAdapter->CommonCfg.DesireRate[0],pAdapter->CommonCfg.DesireRate[1], + pAdapter->CommonCfg.DesireRate[2],pAdapter->CommonCfg.DesireRate[3], + pAdapter->CommonCfg.DesireRate[4],pAdapter->CommonCfg.DesireRate[5], + pAdapter->CommonCfg.DesireRate[6],pAdapter->CommonCfg.DesireRate[7] )); + /* Changing DesiredRate may affect the MAX TX rate we used to TX frames out*/ + MlmeUpdateTxRates(pAdapter, FALSE, 0); +} +#endif /* CONFIG_STA_SUPPORT */ + +#if defined(CONFIG_STA_SUPPORT) || defined(APCLI_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 APCLI_WPA_SUPPLICANT_SUPPORT + UCHAR ifIndex; + BOOLEAN apcliEn=FALSE; + INT idx, BssIdx; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; +#endif/*APCLI_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 APCLI_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/*APCLI_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(APCLI_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( + IN PRTMP_ADAPTER pAd) +{ + + UCHAR i; + + DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveAllKeys(AuthMode=%d, WepStatus=%d)\n", pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus)); + /* + For WEP/CKIP, 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 (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA) + return; + + /* For 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 (pAd->StaCfg.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: + As STA's BSSID is a WC too, it uses shared key table. + This function write correct unicast TX key to ASIC WCID. + And we still make a copy in our MacTab.Content[BSSID_WCID].PairwiseKey. + Caller guarantee TKIP/AES always has keyidx = 0. (pairwise key) + Caller guarantee WEP calls this function when set Txkey, default key index=0~3. + + Arguments: + pAd Pointer to our adapter + pKey Pointer to the where the key stored + + Return Value: + NDIS_SUCCESS Add key successfully + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ + +VOID RTMPSetDefaultChannel( + IN PRTMP_ADAPTER pAd + ) +{ + if ((pAd->CommonCfg.PhyMode != PHY_11A) +#ifdef DOT11_N_SUPPORT + && (pAd->CommonCfg.PhyMode != PHY_11AN_MIXED) && (pAd->CommonCfg.PhyMode != PHY_11N_5G) +#endif /* DOT11_N_SUPPORT */ + ) + { + pAd->CommonCfg.Channel = 1; + } + if ((pAd->CommonCfg.PhyMode == PHY_11A) || (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) +#ifdef DOT11_N_SUPPORT + || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) + || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11N_5G) +#endif /* DOT11_N_SUPPORT */ + ) + { + pAd->CommonCfg.Channel = 36; + } + DBGPRINT(RT_DEBUG_OFF,("%s() : default channel to %d \n",__FUNCTION__,pAd->CommonCfg.Channel)); + +} + +/* + ======================================================================== + Routine Description: + Change NIC PHY mode. Re-association may be necessary. possible settings + include - PHY_11B, PHY_11BG_MIXED, PHY_11A, and PHY_11ABG_MIXED + + Arguments: + pAd - Pointer to our adapter + phymode - + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID RTMPSetPhyMode( + IN PRTMP_ADAPTER pAd, + IN 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) + if (pAd->CommonCfg.Channel != 0) + 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 PHY_11B: + 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 PHY_11G: + case PHY_11BG_MIXED: + case PHY_11ABG_MIXED: +#ifdef DOT11_N_SUPPORT + case PHY_11N_2_4G: + case PHY_11ABGN_MIXED: + case PHY_11BGN_MIXED: + case PHY_11GN_MIXED: +#endif /* DOT11_N_SUPPORT */ + 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 PHY_11A: +#ifdef DOT11_N_SUPPORT + case PHY_11AN_MIXED: + case PHY_11AGN_MIXED: + case PHY_11N_5G: +#endif /* DOT11_N_SUPPORT */ + 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 P2P_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + UINT apidx; + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + MlmeUpdateTxRates(pAd, FALSE, apidx + MIN_NET_DEVICE_FOR_P2P_GO); + } + + for (apidx = 0; apidx < MAX_APCLI_NUM; apidx++) + { + MlmeUpdateTxRates(pAd, FALSE, apidx + MIN_NET_DEVICE_FOR_APCLI); + } + } +#endif /* P2P_SUPPORT */ + + pAd->CommonCfg.BandState = UNKNOWN_BAND; +} + + +#ifdef DOT11_N_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 RTMPSetHT( + IN PRTMP_ADAPTER pAd, + IN OID_SET_HT_PHYMODE *pHTPhyMode) +{ + /*ULONG *pmcs;*/ + UINT32 Value = 0; + UCHAR BBPValue = 0; + UCHAR BBP3Value = 0; + UCHAR RxStream = pAd->CommonCfg.RxStream; +#ifdef CONFIG_AP_SUPPORT + INT apidx; +#endif /* CONFIG_AP_SUPPORT */ + +#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(&pAd->CommonCfg.HtCapability, sizeof(pAd->CommonCfg.HtCapability)); + RTMPZeroMemory(&pAd->CommonCfg.AddHTInfo, sizeof(pAd->CommonCfg.AddHTInfo)); + RTMPZeroMemory(&pAd->CommonCfg.NewExtChanOffset, sizeof(pAd->CommonCfg.NewExtChanOffset)); + RTMPZeroMemory(&pAd->CommonCfg.DesiredHtPhy, sizeof(pAd->CommonCfg.DesiredHtPhy)); + + if (pAd->CommonCfg.bRdg) + { + pAd->CommonCfg.HtCapability.ExtHtCapInfo.PlusHTC = 1; + pAd->CommonCfg.HtCapability.ExtHtCapInfo.RDGSupport = 1; + } + else + { + pAd->CommonCfg.HtCapability.ExtHtCapInfo.PlusHTC = 0; + pAd->CommonCfg.HtCapability.ExtHtCapInfo.RDGSupport = 0; + } + + + if (RxStream == 1) + { + pAd->CommonCfg.HtCapability.HtCapParm.MaxRAmpduFactor = 2; + pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor = 2; + } + else + { + pAd->CommonCfg.HtCapability.HtCapParm.MaxRAmpduFactor = 3; + pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor = 3; + } + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : RxBAWinLimit = %d\n", pAd->CommonCfg.BACapability.field.RxBAWinLimit)); + + /* Mimo power save, A-MSDU size, */ + pAd->CommonCfg.DesiredHtPhy.AmsduEnable = (USHORT)pAd->CommonCfg.BACapability.field.AmsduEnable; + pAd->CommonCfg.DesiredHtPhy.AmsduSize = (UCHAR)pAd->CommonCfg.BACapability.field.AmsduSize; + pAd->CommonCfg.DesiredHtPhy.MimoPs = (UCHAR)pAd->CommonCfg.BACapability.field.MMPSmode; + pAd->CommonCfg.DesiredHtPhy.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; + + pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize; + pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode; + pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : AMsduSize = %d, MimoPs = %d, MpduDensity = %d, MaxRAmpduFactor = %d\n", + pAd->CommonCfg.DesiredHtPhy.AmsduSize, + pAd->CommonCfg.DesiredHtPhy.MimoPs, + pAd->CommonCfg.DesiredHtPhy.MpduDensity, + pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor)); + + if(pHTPhyMode->HtMode == HTMODE_GF) + { + pAd->CommonCfg.HtCapability.HtCapInfo.GF = 1; + pAd->CommonCfg.DesiredHtPhy.GF = 1; + } + else + pAd->CommonCfg.DesiredHtPhy.GF = 0; + + /* Decide Rx MCSSet*/ + switch (RxStream) + { + case 1: + pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff; + pAd->CommonCfg.HtCapability.MCSSet[1] = 0x00; + break; + + case 2: + pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff; + pAd->CommonCfg.HtCapability.MCSSet[1] = 0xff; + break; + + case 3: /* 3*3*/ + pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff; + pAd->CommonCfg.HtCapability.MCSSet[1] = 0xff; + pAd->CommonCfg.HtCapability.MCSSet[2] = 0xff; + break; + } + + if (pAd->CommonCfg.bForty_Mhz_Intolerant && (pHTPhyMode->BW == BW_40) /* && (pAd->CommonCfg.Channel <= 14)*/) + { + pHTPhyMode->BW = BW_20; + pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant = 1; + } + + if(pHTPhyMode->BW == BW_40) + { + pAd->CommonCfg.HtCapability.MCSSet[4] = 0x1; /* MCS 32*/ + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = 1; + if (pAd->CommonCfg.Channel <= 14) + pAd->CommonCfg.HtCapability.HtCapInfo.CCKmodein40 = 1; + + pAd->CommonCfg.DesiredHtPhy.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_IO_READ32(pAd, TX_BAND_CFG, &Value); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBP3Value); + if ((pHTPhyMode->ExtOffset == EXTCHA_BELOW)) + { + Value |= 0x1; + BBP3Value |= (0x20); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + } + else if ((pHTPhyMode->ExtOffset == EXTCHA_ABOVE)) + { + Value &= 0xfe; + BBP3Value &= (~0x20); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + } + + /* 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) +#ifdef MESH_SUPPORT + || MESH_ON(pAd) +#endif /* MESH_SUPPORT */ +#ifdef P2P_SUPPORT + || P2P_GO_ON(pAd) +#endif /* P2P_SUPPORT */ + ) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPActive == 0) +#endif /* GREENAP_SUPPORT */ + BBPValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBP3Value); +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPActive == 1) + pAd->CommonCfg.BBPCurrentBW = BW_20; + else +#endif /* GREENAP_SUPPORT */ + pAd->CommonCfg.BBPCurrentBW = BW_40; + +#ifdef RT305x + RTMP_CHIP_SPECIFIC(pAd, RT305x_HT_MODE_CHANGE, NULL, BW_40); +#endif /* RT305x */ + } + } + else + { + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = 0; + pAd->CommonCfg.DesiredHtPhy.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.*/ + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + pAd->CommonCfg.BBPCurrentBW = BW_20; + +#ifdef RT305x + RTMP_CHIP_SPECIFIC(pAd, RT305x_HT_MODE_CHANGE, NULL, BW_20); +#endif /* RT305x */ + } + } + + if(pHTPhyMode->STBC == STBC_USE) + { + /* + TxSTBC + 0:not supported, + 1:if supported + */ + if (pAd->Antenna.field.TxPath >= 2) + { + pAd->CommonCfg.HtCapability.HtCapInfo.TxSTBC = 1; + pAd->CommonCfg.DesiredHtPhy.TxSTBC = 1; + } + else + { + pAd->CommonCfg.HtCapability.HtCapInfo.TxSTBC = 0; + pAd->CommonCfg.DesiredHtPhy.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) + { + pAd->CommonCfg.HtCapability.HtCapInfo.RxSTBC = 1; + pAd->CommonCfg.DesiredHtPhy.RxSTBC = 1; + } + else + { + pAd->CommonCfg.HtCapability.HtCapInfo.RxSTBC = 0; + pAd->CommonCfg.DesiredHtPhy.RxSTBC = 0; + } + } + else + { + pAd->CommonCfg.DesiredHtPhy.TxSTBC = 0; + pAd->CommonCfg.DesiredHtPhy.RxSTBC = 0; + } + + if(pHTPhyMode->SHORTGI == GI_400) + { + pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20 = 1; + pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40 = 1; + pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 = 1; + pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 = 1; + } + else + { + pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20 = 0; + pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40 = 0; + pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 = 0; + pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 = 0; + } + + /* We support link adaptation for unsolicit MCS feedback, set to 2.*/ +#if defined(RT2883) || defined(RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + pAd->CommonCfg.HtCapability.ExtHtCapInfo.MCSFeedback = MCSFBK_NONE; /* MCSFBK_UNSOLICIT; */ + /* pAd->CommonCfg.HtCapability.ExtHtCapInfo.MCSFeedback = MCSFBK_MRQ; */ +#endif /* definde(RT2883) || defined(RT3883) */ + 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) + { + 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; + } + AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); + +#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 TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + { + /* Set ETxBF */ + setETxBFCap(pAd, &pAd->CommonCfg.HtCapability.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_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef P2P_SUPPORT + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + RTMPSetIndividualHT(pAd, apidx + MIN_NET_DEVICE_FOR_P2P_GO); + } + + for (apidx = 0; apidx < MAX_APCLI_NUM; apidx++) + { + RTMPSetIndividualHT(pAd, apidx + MIN_NET_DEVICE_FOR_APCLI); + } +#endif /* P2P_SUPPORT */ + + RTMPSetIndividualHT(pAd, 0); + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef MESH_SUPPORT + RTMPSetIndividualHT(pAd, MIN_NET_DEVICE_FOR_MESH); +#endif /* MESH_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( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx) +{ + PRT_HT_PHY_INFO pDesired_ht_phy = NULL; + UCHAR TxStream = pAd->CommonCfg.TxStream; + UCHAR DesiredMcs = MCS_AUTO; + UCHAR encrypt_mode = Ndis802_11EncryptionDisabled; + + do + { +#ifdef P2P_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_P2P_GO) + { + UCHAR idx = apidx - MIN_NET_DEVICE_FOR_P2P_GO; + + pDesired_ht_phy = &pAd->ApCfg.MBSSID[idx].DesiredHtPhyInfo; + DesiredMcs = pAd->ApCfg.MBSSID[idx].DesiredTransmitSetting.field.MCS; + encrypt_mode = pAd->ApCfg.MBSSID[idx].WepStatus; + pAd->ApCfg.MBSSID[idx].bWmmCapable = TRUE; + pAd->ApCfg.MBSSID[idx].bAutoTxRateSwitch = (DesiredMcs == MCS_AUTO) ? TRUE : FALSE; + /* DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetIndividualHT: P2P GO apidx(%d)\n", apidx)); */ + break; + } +#endif /* P2P_SUPPORT */ + +#ifdef MESH_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_MESH) + { + pDesired_ht_phy = &pAd->MeshTab.DesiredHtPhyInfo; + DesiredMcs = pAd->MeshTab.DesiredTransmitSetting.field.MCS; + encrypt_mode = pAd->MeshTab.WepStatus; + pAd->MeshTab.bAutoTxRateSwitch = (DesiredMcs == MCS_AUTO) ? TRUE : FALSE; + break; + } +#endif /* MESH_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].DesiredHtPhyInfo; + DesiredMcs = pAd->ApCfg.ApCliTab[idx].DesiredTransmitSetting.field.MCS; + encrypt_mode = pAd->ApCfg.ApCliTab[idx].WepStatus; + pAd->ApCfg.ApCliTab[idx].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].DesiredHtPhyInfo; + DesiredMcs = pAd->WdsTab.WdsEntry[idx].DesiredTransmitSetting.field.MCS; + /*encrypt_mode = pAd->WdsTab.WdsEntry[idx].WepStatus;*/ + pAd->WdsTab.WdsEntry[idx].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)) + { + pDesired_ht_phy = &pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo; + DesiredMcs = pAd->ApCfg.MBSSID[apidx].DesiredTransmitSetting.field.MCS; + encrypt_mode = pAd->ApCfg.MBSSID[apidx].WepStatus; + pAd->ApCfg.MBSSID[apidx].bWmmCapable = TRUE; + pAd->ApCfg.MBSSID[apidx].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) + { + pDesired_ht_phy = &pAd->StaCfg.DesiredHtPhyInfo; + DesiredMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS; + encrypt_mode = pAd->StaCfg.WepStatus; + /*pAd->StaCfg.bAutoTxRateSwitch = (DesiredMcs == MCS_AUTO) ? TRUE : FALSE;*/ + 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_HT_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 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)) + { + 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; + } + + pDesired_ht_phy->bHtEnable = TRUE; + + /* Decide desired Tx MCS*/ + switch (TxStream) + { + case 1: + if (DesiredMcs == MCS_AUTO) + { + pDesired_ht_phy->MCSSet[0]= 0xff; + pDesired_ht_phy->MCSSet[1]= 0x00; + } + else if (DesiredMcs <= MCS_7) + { + pDesired_ht_phy->MCSSet[0]= 1<MCSSet[1]= 0x00; + } + break; + + case 2: + if (DesiredMcs == MCS_AUTO) + { + pDesired_ht_phy->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: /* 3*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) + { +#ifdef P2P_SUPPORT + if (apidx > BSS0) + MlmeUpdateHtTxRates(pAd, apidx); + else +#endif /* P2P_SUPPORT */ + MlmeUpdateHtTxRates(pAd, BSS0); + } + else + MlmeUpdateHtTxRates(pAd, apidx); +} + +/* + ======================================================================== + Routine Description: + Clear the desire HT info per interface + + Arguments: + + ======================================================================== +*/ +VOID RTMPDisableDesiredHtInfo( + IN PRTMP_ADAPTER pAd) +{ +#ifdef CONFIG_AP_SUPPORT + UINT8 apidx = 0; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + RTMPZeroMemory(&pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo, sizeof(RT_HT_PHY_INFO)); + } +#ifdef WDS_SUPPORT + for (apidx = 0; apidx < MAX_WDS_ENTRY; apidx++) + { + RTMPZeroMemory(&pAd->WdsTab.WdsEntry[apidx].DesiredHtPhyInfo, sizeof(RT_HT_PHY_INFO)); + } +#endif /* WDS_SUPPORT */ +#ifdef APCLI_SUPPORT + for (apidx = 0; apidx < MAX_APCLI_NUM; apidx++) + { + RTMPZeroMemory(&pAd->ApCfg.ApCliTab[apidx].DesiredHtPhyInfo, sizeof(RT_HT_PHY_INFO)); + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef P2P_SUPPORT + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + RTMPZeroMemory(&pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo, sizeof(RT_HT_PHY_INFO)); + } + + for (apidx = 0; apidx < MAX_APCLI_NUM; apidx++) + { + RTMPZeroMemory(&pAd->ApCfg.ApCliTab[apidx].DesiredHtPhyInfo, sizeof(RT_HT_PHY_INFO)); + } +#endif /* P2P_SUPPORT */ + RTMPZeroMemory(&pAd->StaCfg.DesiredHtPhyInfo, sizeof(RT_HT_PHY_INFO)); + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef MESH_SUPPORT + RTMPZeroMemory(&pAd->MeshTab.DesiredHtPhyInfo, sizeof(RT_HT_PHY_INFO)); +#endif /* MESH_SUPPORT */ +} + + +INT SetCommonHT( + IN PRTMP_ADAPTER pAd) +{ + OID_SET_HT_PHYMODE SetHT; + + if (pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED) + { + /* Clear previous HT information */ + RTMPDisableDesiredHtInfo(pAd); + return FALSE; + } + + 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 */ + +/* + ======================================================================== + 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 MESH_SUPPORT + if (BssIdx >= MIN_NET_DEVICE_FOR_MESH) + { + if (pEntry) + { + BssIdx -= MIN_NET_DEVICE_FOR_MESH; + Wcid = pEntry->Aid; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("RTMPAddWcidAttributeEntry: Mesh link doesn't need to set Group WCID Attribute. \n")); + return; + } + } + else +#endif /* MESH_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->Aid; + 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].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->Aid; + else + Wcid = MCAST_WCID; + } +#endif /* CONFIG_STA_SUPPORT */ + } + + /* Update WCID attribute table*/ + offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_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) + 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(QOS_DLS_SUPPORT) */ + else + WCIDAttri = (CipherAlg<<1) | SHAREDKEYTABLE; + } +#endif /* CONFIG_STA_SUPPORT */ + + RTMP_IO_WRITE32(pAd, offset, WCIDAttri); + + + /* Update IV/EIV table*/ + offset = MAC_IVEIV_TABLE_BASE + (Wcid * HW_IVEIV_ENTRY_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_11Encryption2Enabled) + return "TKIP"; + if(enc == Ndis802_11Encryption3Enabled) + return "AES"; + if(enc == Ndis802_11Encryption4Enabled) + 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 CONFIG_STA_SUPPORT +#ifdef WSC_STA_SUPPORT +#define WPS_LINE_LEN (4+5) /* WPS+DPID*/ +#endif /* WSC_STA_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ +VOID RTMPCommSiteSurveyData( + IN PSTRING msg, + IN PBSS_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; + + /*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; + sprintf(Ssid, "0x"); + for (idx = 0; (idx < 14) && (idx < pBss->SsidLen); idx++) + sprintf(Ssid + 2 + (idx*2), "%02X", (UCHAR)pBss->Ssid[idx]); + } + sprintf(msg+strlen(msg),"%-33s", Ssid); + + /*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) + { + 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_11Encryption4Enabled; + } + 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_11Encryption4Enabled; + } + } + 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; + + if (pBss->WPA.PairCipher != pBss->WPA2.PairCipher) + ap_cipher = Ndis802_11Encryption4Enabled; + else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && + (pBss->WPA.PairCipherAux != pBss->WPA2.PairCipherAux)) + ap_cipher = Ndis802_11Encryption4Enabled; + else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && + (pBss->WPA.PairCipherAux == pBss->WPA2.PairCipherAux) && + (pBss->WPA.PairCipherAux != Ndis802_11WEPDisabled)) + ap_cipher = Ndis802_11Encryption4Enabled; + 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_11Encryption4Enabled; + else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && + (pBss->WPA.PairCipherAux != pBss->WPA2.PairCipherAux)) + ap_cipher = Ndis802_11Encryption4Enabled; + else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && + (pBss->WPA.PairCipherAux == pBss->WPA2.PairCipherAux) && + (pBss->WPA.PairCipherAux != Ndis802_11WEPDisabled)) + ap_cipher = Ndis802_11Encryption4Enabled; + 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),"%-7s", "11b"); + else if (wireless_mode == Ndis802_11OFDM5) + sprintf(msg+strlen(msg),"%-7s", "11a"); + else if (wireless_mode == Ndis802_11OFDM5_N) + sprintf(msg+strlen(msg),"%-7s", "11a/n"); + else if (wireless_mode == Ndis802_11OFDM24) + sprintf(msg+strlen(msg),"%-7s", "11b/g"); + else if (wireless_mode == Ndis802_11OFDM24_N) + sprintf(msg+strlen(msg),"%-7s", "11b/g/n"); + else + sprintf(msg+strlen(msg),"%-7s", "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; +} + +#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 Status=0; + INT max_len = LINE_LEN; + PBSS_ENTRY pBss; + UINT32 TotalLen, BufLen = IW_SCAN_MAX_DATA; + +#ifdef CONFIG_STA_SUPPORT +#ifdef WSC_STA_SUPPORT + max_len += WPS_LINE_LEN; +#endif /* WSC_STA_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + TotalLen = sizeof(CHAR)*((MAX_LEN_OF_BSS_TABLE)*max_len) + 100; + 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"); + + sprintf(msg+strlen(msg),"%-4s%-33s%-20s%-23s%-9s%-7s%-7s%-3s\n", + "Ch", "SSID", "BSSID", "Security", "Siganl(%)", "W-Mode", " ExtCH"," NT"); + +#ifdef WSC_INCLUDED + sprintf(msg+strlen(msg)-1,"%-4s%-5s\n", " WPS", " DPID"); +#endif /* WSC_INCLUDED */ + +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + + WaitCnt = 0; +#ifdef CONFIG_STA_SUPPORT + pAdapter->StaCfg.bSkipAutoScanConn = TRUE; +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef DPA_S + OS_WAIT(100);; +#else /* DPA_S */ + while ((ScanRunning(pAdapter) == TRUE) && (WaitCnt++ < 200)) + OS_WAIT(500); +#endif /* !DPA_S */ + + for(i=0; iScanTab.BssNr ;i++) + { + pBss = &pAdapter->ScanTab.BssEntry[i]; + + if( pBss->Channel==0) + break; + + if((strlen(msg)+100 ) >= BufLen) + break; + + + RTMPCommSiteSurveyData(msg, pBss, TotalLen); + +#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 +#endif /* CONFIG_STA_SUPPORT */ + } + +#ifdef CONFIG_STA_SUPPORT + pAdapter->StaCfg.bSkipAutoScanConn = FALSE; +#endif /* CONFIG_STA_SUPPORT */ + wrq->u.data.length = strlen(msg); + Status = 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 + + +#ifdef RTMP_RBUS_SUPPORT +/* +++ added by Red@Ralink, 2009/09/30 */ +VOID RTMPIoctlGetMacTableStaInfo( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + INT i; +/* RT_802_11_MAC_TABLE MacTab;*/ + RT_802_11_MAC_TABLE *pMacTab = NULL; + PRT_802_11_MAC_ENTRY pDst; + MAC_TABLE_ENTRY *pEntry; + + /* 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 = pEntry->apidx; + 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; +#if defined (RT2883) || defined (RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + { + pDst->StreamSnr[0] = pEntry->BF_SNR[0]; + pDst->StreamSnr[1] = pEntry->BF_SNR[1]; + pDst->StreamSnr[2] = pEntry->BF_SNR[2]; +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + { + pDst->SoundingRespSnr[0] = pEntry->sndg0Snr0; + pDst->SoundingRespSnr[1] = pEntry->sndg0Snr1; + pDst->SoundingRespSnr[2] = pEntry->sndg0Snr2; + } +#endif /* TXBF_SUPPORT */ +/* pDst->TxPER = pEntry->SaveTxPER; */ + } +#endif /* defined (RT2883) || defined (RT3883) */ + + 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__)); + } + + if (pMacTab != NULL) + os_free_mem(NULL, pMacTab); +} +/* +++ end of addition */ +#endif /* RTMP_RBUS_SUPPORT */ + + +#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; +/* RT_802_11_MAC_TABLE MacTab;*/ + RT_802_11_MAC_TABLE *pMacTab = NULL; + RT_802_11_MAC_ENTRY *pDst; + MAC_TABLE_ENTRY *pEntry; + char *msg; +#ifdef DPA_S //yiwei + UCHAR index; + BOOLEAN bFound; +#endif /* DPA_S */ + + /* 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)); + pMacTab->Num = 0; + for (i=0; iMacTab.Content[i]); + +#ifdef DPA_S + if ((IS_P2P_GO_ENTRY(pEntry) || IS_P2P_CLI_ENTRY(pEntry)) + && (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)) +#else /* DPA_S */ + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) +#endif /* !DPA_S */ + { + pDst = &pMacTab->Entry[pMacTab->Num]; + +#ifdef DPA_S //yiwei + bFound = FALSE; + if (IS_P2P_GO_ENTRY(pEntry) || IS_P2P_CLI_ENTRY(pEntry)) + { + index = P2pGroupTabSearch(pAd, pEntry->Addr); + if(index != P2P_NOT_FOUND) + bFound = TRUE; + } + + if(bFound) + { + RTMPMoveMemory(&(pDst->DeviceName[0]), &pAd->P2pTable.Client[index].DeviceName[0], pAd->P2pTable.Client[index].DeviceNameLen); + pDst->DeviceNameLen = pAd->P2pTable.Client[index].DeviceNameLen; + pDst->DeviceName[pDst->DeviceNameLen]=0x0; + } + else + { + pDst->DeviceNameLen = 0; + } +#endif /* DPA_S */ + + pDst->ApIdx = (UCHAR)pEntry->apidx; + 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; + +#ifdef RTMP_RBUS_SUPPORT + pDst->LastRxRate = pEntry->LastRxRate; +#if defined(RT2883) || defined(RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + { + pDst->StreamSnr[0] = pEntry->BF_SNR[0]; + pDst->StreamSnr[1] = pEntry->BF_SNR[1]; + pDst->StreamSnr[2] = pEntry->BF_SNR[2]; +#ifdef TXBF_SUPPORT + pDst->SoundingRespSnr[0] = pEntry->sndg0Snr0; + pDst->SoundingRespSnr[1] = pEntry->sndg0Snr1; + pDst->SoundingRespSnr[2] = pEntry->sndg0Snr2; +#endif /* TXBF_SUPPORT */ + } +#endif /* defined(RT2883) || defined(RT3883) */ +/* pDst->TxPER = pEntry->SaveTxPER; */ +#endif /* RTMP_RBUS_SUPPORT */ + + 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__)); + } + + +/* msg = kmalloc(sizeof(CHAR)*(MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN), MEM_ALLOC_FLAG);*/ + 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]; + +#ifdef DPA_S + if ((IS_P2P_GO_ENTRY(pEntry) || IS_P2P_CLI_ENTRY(pEntry)) + && (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)) +#else /* DPA_S */ + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) +#endif /* !DPA_S */ + { + 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*/ + + DBGPRINT(RT_DEBUG_TRACE, ("%s", msg)); +/* kfree(msg);*/ + os_free_mem(NULL, msg); + +LabelOK: + if (pMacTab != NULL) + os_free_mem(NULL, pMacTab); +} +#define ASSO_MAC_LINE_LEN (1+19+4+4+4+4+8+7+7+7+10+6+6+6+6+7+7+1) + +VOID RTMPAPGetAssoMacTable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + ULONG 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%-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=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; + getRate(pEntry->HTPhyMode, &DataRate); + 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->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 */ + sprintf(msg+strlen(msg),"%-7d", pEntry->RssiSample.AvgRssi0); + sprintf(msg+strlen(msg),"%-7d", pEntry->RssiSample.AvgRssi1); + sprintf(msg+strlen(msg),"%-7d", pEntry->RssiSample.AvgRssi2); + sprintf(msg+strlen(msg),"%-10s", GetPhyMode(pEntry->HTPhyMode.field.MODE)); + sprintf(msg+strlen(msg),"%-6s", GetBW(pEntry->HTPhyMode.field.BW)); + 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),"%-10d, %d, %d%%\n", pEntry->DebugFIFOCount, pEntry->DebugTxCount, + (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0); + 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); +} + +#ifdef INF_AR9 +#ifdef AR9_MAPI_SUPPORT +#ifdef CONFIG_AP_SUPPORT +VOID RTMPAR9IoctlGetMacTable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + INT i; + char *msg; + +/* msg = kmalloc(sizeof(CHAR)*(MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN), MEM_ALLOC_FLAG);*/ + 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)); + } + +/* kfree(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; + + +/* 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); + sprintf(msg+strlen(msg),"bytesTx = %ld\n",(pMbss->TransmittedByteCount)); + sprintf(msg+strlen(msg),"bytesRx = %ld\n",(pMbss->ReceivedByteCount)); + sprintf(msg+strlen(msg),"pktsTx = %ld\n",pMbss->TxCount); + sprintf(msg+strlen(msg),"pktsRx = %ld\n",pMbss->RxCount); + sprintf(msg+strlen(msg),"errorsTx = %ld\n",pMbss->TxErrorCount); + sprintf(msg+strlen(msg),"errorsRx = %ld\n",pMbss->RxErrorCount); + sprintf(msg+strlen(msg),"discardPktsTx = %ld\n",pMbss->TxDropCount); + sprintf(msg+strlen(msg),"discardPktsRx = %ld\n",pMbss->RxDropCount); + sprintf(msg+strlen(msg),"ucPktsTx = %ld\n",pMbss->ucPktsTx); + sprintf(msg+strlen(msg),"ucPktsRx = %ld\n",pMbss->ucPktsRx); + sprintf(msg+strlen(msg),"mcPktsTx = %ld\n",pMbss->mcPktsTx); + sprintf(msg+strlen(msg),"mcPktsRx = %ld\n",pMbss->mcPktsRx); + sprintf(msg+strlen(msg),"bcPktsTx = %ld\n",pMbss->bcPktsTx); + sprintf(msg+strlen(msg),"bcPktsRx = %ld\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)); + } + +/* kfree(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; + + +/* 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]; + 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",pMbss->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)); + } + +/* kfree(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", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], tid)); + + pEntry = MacTableLookup(pAd, (PUCHAR) mac); + + if (pEntry) { + DBGPRINT(RT_DEBUG_OFF, ("\nTear down Ori BA Session: Tid = %d\n", tid)); + BAOriSessionTearDown(pAd, pEntry->Aid, 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", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], tid)); + + pEntry = MacTableLookup(pAd, (PUCHAR) mac); + + if (pEntry) { + DBGPRINT(RT_DEBUG_OFF, ("\nTear down Rec BA Session: Tid = %d\n", tid)); + BARecSessionTearDown(pAd, pEntry->Aid, 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)); + + return TRUE; +} + +INT Set_HtMcs_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG HtMcs, Mcs_tmp, ValidMcs = 15; +#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 */ + +#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) + { + pAd->ApCfg.MBSSID[pObj->ioctl_if].DesiredTransmitSetting.field.MCS = HtMcs; + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMcs_Proc::(HtMcs=%d) for ra%d\n", + pAd->ApCfg.MBSSID[pObj->ioctl_if].DesiredTransmitSetting.field.MCS, pObj->ioctl_if)); + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pAd->StaCfg.DesiredTransmitSetting.field.MCS = HtMcs; + pAd->StaCfg.bAutoTxRateSwitch = (HtMcs == MCS_AUTO) ? TRUE:FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMcs_Proc::(HtMcs=%d, bAutoTxRateSwitch = %d)\n", + pAd->StaCfg.DesiredTransmitSetting.field.MCS, pAd->StaCfg.bAutoTxRateSwitch)); + + if ((pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED) || + (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE < MODE_HTMIX)) + { + if ((pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) && + (HtMcs <= 3) && + (pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode == FIXED_TXMODE_CCK)) + { + RTMPSetDesiredRates(pAd, (LONG) (RateIdToMbps[HtMcs] * 1000000)); + } + else if ((pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) && + (HtMcs <= 7) && + (pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode == FIXED_TXMODE_OFDM)) + { + RTMPSetDesiredRates(pAd, (LONG) (RateIdToMbps[HtMcs+4] * 1000000)); + } + else + bAutoRate = TRUE; + + if (bAutoRate) + { + pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; + RTMPSetDesiredRates(pAd, -1); + } + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMcs_Proc::(FixedTxMode=%d)\n",pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode)); + } + if (ADHOC_ON(pAd)) + return TRUE; + } +#endif /* CONFIG_STA_SUPPORT */ + + SetCommonHT(pAd); + + 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); + if (Value == 0) + pAd->CommonCfg.BACapability.field.AmsduEnable = FALSE; + else if ( Value == 1 ) + pAd->CommonCfg.BACapability.field.AmsduEnable = TRUE; + else + return FALSE; /*Invalid argument*/ + + 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_SendPSMPAction_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_ENABLE) + 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", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], mode)); + + pEntry = MacTableLookup(pAd, mac); + + if (pEntry) { + DBGPRINT(RT_DEBUG_OFF, ("\nSendPSMPAction MIPS mode = %d\n", mode)); + SendPSMPAction(pAd, pEntry->Aid, 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)); + + 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 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( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; +#endif /* CONFIG_AP_SUPPORT */ + INT fix_tx_mode = FIXED_TXMODE_HT; + + fix_tx_mode = RT_CfgSetFixedTxPhyMode(arg); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + pAd->ApCfg.MBSSID[pObj->ioctl_if].DesiredTransmitSetting.field.FixedTxMode = fix_tx_mode; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode = fix_tx_mode; +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_FixedTxMode_Proc::(FixedTxMode=%d)\n", fix_tx_mode)); + + return TRUE; +} + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +INT Set_OpMode_Proc( + IN PRTMP_ADAPTER pAd, + IN 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 +#if defined(RT2883) || defined(RT3883) + case 0x7a: /* RXWI - next long, MSB to LSB. Decode BF SNR */ + if (decode) + DBGPRINT(RT_DEBUG_OFF, (" BF:%02d %02d %02d 0x%02X\n", + (BF_SNR_OFFSET + (CHAR)(oldTail->data[1]) + 2)/4, + (BF_SNR_OFFSET + (CHAR)(oldTail->data[2]) + 2)/4, + (BF_SNR_OFFSET + (CHAR)(oldTail->data[3]) + 2)/4, + oldTail->data[0]) ); + else + DBGPRINT(RT_DEBUG_OFF, ("Rx4 %02X%02X %02X%02X-%02X%02X %02X%02X \n", + 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; +#endif /* defined(RT2883) || defined(RT3883) */ +#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 */ + + +#if defined(RT2883) || defined(RT3883) +/* + Set_PhyRateLimit_Proc - limit max PHY rate + usage: iwpriv ra0 set PhyRateLimit= +*/ +INT Set_PhyRateLimit_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + pAd->CommonCfg.PhyRateLimit = simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s():(PhyRateLimit=%ld)\n", + __FUNCTION__, pAd->CommonCfg.PhyRateLimit)); + return TRUE; +} + +#ifdef DBG +/* + Set_FixedRate_Proc - Use fixed MCS + usage: iwpriv ra0 set PhyRateLimit= or -1 to disable + Parameter is ItemNo that is used to index into the RateSwitch table +*/ +INT Set_FixedRate_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int rate; + + rate = simple_strtol(arg, 0, 10); + if (rate<-1 || rate > MAX_TX_RATE_INDEX) + return FALSE; + pAd->CommonCfg.FixedRate = rate; + DBGPRINT(RT_DEBUG_TRACE, ("Set_FixedRate_Proc::(FixedRate=%d)\n", pAd->CommonCfg.FixedRate)); + return TRUE; +} +#endif /* DBG */ +#endif /* defined(RT2883) || defined(RT3883) */ + + +#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 */ + + +#if defined(RT305x)||defined(RT3070) +INT Set_HiPower_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + pAdapter->CommonCfg.HighPowerPatchDisabled = !(simple_strtol(arg, 0, 10)); + + if (pAdapter->CommonCfg.HighPowerPatchDisabled != 0) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R82, 0x62); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R67, 0x20); + RT30xxWriteRFRegister(pAdapter, RF_R27, 0x23); + } + return TRUE; +} +#endif /* defined(RT305x) || defined(RT3070) */ + + +#ifdef RT305x +#if defined(RT3352) || defined(RT5350) +#ifdef RTMP_INTERNAL_TX_ALC +INT Set_TSSIMaxRange_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + UINT8 range = (UINT8)simple_strtol(arg, 0, 10); + + if ((!IS_RT3352(pAdapter)) && (!IS_RT5350(pAdapter))) + { + DBGPRINT_ERR(("The chipset is neither RT3352 nor RT5350 !\n")); + return FALSE; + } + + if ((range != 0) && (range != 2) && (range != 4)) + { + DBGPRINT_ERR(("You should input 0, 2, or 4 !\n")); + return FALSE; + } + + /* one step means 0.5 dB */ + pAdapter->chipCap.TxPowerMaxCompenStep = (range << 1); + DBGPRINT(RT_DEBUG_TRACE, ("Set_TSSIMaxRange_Proc::(TxPowerMaxCompenStep=%d)\n", + pAdapter->chipCap.TxPowerMaxCompenStep)); + + return TRUE; +} +#endif /* RTMP_INTERNAL_TX_ALC */ +#endif /* defined(RT3352) || defined(RT5350) */ +#endif /* RT305x */ + + +INT Set_LongRetryLimit_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + TX_RTY_CFG_STRUC tx_rty_cfg; + UCHAR LongRetryLimit = (UCHAR)simple_strtol(arg, 0, 10); + + RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word); + tx_rty_cfg.field.LongRtyLimit = LongRetryLimit; + RTMP_IO_WRITE32(pAdapter, 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( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + TX_RTY_CFG_STRUC tx_rty_cfg; + UCHAR ShortRetryLimit = (UCHAR)simple_strtol(arg, 0, 10); + + RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word); + tx_rty_cfg.field.ShortRtyLimit = ShortRetryLimit; + RTMP_IO_WRITE32(pAdapter, 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_11Encryption2Enabled: + return "TKIP"; + case Ndis802_11Encryption3Enabled: + return "AES"; + case Ndis802_11Encryption4Enabled: + return "TKIPAES"; + default: + return "UNKNOW"; + } +} + +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_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 PHY_11BG_MIXED: + snprintf(pBuf, BufLen, "\t11B/G"); + break; + case PHY_11B: + snprintf(pBuf, BufLen, "\t11B"); + break; + case PHY_11A: + snprintf(pBuf, BufLen, "\t11A"); + break; + case PHY_11ABG_MIXED: + snprintf(pBuf, BufLen, "\t11A/B/G"); + break; + case PHY_11G: + snprintf(pBuf, BufLen, "\t11G"); + break; +#ifdef DOT11_N_SUPPORT + case PHY_11ABGN_MIXED: + snprintf(pBuf, BufLen, "\t11A/B/G/N"); + break; + case PHY_11N_2_4G: + snprintf(pBuf, BufLen, "\t11N only with 2.4G"); + break; + case PHY_11GN_MIXED: + snprintf(pBuf, BufLen, "\t11G/N"); + break; + case PHY_11AN_MIXED: + snprintf(pBuf, BufLen, "\t11A/N"); + break; + case PHY_11BGN_MIXED: + snprintf(pBuf, BufLen, "\t11B/G/N"); + break; + case PHY_11AGN_MIXED: + snprintf(pBuf, BufLen, "\t11A/G/N"); + break; + case PHY_11N_5G: + 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) +{ +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + snprintf(pBuf, BufLen, "\t%u", pAd->ApCfg.MBSSID[pObj->ioctl_if].DesiredTransmitSetting.field.MCS); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + snprintf(pBuf, BufLen, "\t%u", pAd->StaCfg.DesiredTransmitSetting.field.MCS); +#endif /* CONFIG_STA_SUPPORT */ + 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 */ + +#ifdef WMM_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].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; +} +#endif /* WMM_SUPPORT */ + +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; +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + AuthMode = pAd->ApCfg.MBSSID[pObj->ioctl_if].AuthMode; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + AuthMode = pAd->StaCfg.AuthMode; +#endif /* CONFIG_STA_SUPPORT */ + + 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) +{ + 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) + WepStatus = pAd->ApCfg.MBSSID[pObj->ioctl_if].WepStatus; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + WepStatus = pAd->StaCfg.WepStatus; +#endif /* CONFIG_STA_SUPPORT */ + + 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) +{ + UCHAR DefaultKeyId = 0; +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + DefaultKeyId = pAd->ApCfg.MBSSID[pObj->ioctl_if].DefaultKeyId; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + DefaultKeyId = pAd->StaCfg.DefaultKeyId; +#endif /* CONFIG_STA_SUPPORT */ + + snprintf(pBuf, BufLen, "\t%d", 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 */ + +#if defined (RT2883) || defined (RT3883) + sprintf(pBuf+strlen(pBuf), "FixedRate: %d\n", pAd->CommonCfg.FixedRate); +#endif // defined (RT2883) || defined (RT3883) // + +#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 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; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + + 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; + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + 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, + pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], + pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5], + 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*/ + +void getRate(HTTRANSMIT_SETTING HTSetting, ULONG* fLastTxRxRate) + +{ + 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}; + + int rate_count = sizeof(MCSMappingRateTable)/sizeof(int); + int rate_index = 0; + int value = 0; + +#ifdef DOT11_N_SUPPORT + if (HTSetting.field.MODE >= MODE_HTMIX) + { +/* rate_index = 12 + ((UCHAR)ht_setting.field.BW *16) + ((UCHAR)ht_setting.field.ShortGI *32) + ((UCHAR)ht_setting.field.MCS);*/ + rate_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) + rate_index = (UCHAR)(HTSetting.field.MCS) + 4; + else if (HTSetting.field.MODE == MODE_CCK) + rate_index = (UCHAR)(HTSetting.field.MCS); + + if (rate_index < 0) + rate_index = 0; + + if (rate_index >= rate_count) + rate_index = rate_count-1; + + value = (MCSMappingRateTable[rate_index] * 5)/10; + *fLastTxRxRate=(ULONG)value; + return; +} + + +#ifdef TXBF_SUPPORT + +/* + Set_ReadITxBf_Proc - Read Implicit BF profile and display it + iwpriv ra0 set ReadITxBf= +*/ +INT Set_ReadITxBf_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int profileNum = simple_strtol(arg, 0, 10); + int scIndex, i, maxCarriers; + + Read_TxBfProfile(pAd, &profData, profileNum, TRUE); + + /* Display profile. Note: each column is displayed as a row. This shortens the display */ + DBGPRINT(RT_DEBUG_OFF, ("---ITxBF Profile: %d - %dx%d, %dMHz\n", + profileNum, profData.rows, profData.columns, profData.fortyMHz? 40: 20)); + + maxCarriers = profData.fortyMHz? PROFILE_MAX_CARRIERS_40: PROFILE_MAX_CARRIERS_20; + + for (scIndex=0; scIndex1) { + for (i=0; i +*/ +INT Set_ReadETxBf_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int profileNum = simple_strtol(arg, 0, 10); + int scIndex, i, maxCarriers; + + Read_TxBfProfile(pAd, &profData, profileNum, FALSE); + + /* Dump ETxBF profile values. Note: each column is displayed as a row. This shortens the display */ + DBGPRINT(RT_DEBUG_OFF, ("---ETxBF Profile: %d - %dx%d, %dMHz, grp=%d\n", + profileNum, profData.rows, profData.columns, profData.fortyMHz? 40: 20, profData.grouping)); + + maxCarriers = profData.fortyMHz? PROFILE_MAX_CARRIERS_40: PROFILE_MAX_CARRIERS_20; + + for (scIndex=0; scIndex1) { + for (i=0; i2) { + for (i=0; i + Assumes profData contains a valid Implicit Profile +*/ +INT Set_WriteITxBf_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int profileNum = simple_strtol(arg, 0, 10); + + if (!profData.impProfile) + return FALSE; + + Write_TxBfProfile(pAd, &profData, profileNum); + + return TRUE; +} + + +/* + Set_WriteETxBf_Proc - Write Explicit BF matrix + usage: iwpriv ra0 set WriteETxBf= + Assumes profData contains a valid Explicit Profile +*/ +INT Set_WriteETxBf_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int profileNum = simple_strtol(arg, 0, 10); + + if (profData.impProfile) + return FALSE; + + Write_TxBfProfile(pAd, &profData, profileNum); + + return TRUE; +} + + +/* + Set_StatITxBf_Proc - Compute power of each chain in Implicit BF matrix + usage: iwpriv ra0 set StatITxBf= +*/ +INT Set_StatITxBf_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int scIndex, maxCarriers, i; + unsigned long col1Power[3] = {0,0,0}, col2Power[3] = {0,0,0}; + int profileNum = simple_strtol(arg, 0, 10); + PROFILE_DATA *pProfData; + + pProfData = (PROFILE_DATA *)kmalloc(sizeof(PROFILE_DATA), MEM_ALLOC_FLAG); + if (pProfData == NULL) + { + DBGPRINT(RT_DEBUG_OFF, ("Set_StatITxBf_Proc: kmalloc failed\n")); + return FALSE; + } + + Read_TxBfProfile(pAd, pProfData, profileNum, TRUE); + + maxCarriers = pProfData->fortyMHz? PROFILE_MAX_CARRIERS_40: PROFILE_MAX_CARRIERS_20; + + for (scIndex=0; scIndexrows; i++) { + int ival = Unpack_IBFValue(pProfData->data[scIndex], 2*i+1); + int qval = Unpack_IBFValue(pProfData->data[scIndex], 2*i); + col1Power[i] += ival*ival+qval*qval; + + if (pProfData->columns==2) { + ival = Unpack_IBFValue(pProfData->data[scIndex], 2*i+7); + qval = Unpack_IBFValue(pProfData->data[scIndex], 2*i+6); + col2Power[i] += ival*ival+qval*qval; + } + } + } + + /* Remove implied scale factor of 2^-16. Convert to thousandths */ + for (i=0; irows; i++) { + col1Power[i] >>= 12; + col1Power[i] = ((col1Power[i]*1000)/maxCarriers)>>4; + col2Power[i] >>= 12; + col2Power[i] = ((col2Power[i]*1000)/maxCarriers)>>4; + } + + /* Display stats */ + DBGPRINT(RT_DEBUG_OFF, ("ITxBF Stats:\n %dx1=[0.%03lu 0.%03lu, 0.%03lu]\n", + pProfData->rows, col1Power[0], col1Power[1], col1Power[2])); + if (pProfData->columns==2) { + DBGPRINT(RT_DEBUG_OFF, (" %dx2=[0.%03lu 0.%03lu, 0.%03lu]\n", + pProfData->rows, (col1Power[0]+col2Power[0])/2, (col1Power[1]+col2Power[1])/2, + (col1Power[2]+col2Power[2])/2) ); + } + + kfree(pProfData); + + return TRUE; +} + +/* + Set_StatETxBf_Proc - Compute power of each chain in Explicit BF matrix + usage: iwpriv ra0 set StatETxBf= +*/ +INT Set_StatETxBf_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int scIndex, maxCarriers, i; + unsigned long col1Power[3] = {0,0,0}, col2Power[3] = {0,0,0}, col3Power[3] = {0,0,0}; + int profileNum = simple_strtol(arg, 0, 10); + PROFILE_DATA *pProfData; + + pProfData = (PROFILE_DATA *)kmalloc(sizeof(PROFILE_DATA), MEM_ALLOC_FLAG); + if (pProfData == NULL) + { + DBGPRINT(RT_DEBUG_OFF, ("Set_StatETxBf_Proc: kmalloc failed\n")); + return FALSE; + } + + Read_TxBfProfile(pAd, pProfData, profileNum, FALSE); + + maxCarriers = pProfData->fortyMHz? PROFILE_MAX_CARRIERS_40: PROFILE_MAX_CARRIERS_20; + + for (scIndex=0; scIndexrows; i++) { + int ival = (CHAR)(pProfData->data[scIndex][6*i]); + int qval = (CHAR)(pProfData->data[scIndex][6*i+1]); + col1Power[i] += ival*ival+qval*qval; + + if (pProfData->columns>1) { + ival = (CHAR)(pProfData->data[scIndex][6*i+2]); + qval = (CHAR)(pProfData->data[scIndex][6*i+3]); + col2Power[i] += ival*ival+qval*qval; + } + + if (pProfData->columns>2) { + ival = (CHAR)(pProfData->data[scIndex][6*i+4]); + qval = (CHAR)(pProfData->data[scIndex][6*i+5]); + col3Power[i] += ival*ival+qval*qval; + } + } + } + + /* Remove implied scale factor of 2^-14. Convert to thousandths */ + for (i=0; irows; i++) { + col1Power[i] >>= 10; + col1Power[i] = ((col1Power[i]*1000)/maxCarriers)>>4; + col2Power[i] >>= 10; + col2Power[i] = ((col2Power[i]*1000)/maxCarriers)>>4; + col3Power[i] >>= 10; + col3Power[i] = ((col3Power[i]*1000)/maxCarriers)>>4; + } + + /* Display stats */ + DBGPRINT(RT_DEBUG_OFF, ("ETxBF Stats:\n %dx1=[0.%03lu 0.%03lu, 0.%03lu]\n", + pProfData->rows, col1Power[0], col1Power[1], col1Power[2])); + if (pProfData->columns==2) { + DBGPRINT(RT_DEBUG_OFF, (" %dx2=[0.%03lu 0.%03lu, 0.%03lu]\n", + pProfData->rows, (col1Power[0]+col2Power[0])/2, + (col1Power[1]+col2Power[1])/2, (col1Power[2]+col2Power[2])/2) ); + } + if (pProfData->columns==3) { + DBGPRINT(RT_DEBUG_OFF, (" %dx3=[0.%03lu 0.%03lu, 0.%03lu]\n", + pProfData->rows, (col1Power[0]+col2Power[0]+col3Power[0])/3, + (col1Power[1]+col2Power[1]+col3Power[1])/3, + (col1Power[2]+col2Power[2]+col3Power[2])/3) ); + } + + kfree(pProfData); + + return TRUE; +} + + +/* + Set_TxBfTag_Proc - Display BF Profile Tags + usage: "iwpriv ra0 set TxBfTag=n" + n: 0=>all, + 1=>Explicit, + 2=>Implicit, + 3=>dump Power table +*/ +INT Set_TxBfTag_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int argVal = simple_strtol(arg, 0, 10); + int profileNum; + + if (argVal==0 || argVal==1) { + /* Display Explicit tagfield */ + DBGPRINT(RT_DEBUG_OFF, ("---Explicit TxBfTag:\n")); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R179, 4); + for (profileNum=0; profileNum<4; profileNum++) + displayTagfield(pAd, profileNum, FALSE); + } + + if (argVal==0 || argVal==2) { + /* Display Implicit tagfield */ + DBGPRINT(RT_DEBUG_OFF, ("---Implicit TxBfTag:\n")); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R179, 0); + for (profileNum=0; profileNum<4; profileNum++) + displayTagfield(pAd, profileNum, TRUE); + } + + if (argVal==3) { + int i; + /* 4. Dump power table */ + for (i = 0; i < (14 + 12 + 16 + 7); i++) + DBGPRINT(RT_DEBUG_OFF, ("%d: Ch%2d=[%d, %d %d]\n", i, + pAd->TxPower[i].Channel, pAd->TxPower[i].Power, + pAd->TxPower[i].Power2, pAd->TxPower[i].Power3)); + } + + return TRUE; +} + + +/* + 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; + + /* Disable Profile Updates during access */ + 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); + + return TRUE; +} + + +/* + Set_ITxBfTimeout_Proc - Set ITxBF timeout value + usage: iwpriv ra0 set ITxBfTimeout= +*/ +INT Set_ITxBfTimeout_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG t = simple_strtol(arg, 0, 10); + + if (t > 65535) { + DBGPRINT(RT_DEBUG_ERROR, ("Set_ITxBfTimeout_Proc: value > 65535!\n")); + return FALSE; + } + + pAd->CommonCfg.ITxBfTimeout = t; + 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); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ITxBfTimeout_Proc::(ITxBfTimeout=%d)\n", (int)pAd->CommonCfg.ITxBfTimeout)); + return TRUE; +} + + +/* + Set_ETxBfTimeout_Proc - Set ITxBF timeout value + usage: iwpriv ra0 set ETxBfTimeout= +*/ +INT Set_ETxBfTimeout_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG t = simple_strtol(arg, 0, 10); + + if (t > 65535) { + DBGPRINT(RT_DEBUG_ERROR, ("Set_ETxBfTimeout_Proc: value > 65535!\n")); + return FALSE; + } + + pAd->CommonCfg.ETxBfTimeout = t; + RTMP_IO_WRITE32(pAd, TX_TXBF_CFG_3, pAd->CommonCfg.ETxBfTimeout); + DBGPRINT(RT_DEBUG_TRACE, ("Set_ETxBfTimeout_Proc::(ETxBfTimeout=%d)\n", (int)pAd->CommonCfg.ETxBfTimeout)); + 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 ITxBFDividerCalibration(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 ITxBFLNACalibration(pAd, calFunction, 0, channel<=14); +} + + +/* + Set_ITxBfCal_Proc - Calculate ITxBf Calibration parameters + usage: "iwpriv ra0 set ITxBfCal=[0 | 1]" + 0=>calculate values, 1=>update BBP and EEPROM +*/ +INT Set_ITxBfCal_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int calFunction = simple_strtol(arg, 0, 10); + int calParams[2]; + int ret; + UCHAR channel = pAd->CommonCfg.Channel; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + channel = pAd->ate.Channel; +#endif /* RALINK_ATE */ + + ret = iCalcCalibration(pAd, 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; + } + + /* Display result */ + DBGPRINT((calFunction==0? RT_DEBUG_OFF: RT_DEBUG_WARN), + ("ITxBfCal Result = [0x%02x 0x%02x]\n", calParams[0], calParams[1])); + +#ifdef RALINK_ATE + pAd->ate.calParams[0] = (UCHAR)calParams[0]; + pAd->ate.calParams[1] = (UCHAR)calParams[1]; + + /* Double check */ + DBGPRINT((calFunction==0? RT_DEBUG_OFF: RT_DEBUG_WARN), + ("ITxBfCal Result in ATE = [0x%02x 0x%02x]\n", pAd->ate.calParams[0], pAd->ate.calParams[1])); +#endif /* RALINK_ATE */ + + /* Update BBP R176 and EEPROM for Ant 0 and 2 */ + if (calFunction == 1) { + UCHAR r27Value = 0, r173Value = 0; + ITXBF_PHASE_PARAMS phaseParams; + UCHAR divPhase[2] = {0}, phaseValues[2] = {0}; + + /* Read R173 to see if Phase compensation is already enabled */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R173, &r173Value); + + /* Select Ant 0 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R27, &r27Value); + r27Value &= ~0x60; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, r27Value); + + /* Update R176 */ + if (r173Value & 0x08) { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R176, &phaseValues[0]); + phaseValues[0] += calParams[0]; + } + else + phaseValues[0] = calParams[0]; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R176, phaseValues[0]); + + /* Select Ant 2 */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, r27Value | 0x40); + + /* Update R176 */ + if (r173Value & 0x08) { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R176, &phaseValues[1]); + phaseValues[1] += calParams[1]; + } + else + phaseValues[1] = calParams[1]; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R176, phaseValues[1]); + + /* Enable TX Phase Compensation */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R173, r173Value | 0x08); + + /* Remove Divider phase */ + ITxBFDividerCalibration(pAd, 3, 0, divPhase); + phaseValues[0] -= divPhase[0]; + phaseValues[1] -= divPhase[1]; + + /* Update EEPROM */ + + ITxBFGetEEPROM(pAd, &phaseParams, 0, 0); + + /* Only allow calibration on specific channels */ + if (channel == 1) { + phaseParams.gBeg[0] = phaseValues[0]; + phaseParams.gBeg[1] = phaseValues[1]; + } + else if (channel == 14) { + phaseParams.gEnd[0] = phaseValues[0]; + phaseParams.gEnd[1] = phaseValues[1]; + } + else if (channel == 36) { + phaseParams.aLowBeg[0] = phaseValues[0]; + phaseParams.aLowBeg[1] = phaseValues[1]; + } + else if (channel == 64) { + phaseParams.aLowEnd[0] = phaseValues[0]; + phaseParams.aLowEnd[1] = phaseValues[1]; + } + else if (channel == 100) { + phaseParams.aMidBeg[0] = phaseValues[0]; + phaseParams.aMidBeg[1] = phaseValues[1]; + } + else if (channel == 128) { + phaseParams.aMidEnd[0] = phaseValues[0]; + phaseParams.aMidEnd[1] = phaseValues[1]; + } + else if (channel == 132) { + phaseParams.aHighBeg[0] = phaseValues[0]; + phaseParams.aHighBeg[1] = phaseValues[1]; + } + else if (channel == 165) { + phaseParams.aHighEnd[0] = phaseValues[0]; + phaseParams.aHighEnd[1] = phaseValues[1]; + } + else { + DBGPRINT(RT_DEBUG_OFF, + ("Invalid channel: %d\nMust calibrate channel 1, 14, 36, 64, 100, 128, 132 or 165", channel) ); + return FALSE; + } + ITxBFSetEEPROM(pAd, &phaseParams, 0, 0); + + DBGPRINT(RT_DEBUG_WARN, ("Set_ITxBfCal_Proc: Calibration Parameters updated\n")); + } + + return TRUE; +} + + +/* + 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); + rtmp_asic_set_bf(pAd); + + for (i=0; iMacTab.Content[i]; + if (!IS_ENTRY_NONE(pEntry)) + { + pEntry->eTxBfEnCond = clientSupportsETxBF(pAd, &pEntry->HTCapability.TxBFCap)? enableETxBf: 0; + pEntry->bfState = READY_FOR_SNDG0; + } + } + + + 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); + } + } + + + 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 +*/ +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) { + ITxBFLoadLNAComp(pAd); + ITxBFDividerCalibration(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; +} +#endif /* TXBF_SUPPORT */ + + +#ifdef DOT11_N_SUPPORT +void assoc_ht_info_debugshow( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR HTCapability_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 && (HTCapability_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 AdvCode(%d), BW(%d), MIMOPS(%d), GF(%d), ShortGI_20(%d), ShortGI_40(%d)\n", + pHTCap->AdvCoding, 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); + + if (Value == 1) + { + pAd->CommonCfg.bRalinkBurstMode= TRUE; + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE); + AsicEnableRalinkBurstMode(pAd); + } + else + { + pAd->CommonCfg.bRalinkBurstMode = FALSE; + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE); + AsicDisableRalinkBurstMode(pAd); + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_BurstMode_Proc ::%s\n", + (pAd->CommonCfg.bRalinkBurstMode == TRUE) ? "enabled" : "disabled")); + + return TRUE; +} +#endif /* DOT11_N_SUPPORT */ + + +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; + +} + + +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 PRTMP_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 */ + diff --git a/mt7620/src/common/cmm_loft_cal.c b/mt7620/src/common/cmm_loft_cal.c new file mode 100644 index 0000000..89e6068 --- /dev/null +++ b/mt7620/src/common/cmm_loft_cal.c @@ -0,0 +1,1202 @@ +/* + *************************************************************************** + * 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_WARN, ("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_WARN, ("\n========================================================\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_WARN, ("alc=%u, IorQ=%u, idx_final=%2x\n", alc_idx, iorq, index_final[iorq])); + DBGPRINT(RT_DEBUG_WARN, ("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_WARN, ("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_WARN, ("\n========================================================\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_WARN, ("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_WARN, ("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_WARN, ("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; /* 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, 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, 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, RF_BYPASS0, 0x0); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, MacOrg2); + RTMPusecDelay(1); + RTMP_IO_WRITE32(pAd, 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, 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, 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, RF_BYPASS0 , 0x0); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, MacOrg2); + RTMPusecDelay(1); + RTMP_IO_WRITE32(pAd, 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/mt7620/src/common/cmm_mac_pci.c b/mt7620/src/common/cmm_mac_pci.c new file mode 100644 index 0000000..005109b --- /dev/null +++ b/mt7620/src/common/cmm_mac_pci.c @@ -0,0 +1,2487 @@ +/**************************************************************************** + * 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 RESOURCE_PRE_ALLOC +VOID RTMPResetTxRxRingMemory( + IN RTMP_ADAPTER * pAd) +{ + int index, j; + PRTMP_TX_RING pTxRing; + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; +#endif /* RT_BIG_ENDIAN */ + PNDIS_PACKET pPacket; + unsigned int IrqFlags; + + + /* Free TxSwQueue Packet*/ + for (index=0; index irq_lock, IrqFlags); + pQueue = &pAd->TxSwQueue[index]; + while (pQueue->Head) + { + pEntry = RemoveHeadQueue(pQueue); + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + } + + + /* 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); + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) (pTxRing->Cell[j].AllocVa); +#endif /* RT_BIG_ENDIAN */ + pPacket = pTxRing->Cell[j].pNdisPacket; + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + /*Always assign pNdisPacket as NULL after clear*/ + pTxRing->Cell[j].pNdisPacket = NULL; + + pPacket = pTxRing->Cell[j].pNextNdisPacket; + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + /*Always assign pNextNdisPacket as NULL after clear*/ + pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif /* RT_BIG_ENDIAN */ + + } + } + + + for (index = RX_RING_SIZE - 1 ; index >= 0; index--) + { + if ((pAd->RxRing.Cell[index].DmaBuf.AllocVa) && (pAd->RxRing.Cell[index].pNdisPacket)) + { + PCI_UNMAP_SINGLE(pAd, pAd->RxRing.Cell[index].DmaBuf.AllocPa, pAd->RxRing.Cell[index].DmaBuf.AllocSize, RTMP_PCI_DMA_FROMDEVICE); + RELEASE_NDIS_PACKET(pAd, pAd->RxRing.Cell[index].pNdisPacket, NDIS_STATUS_SUCCESS); + } + } + NdisZeroMemory(pAd->RxRing.Cell, RX_RING_SIZE * sizeof(RTMP_DMACB)); + + if (pAd->FragFrame.pFragPacket) + { + RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS); + pAd->FragFrame.pFragPacket = NULL; + } + + NdisFreeSpinLock(&pAd->CmdQLock); +} + + +VOID RTMPFreeTxRxRingMemory( + IN PRTMP_ADAPTER pAd) +{ + int num; + + + DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPFreeTxRxRingMemory\n")); + + + /* Free RxDesc buffer*/ + if (pAd->RxDescRing.AllocVa) + { +#ifdef DESC_32B_SUPPORT + kfree(pAd->RxDescRing.AllocVa); +#else + RTMP_FreeDescMemory(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + pAd->RxDescRing.AllocSize, + pAd->RxDescRing.AllocVa, + pAd->RxDescRing.AllocPa); +#endif /* DESC_32B_SUPPORT */ + } + NdisZeroMemory(&pAd->RxDescRing, sizeof(RTMP_DMABUF)); + + /* Free MgmtDesc buffer*/ + if (pAd->MgmtDescRing.AllocVa) + { + RTMP_FreeDescMemory(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + pAd->MgmtDescRing.AllocSize, + pAd->MgmtDescRing.AllocVa, + pAd->MgmtDescRing.AllocPa); + } + NdisZeroMemory(&pAd->MgmtDescRing, sizeof(RTMP_DMABUF)); + + /* Free 1st TxBufSpace and TxDesc buffer*/ + 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) + { + RTMP_FreeDescMemory(((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)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<-- RTMPFreeTxRxRingMemory\n")); +} + + +NDIS_STATUS RTMPInitTxRxRingMemory + (IN RTMP_ADAPTER *pAd) +{ + INT num, index; + ULONG RingBasePaHigh; + ULONG RingBasePaLow; + PVOID RingBaseVa; + PRTMP_TX_RING pTxRing; + PRTMP_DMABUF pDmaBuf; + PNDIS_PACKET pPacket; + PTXD_STRUC pTxD; + PRXD_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; numTxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocSize); + /* Save PA & VA for further operation*/ + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxDescRing[num].AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxDescRing[num].AllocPa); + RingBaseVa = pAd->TxDescRing[num].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; + + /* linking Tx Ring Descriptor and associated buffer memory*/ + pTxRing = &pAd->TxRing[num]; + for (index = 0; index < TX_RING_SIZE; index++) + { + pTxRing->Cell[index].pNdisPacket = NULL; + pTxRing->Cell[index].pNextNdisPacket = NULL; + /* Init Tx Ring Size, Va, Pa variables*/ + pTxRing->Cell[index].AllocSize = TXD_SIZE; + pTxRing->Cell[index].AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(pTxRing->Cell[index].AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow (pTxRing->Cell[index].AllocPa, RingBasePaLow); + + /* Setup Tx Buffer size & address. only 802.11 header will store in this space*/ + pDmaBuf = &pTxRing->Cell[index].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) pTxRing->Cell[index].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, RXD_SIZE); + + 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*/ + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->MgmtDescRing.AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->MgmtDescRing.AllocPa); + RingBaseVa = pAd->MgmtDescRing.AllocVa; + NdisZeroMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize); + for (index = 0; index < MGMT_RING_SIZE; index++) + { + pAd->MgmtRing.Cell[index].pNdisPacket = NULL; + pAd->MgmtRing.Cell[index].pNextNdisPacket = NULL; + /* Init MGMT Ring Size, Va, Pa variables*/ + pAd->MgmtRing.Cell[index].AllocSize = TXD_SIZE; + pAd->MgmtRing.Cell[index].AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(pAd->MgmtRing.Cell[index].AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow (pAd->MgmtRing.Cell[index].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) pAd->MgmtRing.Cell[index].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, RXD_SIZE); + + /* no pre-allocated buffer required in MgmtRing for scatter-gather case*/ + } + + /* Initialize Rx Ring and associated buffer memory*/ + NdisZeroMemory(pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize); + DBGPRINT(RT_DEBUG_OFF, ("RX DESC %p size = %ld\n", + pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize)); + + /* Save PA & VA for further operation*/ + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->RxDescRing.AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->RxDescRing.AllocPa); + RingBaseVa = pAd->RxDescRing.AllocVa; + + /* Linking Rx Ring and associated buffer memory*/ + for (index = 0; index < RX_RING_SIZE; index++) + { + /* Init RX Ring Size, Va, Pa variables*/ + pAd->RxRing.Cell[index].AllocSize = RXD_SIZE; + pAd->RxRing.Cell[index].AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(pAd->RxRing.Cell[index].AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow (pAd->RxRing.Cell[index].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 = &pAd->RxRing.Cell[index].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 */ + pAd->RxRing.Cell[index].pNdisPacket = pPacket; + + /* Error handling*/ + 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) pAd->RxRing.Cell[index].AllocVa; + pRxD->SDP0 = RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa); + pRxD->DDONE = 0; + +#ifdef RX_DMA_SCATTER + pRxD->SDL0 = RX_BUFFER_AGGRESIZE; +#endif /* RX_DMA_SCATTER */ + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#endif + +#ifdef DESC_32B_SUPPORT + dma_cache_sync(NULL, pRxD, RXD_SIZE, DMA_TO_DEVICE); +#endif /* DESC_32B_SUPPORT */ + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pRxD, RXD_SIZE); + } + + + NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME)); + pAd->FragFrame.pFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); + + if (pAd->FragFrame.pFragPacket == NULL) + { + Status = NDIS_STATUS_RESOURCES; + } + + + /* Following code segment get from original func:NICInitTxRxRingAndBacklogQueue(), now should integrate it to here.*/ + { + DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitTxRxRingAndBacklogQueue\n")); + + + /* 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; + /*RTMP_IO_WRITE32(pAd, (TX_CTX_IDX0 + i * 0x10) , pAd->TxRing[i].TX_CTX_IDX);*/ + } + + /* Init RX Ring index pointer*/ + pAd->RxRing.RxSwReadIdx = 0; + pAd->RxRing.RxCpuIdx = RX_RING_SIZE - 1; + /*RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RX_CRX_IDX0);*/ + + + /* init MGMT ring index pointer*/ + pAd->MgmtRing.TxSwFreeIdx = 0; + pAd->MgmtRing.TxCpuIdx = 0; + + pAd->PrivateInfo.TxRingFullCnt = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitTxRxRingAndBacklogQueue\n")); + } + + 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( + IN PRTMP_ADAPTER pAd) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + INT num; + ULONG ErrorValue = 0; +/* PRTMP_REORDERBUF pReorderBuf;*/ + + 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; numTxDescRing[num].AllocSize = TX_RING_SIZE * TXD_SIZE; + RTMP_AllocateTxDescMemory( + ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + /* pAd,*/ + num, + pAd->TxDescRing[num].AllocSize, + FALSE, + &pAd->TxDescRing[num].AllocVa, + &pAd->TxDescRing[num].AllocPa); + + if (pAd->TxDescRing[num].AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + + /* + 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\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + + DBGPRINT(RT_DEBUG_TRACE, ("TxRing[%d]: total %d bytes allocated\n", num, (INT)pAd->TxDescRing[num].AllocSize)); + } + if (Status == NDIS_STATUS_RESOURCES) + break; + + + /* + Allocate MGMT ring descriptor's memory except Tx ring which allocated eariler + */ + pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * TXD_SIZE; + RTMP_AllocateMgmtDescMemory( + ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + pAd->MgmtDescRing.AllocSize, + FALSE, + &pAd->MgmtDescRing.AllocVa, + &pAd->MgmtDescRing.AllocPa); + + if (pAd->MgmtDescRing.AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d bytes allocated\n", (INT)pAd->MgmtDescRing.AllocSize)); + + + + /* + Allocate RX ring descriptor's memory except Tx ring which allocated eariler + */ + pAd->RxDescRing.AllocSize = RX_RING_SIZE * RXD_SIZE; + RTMP_AllocateRxDescMemory( + ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + pAd->RxDescRing.AllocSize, + FALSE, + &pAd->RxDescRing.AllocVa, + &pAd->RxDescRing.AllocPa); + + if (pAd->RxDescRing.AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("Rx Ring: total %d bytes allocated\n", (INT)pAd->RxDescRing.AllocSize)); + + } 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( + IN PRTMP_ADAPTER pAd) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + ULONG RingBasePaHigh; + ULONG RingBasePaLow; + PVOID RingBaseVa; + INT index, num; + PTXD_STRUC pTxD; + PRXD_STRUC pRxD; + ULONG ErrorValue = 0; + PRTMP_TX_RING pTxRing; + PRTMP_DMABUF pDmaBuf; + PNDIS_PACKET pPacket; +/* PRTMP_REORDERBUF pReorderBuf;*/ + + DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n")); + do + { + /* Init the CmdQ and CmdQLock*/ + NdisAllocateSpinLock(pAd, &pAd->CmdQLock); + NdisAcquireSpinLock(&pAd->CmdQLock); + RTInitializeCmdQ(&pAd->CmdQ); + NdisReleaseSpinLock(&pAd->CmdQLock); + + /* + 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].AllocSize = TX_RING_SIZE * TXD_SIZE; + RTMP_AllocateTxDescMemory( + ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + /* pAd,*/ + num, + pAd->TxDescRing[num].AllocSize, + FALSE, + &pAd->TxDescRing[num].AllocVa, + &pAd->TxDescRing[num].AllocPa); + + if (pAd->TxDescRing[num].AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + + /* Zero init this memory block*/ + NdisZeroMemory(pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocSize); + + /* Save PA & VA for further operation*/ + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxDescRing[num].AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxDescRing[num].AllocPa); + RingBaseVa = pAd->TxDescRing[num].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\n")); + 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++) + { + pTxRing->Cell[index].pNdisPacket = NULL; + pTxRing->Cell[index].pNextNdisPacket = NULL; + /* Init Tx Ring Size, Va, Pa variables*/ + pTxRing->Cell[index].AllocSize = TXD_SIZE; + pTxRing->Cell[index].AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(pTxRing->Cell[index].AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow (pTxRing->Cell[index].AllocPa, RingBasePaLow); + + /* Setup Tx Buffer size & address. only 802.11 header will store in this space*/ + pDmaBuf = &pTxRing->Cell[index].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) pTxRing->Cell[index].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, RXD_SIZE); + + 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 + */ + pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * TXD_SIZE; + RTMP_AllocateMgmtDescMemory( + ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + pAd->MgmtDescRing.AllocSize, + FALSE, + &pAd->MgmtDescRing.AllocVa, + &pAd->MgmtDescRing.AllocPa); + + if (pAd->MgmtDescRing.AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + + /* Zero init this memory block*/ + NdisZeroMemory(pAd->MgmtDescRing.AllocVa, 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++) + { + pAd->MgmtRing.Cell[index].pNdisPacket = NULL; + pAd->MgmtRing.Cell[index].pNextNdisPacket = NULL; + /* Init MGMT Ring Size, Va, Pa variables*/ + pAd->MgmtRing.Cell[index].AllocSize = TXD_SIZE; + pAd->MgmtRing.Cell[index].AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(pAd->MgmtRing.Cell[index].AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow (pAd->MgmtRing.Cell[index].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) pAd->MgmtRing.Cell[index].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, RXD_SIZE); + + /* no pre-allocated buffer required in MgmtRing for scatter-gather case*/ + } + DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d entry allocated\n", index)); + + /* + Allocate RX ring descriptor's memory except Tx ring which allocated eariler + */ + pAd->RxDescRing.AllocSize = RX_RING_SIZE * RXD_SIZE; + RTMP_AllocateRxDescMemory( + ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + pAd->RxDescRing.AllocSize, + FALSE, + &pAd->RxDescRing.AllocVa, + &pAd->RxDescRing.AllocPa); + + if (pAd->RxDescRing.AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + + /* Zero init this memory block*/ + NdisZeroMemory(pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize); + + + DBGPRINT(RT_DEBUG_OFF, + ("RX DESC %p size = %ld\n", pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize)); + + /* Save PA & VA for further operation*/ + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->RxDescRing.AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->RxDescRing.AllocPa); + RingBaseVa = pAd->RxDescRing.AllocVa; + + + /* Initialize Rx Ring and associated buffer memory*/ + + for (index = 0; index < RX_RING_SIZE; index++) + { + /* Init RX Ring Size, Va, Pa variables*/ + pAd->RxRing.Cell[index].AllocSize = RXD_SIZE; + pAd->RxRing.Cell[index].AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(pAd->RxRing.Cell[index].AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow (pAd->RxRing.Cell[index].AllocPa, RingBasePaLow); + + /*NdisZeroMemory(RingBaseVa, RXD_SIZE);*/ + + /* Offset to next ring descriptor address*/ + RingBasePaLow += RXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + RXD_SIZE; + + /* Setup Rx associated Buffer size & allocate share memory*/ + pDmaBuf = &pAd->RxRing.Cell[index].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 */ + pAd->RxRing.Cell[index].pNdisPacket = pPacket; + + /* Error handling*/ + 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) pAd->RxRing.Cell[index].AllocVa; + pRxD->SDP0 = RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa); + pRxD->DDONE = 0; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#endif + +#ifdef DESC_32B_SUPPORT + dma_cache_sync(NULL, pRxD, RXD_SIZE, DMA_TO_DEVICE); +#endif /* DESC_32B_SUPPORT */ + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pRxD, RXD_SIZE); + } + + DBGPRINT(RT_DEBUG_TRACE, ("Rx Ring: total %d entry allocated\n", 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); + } + + /* Following code segment get from original func:NICInitTxRxRingAndBacklogQueue(), now should integrate it to here.*/ + { + DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitTxRxRingAndBacklogQueue\n")); + + + /* 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; + /*RTMP_IO_WRITE32(pAd, (TX_CTX_IDX0 + i * 0x10) , pAd->TxRing[i].TX_CTX_IDX);*/ + } + + /* Init RX Ring index pointer*/ + pAd->RxRing.RxSwReadIdx = 0; + pAd->RxRing.RxCpuIdx = RX_RING_SIZE - 1; + /*RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RX_CRX_IDX0);*/ + + + /* init MGMT ring index pointer*/ + pAd->MgmtRing.TxSwFreeIdx = 0; + pAd->MgmtRing.TxCpuIdx = 0; + + pAd->PrivateInfo.TxRingFullCnt = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitTxRxRingAndBacklogQueue\n")); + } + + DBGPRINT_S(Status, ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status)); + return Status; +} + + + + +VOID RTMPFreeTxRxRingMemory( + IN PRTMP_ADAPTER pAd) +{ + int index, num , j; + PRTMP_TX_RING pTxRing; + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; +#endif /* RT_BIG_ENDIAN */ + PNDIS_PACKET pPacket; + unsigned int IrqFlags; + + /*POS_COOKIE pObj =(POS_COOKIE) pAd->OS_Cookie;*/ + + DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPFreeTxRxRingMemory\n")); + + /* Free TxSwQueue Packet*/ + for (index=0; index irq_lock, IrqFlags); + pQueue = &pAd->TxSwQueue[index]; + while (pQueue->Head) + { + pEntry = RemoveHeadQueue(pQueue); + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + } + + /* 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); + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (PTXD_STRUC) (pTxRing->Cell[j].AllocVa); +#endif /* RT_BIG_ENDIAN */ + pPacket = pTxRing->Cell[j].pNdisPacket; + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + /*Always assign pNdisPacket as NULL after clear*/ + pTxRing->Cell[j].pNdisPacket = NULL; + + pPacket = pTxRing->Cell[j].pNextNdisPacket; + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + /*Always assign pNextNdisPacket as NULL after clear*/ + pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif /* RT_BIG_ENDIAN */ + } + } + + { + PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing; + NdisAcquireSpinLock(&pAd->MgmtRingLock); + + RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx); + while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->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 + pTxD->DMADONE = 0; + pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket; + + if (pPacket == NULL) + { + INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE); + continue; + } + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL; + + pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket; + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL; + 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); + } + + for (index = RX_RING_SIZE - 1 ; index >= 0; index--) + { + if ((pAd->RxRing.Cell[index].DmaBuf.AllocVa) && (pAd->RxRing.Cell[index].pNdisPacket)) + { + PCI_UNMAP_SINGLE(pAd, pAd->RxRing.Cell[index].DmaBuf.AllocPa, pAd->RxRing.Cell[index].DmaBuf.AllocSize, RTMP_PCI_DMA_FROMDEVICE); + RELEASE_NDIS_PACKET(pAd, pAd->RxRing.Cell[index].pNdisPacket, NDIS_STATUS_SUCCESS); + } + } + NdisZeroMemory(pAd->RxRing.Cell, RX_RING_SIZE * sizeof(RTMP_DMACB)); + + if (pAd->RxDescRing.AllocVa) + { +#ifdef DESC_32B_SUPPORT + kfree(pAd->RxDescRing.AllocVa); +#else + RTMP_FreeDescMemory(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, pAd->RxDescRing.AllocSize, pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocPa); +#endif /* DESC_32B_SUPPORT */ + } + NdisZeroMemory(&pAd->RxDescRing, sizeof(RTMP_DMABUF)); + + if (pAd->MgmtDescRing.AllocVa) + { + RTMP_FreeDescMemory(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, pAd->MgmtDescRing.AllocSize, pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocPa); + } + NdisZeroMemory(&pAd->MgmtDescRing, sizeof(RTMP_DMABUF)); + + 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) + { + RTMP_FreeDescMemory(((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); + + NdisFreeSpinLock(&pAd->CmdQLock); + + DBGPRINT(RT_DEBUG_TRACE, ("<-- RTMPFreeTxRxRingMemory\n")); +} + +#endif /* RESOURCE_PRE_ALLOC */ + + +/* + ======================================================================== + + 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( + IN PRTMP_ADAPTER pAd, + IN UCHAR RingType) +{ + PTXD_STRUC pTxD; + PRXD_STRUC pRxD; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; + PRXD_STRUC pDestRxD; + RXD_STRUC RxD; +#endif /* RT_BIG_ENDIAN */ + PQUEUE_ENTRY pEntry; + PNDIS_PACKET pPacket; + int i; + PRTMP_TX_RING pTxRing; + unsigned long IrqFlags; + /*UINT32 RxSwReadIdx;*/ + + + 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); + /* We have to clean all descriptors in case some error happened with reset*/ + for (i=0; iCell[i].AllocVa; + + pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNdisPacket; + /* release scatter-and-gather NDIS_PACKET*/ + if (pPacket) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + pTxRing->Cell[i].pNdisPacket = NULL; + } + + pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNextNdisPacket; + /* release scatter-and-gather NDIS_PACKET*/ + if (pPacket) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + pTxRing->Cell[i].pNextNdisPacket = NULL; + } + } + + RTMP_IO_READ32(pAd, TX_DTX_IDX0 + RingType * 0x10, &pTxRing->TxDmaIdx); + pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx; + pTxRing->TxCpuIdx = pTxRing->TxDmaIdx; + RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + RingType * 0x10, pTxRing->TxCpuIdx); + + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + while (pAd->TxSwQueue[RingType].Head != NULL) + { + pEntry = RemoveHeadQueue(&pAd->TxSwQueue[RingType]); + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); + 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: + /* We have to clean all descriptors in case some error happened with reset*/ + NdisAcquireSpinLock(&pAd->MgmtRingLock); + + 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) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + pAd->MgmtRing.Cell[i].pNdisPacket = NULL; + + pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNextNdisPacket; + /* release scatter-and-gather NDIS_PACKET*/ + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + pAd->MgmtRing.Cell[i].pNextNdisPacket = NULL; + +#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, TX_MGMTDTX_IDX, &pAd->MgmtRing.TxDmaIdx); + pAd->MgmtRing.TxSwFreeIdx = pAd->MgmtRing.TxDmaIdx; + pAd->MgmtRing.TxCpuIdx = pAd->MgmtRing.TxDmaIdx; + RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); + + NdisReleaseSpinLock(&pAd->MgmtRingLock); + pAd->RalinkCounters.MgmtRingFullCount = 0; + break; + + case QID_RX: + /* We have to clean all descriptors in case some error happened with reset*/ + NdisAcquireSpinLock(&pAd->RxRingLock); + + for (i=0; iRxRing.Cell[i].AllocVa; + RxD = *pDestRxD; + pRxD = &RxD; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + /* Point to Rx indexed rx ring descriptor*/ + pRxD = (PRXD_STRUC) pAd->RxRing.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, RX_DRX_IDX, &pAd->RxRing.RxDmaIdx); + pAd->RxRing.RxSwReadIdx = pAd->RxRing.RxDmaIdx; + pAd->RxRing.RxCpuIdx = ((pAd->RxRing.RxDmaIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxDmaIdx-1)); + RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); + + NdisReleaseSpinLock(&pAd->RxRingLock); + break; + + default: + break; + } +} + + +/*************************************************************************** + * + * register related procedures. + * + **************************************************************************/ +/* +======================================================================== +Routine Description: + Disable DMA. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RT28XXDMADisable( + IN 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( + IN RTMP_ADAPTER *pAd) +{ + WPDMA_GLO_CFG_STRUC GloCfg; + int i = 0; + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4); + do + { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) + break; + + DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy\n")); + RTMPusecDelay(1000); + i++; + }while ( i <200); + + RTMPusecDelay(50); + + GloCfg.field.EnTXWriteBackDDONE = 1; + GloCfg.field.WPDMABurstSIZE = pAd->chipCap.WPDMABurstSIZE; + GloCfg.field.EnableRxDMA = 1; + GloCfg.field.EnableTxDMA = 1; + + DBGPRINT(RT_DEBUG_TRACE, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word)); + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); + +} + + +BOOLEAN AsicCheckCommanOk( + IN PRTMP_ADAPTER pAd, + IN UCHAR Command) +{ + UINT32 CmdStatus = 0, CID = 0, i; + UINT32 ThisCIDMask = 0; +#ifdef SPECIFIC_BCN_BUF_SUPPORT + ULONG IrqFlags = 0; + + 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 MESH_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_MESH) + { + bcn_idx = apidx - MIN_NET_DEVICE_FOR_MESH; + CapInfoPos = pAd->MeshTab.CapabilityInfoLocationInBeacon; + bBcnReq = MESH_ON(pAd); + + ptr_capinfo = (PUCHAR)&pAd->MeshTab.BeaconBuf[CapInfoPos]; + ptr_update = (PUCHAR)&pAd->MeshTab.BeaconBuf[UpdatePos]; + } + else +#endif /* MESH_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + if (apidx < pAd->ApCfg.BssidNum && + apidx < HW_BEACON_MAX_NUM && +#ifdef P2P_SUPPORT + P2P_GO_ON(pAd) +#else + (pAd->OpMode == OPMODE_AP) +#endif /* P2P_SUPPORT */ + ) + { + 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*/ + 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 ++; + } + } + } +} + + +#ifdef CONFIG_STA_SUPPORT +VOID RT28xxPciStaAsicForceWakeup( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromTx) +{ + AUTO_WAKEUP_STRUC AutoWakeupCfg; + + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + return; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW)) + { + DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n")); + 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 + { + /* end johnli*/ + /* 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)) + { + /* Must using 40MHz.*/ + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + } + else + { + /* Must using 20MHz.*/ + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + } + } + } + } + else +#endif /* PCIE_PS_SUPPORT */ + { + /* PCI, 2860-PCIe*/ + DBGPRINT(RT_DEBUG_TRACE, ("<==RT28xxPciStaAsicForceWakeup::Original PCI Power Saving\n")); + 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 PRTMP_ADAPTER pAd, + IN USHORT TbttNumToNextWakeUp) +{ +#ifdef PCIE_PS_SUPPORT + BOOLEAN brc; +#endif /* PCIE_PS_SUPPORT */ + + if (pAd->StaCfg.bRadio == FALSE) + { + 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; + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW)) + { + DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n")); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + return; + } + + 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 */ + { + AUTO_WAKEUP_STRUC AutoWakeupCfg; + /* we have decided to SLEEP, so at least do it for a BEACON period. */ + if (TbttNumToNextWakeUp == 0) + TbttNumToNextWakeUp = 1; + + /*RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt);*/ + + 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)); + } + +} + +#ifdef PCIE_PS_SUPPORT +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); + if (pAd->Mlme.bPsPollTimerRunning) + { + RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); + } + pAd->Mlme.bPsPollTimerRunning = FALSE; + RTMP_INT_UNLOCK(&pAd->irq_lock, flags); + +} + + +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) + { + 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.*/ + AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02, FALSE); + /* 2-1. wait command ok.*/ + AsicCheckCommanOk(pAd, PowerWakeCID); + + /* When PCI clock is off, don't want to service interrupt. So when back to clock on, enable interrupt.*/ + /*RTMP_IO_WRITE32(pAd, INT_MASK_CSR, (DELAYINTMASK|RxINT));*/ + 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)) + { + /* Must using 40MHz.*/ + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + } + else + { + /* Must using 20MHz.*/ + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.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) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); + } + } + 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( + IN PRTMP_ADAPTER pAd, + IN UCHAR Level) +{ + /*WPDMA_GLO_CFG_STRUC DmaCfg;*/ +#ifdef CONFIG_STA_SUPPORT +#ifdef PCIE_PS_SUPPORT + BOOLEAN Cancelled; +#endif /* PCIE_PS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + /*UINT32 MACValue;*/ + + 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 + /* end johnli*/ +#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) + { + if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) + { + /* Must using 40MHz.*/ + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + } + else + { + /* Must using 20MHz.*/ + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.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 PRTMP_ADAPTER pAd, + IN UCHAR Level, + IN USHORT TbttNumToNextWakeUp) +{ +#ifdef CONFIG_STA_SUPPORT + WPDMA_GLO_CFG_STRUC DmaCfg; + UCHAR i, tempBBP_R3 = 0; +#ifdef PCIE_PS_SUPPORT + 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(RT2860) + BOOLEAN brc = FALSE; +#endif /* defined(CONFIG_STA_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.RxCpuIdx, pAd->RxRing.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, RX_DRX_IDX , &RxDmaIdx); + RTMP_IO_READ32(pAd, RX_CRX_IDX , &RxCpuIdx); + if ((RxDmaIdx > RxCpuIdx) && ((RxDmaIdx - RxCpuIdx) > RX_RING_SIZE/3)) + { + DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return1. RxDmaIdx = %d , RxCpuIdx = %d. \n", RxDmaIdx, RxCpuIdx)); + return FALSE; + } + else if ((RxCpuIdx >= RxDmaIdx) && ((RxCpuIdx - RxDmaIdx) < RX_RING_SIZE/3)) + { + DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return2. RxCpuIdx = %d. RxDmaIdx = %d , \n", RxCpuIdx, RxDmaIdx)); + 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) + { + tempBBP_R3 = (pAd->StaCfg.BBPR3 & 0xE7); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, tempBBP_R3); + } +#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)) + { + /* Must using 40MHz.*/ + AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel); + } + else + { + /* Must using 20MHz.*/ + AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel); + } + + if (Level != RTMP_HALT) + { + /* 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, RX_CRX_IDX, pAd->RxRing.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 RT2860 + /* in rt3xxx, after issue SLEEP command, can't read/write register. So don't check Command ok.*/ + if ((pAd->DeviceID == NIC2860_PCIe_DEVICE_ID) + ||(pAd->DeviceID == NIC2790_PCIe_DEVICE_ID)) + { + /* 2-1. Wait command success*/ + /* Status = 1 : success, Status = 2, already sleep, Status = 3, Maybe MAC is busy so can't finish this task.*/ + brc = AsicCheckCommanOk(pAd, PowerSafeCID); + + /* 3. After 0x30 command is ok, send radio off command. lowbyte = 0 for power safe.*/ + /* If 0x30 command is not ok this time, we can ignore 0x35 command. It will make sure not cause firmware'r problem.*/ + if ((Level == DOT11POWERSAVE) && (brc == TRUE)) + { + AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 0, 0x00, FALSE); /* lowbyte = 0 means to do power safe, NOT turn off radio.*/ + /* 3-1. Wait command success*/ + AsicCheckCommanOk(pAd, PowerRadioOffCID); + } + else if (brc == TRUE) + { + AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 1, 0x00, FALSE); /* lowbyte = 0 means to do power safe, NOT turn off radio.*/ + /* 3-1. Wait command success*/ + AsicCheckCommanOk(pAd, PowerRadioOffCID); + } + } +#endif /* RT2860 */ + +#ifdef CONFIG_STA_SUPPORT + /* 1. Wait DMA not busy*/ + i = 0; + do + { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); + if ((DmaCfg.field.RxDMABusy == 0) && (DmaCfg.field.TxDMABusy == 0)) + break; + RTMPusecDelay(20); + i++; + }while(i < 50); + + /* + if (i >= 50) + { + pAd->CheckDmaBusyCount++; + DBGPRINT(RT_DEBUG_TRACE, ("DMA Rx keeps busy. return on AsicRadioOff () CheckDmaBusyCount = %d \n", pAd->CheckDmaBusyCount)); + } + else + { + pAd->CheckDmaBusyCount = 0; + } + */ +#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( + IN PRTMP_ADAPTER pAd) +{ + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + + DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __FUNCTION__)); + + 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); + +#ifdef RTMP_RBUS_SUPPORT + if (pAd->infType == RTMP_DEV_INF_RBUS) + NICResetFromError(pAd); +#endif /* RTMP_RBUS_SUPPORT */ +#ifdef RTMP_PCI_SUPPORT + 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( + IN PRTMP_ADAPTER pAd) +{ +#ifdef RTMP_PCI_SUPPORT + BOOLEAN brc=TRUE; +#endif /* RTMP_PCI_SUPPORT */ + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + + DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __FUNCTION__)); + + /* Set Radio off flag*/ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + +#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 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).*/ +#ifdef RTMP_PCI_SUPPORT + 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); + } + } +#endif /* RTMP_PCI_SUPPORT */ + +#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 */ + + + /* 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); + + /* + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); + return; + } + */ + } +#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 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 */ +#ifdef RTMP_PCI_SUPPORT + if (pAd->infType == RTMP_DEV_INF_PCI || pAd->infType == RTMP_DEV_INF_PCIE) +{ + brc=RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0); + if (brc==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) + { + int i; + WPDMA_GLO_CFG_STRUC GloCfg; + UINT32 macStatus = 0, MTxCycle = 0; + + /* 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); + + // Check MAC Tx/Rx idle + for (MTxCycle = 0; MTxCycle < 20000; MTxCycle++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &macStatus); + if (macStatus & 0x3) + RTMPusecDelay(100); + else + break; + } + + if (MTxCycle == 20000) + { + DBGPRINT(RT_DEBUG_ERROR, ("Polling Mac Status to MAX !!!\n")); + } + + /* 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); + + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + /* Must using 40MHz.*/ + AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel); + } + else + { + /* Must using 20MHz.*/ + AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel); + } + + /* Waiting for DMA idle*/ + i = 0; + do + { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) + break; + + RTMPusecDelay(1000); + }while (i++ < 100); +} +#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 PRTMP_ADAPTER pAd, + IN VOID *ptr, + IN size_t size, + IN int sd_idx, + IN int direction) +{ + if (sd_idx == 1) + { + PTX_BLK pTxBlk; + pTxBlk = (PTX_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); +} + +#endif /* RTMP_MAC_PCI */ + diff --git a/mt7620/src/common/cmm_mat.c b/mt7620/src/common/cmm_mat.c new file mode 100644 index 0000000..4de23e8 --- /dev/null +++ b/mt7620/src/common/cmm_mat.c @@ -0,0 +1,497 @@ +/* + *************************************************************************** + * 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); +#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].CurrentAddress[0]; + } + } +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef ETH_CONVERT_SUPPORT +#ifdef P2P_SUPPORT + if (OpMode == OPMODE_STA) + pMacAddr = &pAd->CurrentAddress[0]; +#ifdef APCLI_SUPPORT + else + pMacAddr = &pAd->ApCfg.ApCliTab[ifIdx].CurrentAddress[0]; +#endif /* APCLI_SUPPORT */ +#else + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pMacAddr = &pAd->CurrentAddress[0]; +#endif /* P2P_SUPPORT */ +#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].dev)) + 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) + { +#ifdef MESH_SUPPORT +/* if (MESH_ON(pAd) && net_dev->priv_flags == INT_MESH) */ + if (MESH_ON(pAd) && (RtmpOsNetPrivGet(net_dev) == INT_MESH)) + return FALSE; +#endif /* MESH_SUPPORT */ +#ifdef P2P_SUPPORT + if (P2P_INF_ON(pAd) && (RtmpOsNetPrivGet(net_dev) == INT_P2P)) + return FALSE; +#endif /* P2P_SUPPORT */ + + 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; + + /* 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 + + pAd->MatCfg.status = MAT_ENGINE_STAT_EXITED; + + 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/mt7620/src/common/cmm_mat_iparp.c b/mt7620/src/common/cmm_mat_iparp.c new file mode 100644 index 0000000..119169c --- /dev/null +++ b/mt7620/src/common/cmm_mat_iparp.c @@ -0,0 +1,796 @@ +/* + *************************************************************************** + * 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; + + 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; + PUCHAR pPktHdr; + PNDIS_PACKET newSkb = NULL; + + pPktHdr = GET_OS_PKT_DATAPTR(pSkb); + + 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); + + pEntry = &pAd->MacTab.Content[wcid]; + pReptEntry = &pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].RepeaterCli[pEntry->MatchReptCliIdx]; + + if (pEntry->bReptCli) + { + PUCHAR pPktHdr, pLayerHdr; + + 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, dhcpHdr, pCliHwAddr; + /*REPEATER_CLIENT_ENTRY *pReptEntry = NULL;*/ + + bootpHdr = pUdpHdr + 8; + dhcpHdr = bootpHdr + 236; + pCliHwAddr = (bootpHdr+28); + if (pReptEntry) + NdisMoveMemory(pCliHwAddr, pReptEntry->OriginalAddress, MAC_ADDR_LEN); + else + { + DBGPRINT(RT_DEBUG_OFF, ("%s() MatchAPCLITabIdx = %u\n", __FUNCTION__, pEntry->MatchAPCLITabIdx)); + } + 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; + + 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; + + 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) + { + 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 NULL; +} + + +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/mt7620/src/common/cmm_mat_ipv6.c b/mt7620/src/common/cmm_mat_ipv6.c new file mode 100644 index 0000000..3782e47 --- /dev/null +++ b/mt7620/src/common/cmm_mat_ipv6.c @@ -0,0 +1,828 @@ +/* + *************************************************************************** + * 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, pSrcIP; + 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; + pSrcIP = (UCHAR *)&pIPv6Hdr->srcAddr; + + + + 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/mt7620/src/common/cmm_mat_pppoe.c b/mt7620/src/common/cmm_mat_pppoe.c new file mode 100644 index 0000000..568e944 --- /dev/null +++ b/mt7620/src/common/cmm_mat_pppoe.c @@ -0,0 +1,1070 @@ +/* + *************************************************************************** + * 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, pCliMac= 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; + pCliMac = (PUCHAR)(GET_OS_PKT_DATAPTR(pSkb)); + 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/mt7620/src/common/cmm_profile.c b/mt7620/src/common/cmm_profile.c new file mode 100644 index 0000000..32c51dc --- /dev/null +++ b/mt7620/src/common/cmm_profile.c @@ -0,0 +1,5777 @@ +/**************************************************************************** + * 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); + +} + + +/* we assume the s1 and s2 both are strings.*/ +BOOLEAN rtstrcasecmp(PSTRING s1, PSTRING s2) +{ + PSTRING p1 = s1, p2 = s2; + + if (strlen(s1) != strlen(s2)) + return FALSE; + + while(*p1 != '\0') + { + if((*p1 != *p2) && ((*p1 ^ *p2) != 0x20)) + 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, keyLen; + + + keyLen = strlen(key); + 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].DefaultKeyId = (UCHAR) (KeyIdx - 1 ); + else + pAd->ApCfg.MBSSID[i].DefaultKeyId = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) DefaultKeyID(0~3)=%d\n", i, pAd->ApCfg.MBSSID[i].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.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; + 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), "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]; + /*UCHAR keyMaterial[40];*/ + PAPCLI_STRUCT pApCliEntry = NULL; + ULONG KeyIdx; + STRING tok_str[16]; + ULONG KeyType[MAX_APCLI_NUM]; + ULONG KeyLen; + /*UCHAR CipherAlg = CIPHER_WEP64;*/ + BOOLEAN bSSIDxIsUsed = FALSE; + BOOLEAN bWPAPSKxIsUsed = FALSE; + BOOLEAN bKeyxStryIsUsed = FALSE; + + 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)); + } + } + + /*ApCliSsid*/ + for (i = 0; i < MAX_APCLI_NUM; i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + + snprintf(tok_str, sizeof(tok_str), "ApCliSsid%d", i + 1); + if(RTMPGetKeyParameter(tok_str, tmpbuf, 33, buffer, FALSE)) + { + /*Ssid acceptable strlen must be less than 32 and bigger than 0.*/ + pApCliEntry->CfgSsidLen = (UCHAR)strlen(tmpbuf); + + if (pApCliEntry->CfgSsidLen > 32) + { + NdisZeroMemory(&(pApCliEntry->CfgSsid), MAX_LEN_OF_SSID); + pApCliEntry->CfgSsidLen = 0; + continue; + } + + if(pApCliEntry->CfgSsidLen > 0) + { + memcpy(&pApCliEntry->CfgSsid, tmpbuf, pApCliEntry->CfgSsidLen); + pApCliEntry->Valid = FALSE;/* it should be set when successfuley association*/ + } + else + { + NdisZeroMemory(&(pApCliEntry->CfgSsid), MAX_LEN_OF_SSID); + continue; + } + + if (bSSIDxIsUsed == FALSE) + { + bSSIDxIsUsed = TRUE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("ApCliEntry[%d].CfgSsidLen=%d, CfgSsid=%s\n", i, pApCliEntry->CfgSsidLen, pApCliEntry->CfgSsid)); + } + } + + if (bSSIDxIsUsed == FALSE) + { + 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]; + + 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, ETH_LENGTH_OF_ADDRESS); + 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]; + + if ((strncmp(macptr, "WEPAUTO", 7) == 0) || (strncmp(macptr, "wepauto", 7) == 0)) + pApCliEntry->AuthMode = Ndis802_11AuthModeAutoSwitch; + else if ((strncmp(macptr, "SHARED", 6) == 0) || (strncmp(macptr, "shared", 6) == 0)) + pApCliEntry->AuthMode = Ndis802_11AuthModeShared; + else if ((strncmp(macptr, "WPAPSK", 6) == 0) || (strncmp(macptr, "wpapsk", 6) == 0)) + pApCliEntry->AuthMode = Ndis802_11AuthModeWPAPSK; + else if ((strncmp(macptr, "WPA2PSK", 7) == 0) || (strncmp(macptr, "wpa2psk", 7) == 0)) + pApCliEntry->AuthMode = Ndis802_11AuthModeWPA2PSK; + else + pApCliEntry->AuthMode = Ndis802_11AuthModeOpen; + + /*pApCliEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;*/ + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) ApCli_AuthMode=%d \n", i, pApCliEntry->AuthMode)); + RTMPMakeRSNIE(pAd, pApCliEntry->AuthMode, pApCliEntry->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]; + + pApCliEntry->WepStatus = Ndis802_11WEPDisabled; + if ((strncmp(macptr, "WEP", 3) == 0) || (strncmp(macptr, "wep", 3) == 0)) + { + if (pApCliEntry->AuthMode < Ndis802_11AuthModeWPA) + pApCliEntry->WepStatus = Ndis802_11WEPEnabled; + } + else if ((strncmp(macptr, "TKIP", 4) == 0) || (strncmp(macptr, "tkip", 4) == 0)) + { + if (pApCliEntry->AuthMode >= Ndis802_11AuthModeWPA) + pApCliEntry->WepStatus = Ndis802_11Encryption2Enabled; + } + else if ((strncmp(macptr, "AES", 3) == 0) || (strncmp(macptr, "aes", 3) == 0)) + { + if (pApCliEntry->AuthMode >= Ndis802_11AuthModeWPA) + pApCliEntry->WepStatus = Ndis802_11Encryption3Enabled; + } + else + { + pApCliEntry->WepStatus = Ndis802_11WEPDisabled; + } + + pApCliEntry->PairCipher = pApCliEntry->WepStatus; + pApCliEntry->GroupCipher = pApCliEntry->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, pApCliEntry->WepStatus)); + RTMPMakeRSNIE(pAd, pApCliEntry->AuthMode, pApCliEntry->WepStatus, (i + MIN_NET_DEVICE_FOR_APCLI)); + } + + } + + for (i = 0; i < MAX_APCLI_NUM; i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + + snprintf(tok_str, sizeof(tok_str), "ApCliWPAPSK%d", i + 1); + + if(RTMPGetKeyParameter(tok_str, tmpbuf, 65, buffer, FALSE)) + { + int retval = TRUE; + + if((strlen(tmpbuf) < 8) || (strlen(tmpbuf) > 64)) + { + DBGPRINT(RT_DEBUG_ERROR, ("APCli_WPAPSK_KEY, key string required 8 ~ 64 characters!!!\n")); + continue; + } + + NdisMoveMemory(pApCliEntry->PSK, tmpbuf, strlen(tmpbuf)); + pApCliEntry->PSKLen = strlen(tmpbuf); + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) APCli_WPAPSK_KEY=%s, Len=%d\n", i, pApCliEntry->PSK, pApCliEntry->PSKLen)); + + if ((pApCliEntry->AuthMode != Ndis802_11AuthModeWPAPSK) && + (pApCliEntry->AuthMode != Ndis802_11AuthModeWPA2PSK)) + { + retval = FALSE; + } + + retval = RT_CfgSetWPAPSKKey(pAd, tmpbuf, strlen(tmpbuf), (PUCHAR)pApCliEntry->CfgSsid, (INT)pApCliEntry->CfgSsidLen, pApCliEntry->PMK); + + if (retval == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Start AP-client WPAPSK state machine \n")); + } + +#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 + + if (bWPAPSKxIsUsed == FALSE) + { + bWPAPSKxIsUsed = TRUE; + } + } + } + + if (bWPAPSKxIsUsed == FALSE) + { + if (RTMPGetKeyParameter("ApCliWPAPSK", tmpbuf, 255, buffer, FALSE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + int retval = TRUE; + + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + + 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); + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) APCli_WPAPSK_KEY=%s, Len=%d\n", i, pApCliEntry->PSK, pApCliEntry->PSKLen)); + + if ((pApCliEntry->AuthMode != Ndis802_11AuthModeWPAPSK) && + (pApCliEntry->AuthMode != Ndis802_11AuthModeWPA2PSK)) + { + retval = FALSE; + } + retval = RT_CfgSetWPAPSKKey(pAd, macptr, strlen(macptr), (PUCHAR)pApCliEntry->CfgSsid, (INT)pApCliEntry->CfgSsidLen, pApCliEntry->PMK); + + if (retval == TRUE) + { + /* Start STA supplicant WPA state machine*/ + DBGPRINT(RT_DEBUG_TRACE, ("Start AP-client WPAPSK state machine \n")); + /*pApCliEntry->WpaState = SS_START; */ + } + + /*RTMPMakeRSNIE(pAd, pApCliEntry->AuthMode, pApCliEntry->WepStatus, (i + MIN_NET_DEVICE_FOR_APCLI)); */ +#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 + } + } + } + + + /*ApCliDefaultKeyID*/ + if (RTMPGetKeyParameter("ApCliDefaultKeyID", tmpbuf, 255, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + + KeyIdx = simple_strtol(macptr, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + pApCliEntry->DefaultKeyId = (UCHAR) (KeyIdx - 1); + else + pApCliEntry->DefaultKeyId = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) DefaultKeyID(0~3)=%d\n", i, pApCliEntry->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); + } + + for (i = 0; i < MAX_APCLI_NUM; i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + + snprintf(tok_str, sizeof(tok_str), "ApCliKey%dStr%d", idx + 1, i + 1); + if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, FALSE)) + { + KeyLen = strlen(tmpbuf); + + 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, tmpbuf, &pApCliEntry->SharedKey[idx], idx) != TRUE) + DBGPRINT(RT_DEBUG_ERROR, ("RT_CfgSetWepKey fail!\n")); + } + + if (bKeyxStryIsUsed == FALSE) + { + bKeyxStryIsUsed = TRUE; + } + } + } + + if (bKeyxStryIsUsed == FALSE) + { + 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++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + + pApCliEntry->DesiredTransmitSetting.field.FixedTxMode = + RT_CfgSetFixedTxPhyMode(macptr); + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Tx Mode = %d\n", i, + pApCliEntry->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++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + + pApCliEntry->DesiredTransmitSetting.field.MCS = + RT_CfgSetTxMCSProc(macptr, &pApCliEntry->bAutoTxRateSwitch); + + if (pApCliEntry->DesiredTransmitSetting.field.MCS == MCS_AUTO) + { + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Tx MCS = AUTO\n", i)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Tx MCS = %d\n", i, + pApCliEntry->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(tmpbuf, 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_ERROR, ("ApCliAPSDCapable[%d]=%d\n", i, + pApCliEntry->UapsdInfo.bAPSDCapable)); + } + } +#endif /* UAPSD_SUPPORT */ +} +#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, ETH_LENGTH_OF_ADDRESS); + } + 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) /*Enable*/ + { + pAd->ApCfg.MBSSID[i].bWmmCapable = TRUE; + bEnableWmm = TRUE; + } + else /*Disable*/ + { + pAd->ApCfg.MBSSID[i].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].bWmmCapable; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) WmmCapable=%d\n", i, pAd->ApCfg.MBSSID[i].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);; + + 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);; + + 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);; + + 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_ERROR, ("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_ERROR, ("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_ERROR, ("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, 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].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].IEEE8021X = TRUE; + else /*Disable*/ + pAd->ApCfg.MBSSID[i].IEEE8021X = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d), IEEE8021X=%d\n", i, pAd->ApCfg.MBSSID[i].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; + +#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; + } + + 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) +{ + UINT32 Value = 0; + + /* 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; + } + + if (pAd->StaCfg.PSPXlink) + Value = PSPXLINK; + else + Value = STANORMAL; + + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, Value); + + DBGPRINT(RT_DEBUG_TRACE, ("PSP_XLINK_MODE=%d\n", pAd->StaCfg.PSPXlink)); + } +} +#endif /* XLINK_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + +#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_ENABLE) + { + pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE; + } + else + { + /*TODO: add mimo power saving mechanism*/ + pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE; + /*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); + if (Value == 0) + { + pAd->CommonCfg.BACapability.field.AmsduEnable = FALSE; + } + else + { + pAd->CommonCfg.BACapability.field.AmsduEnable = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx A-MSDU = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + /* 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 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].DesiredTransmitSetting.field.FixedTxMode = + RT_CfgSetFixedTxPhyMode(Bufptr); + DBGPRINT(RT_DEBUG_TRACE, ("(IF-ra%d) Fixed Tx Mode = %d\n", i, + pAd->ApCfg.MBSSID[i].DesiredTransmitSetting.field.FixedTxMode)); + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode = + RT_CfgSetFixedTxPhyMode(pValueStr); + DBGPRINT(RT_DEBUG_TRACE, ("Fixed Tx Mode = %d\n", + pAd->StaCfg.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 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; + } + + 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++) + { + Value = simple_strtol(Bufptr, 0, 10); +/* if ((Value >= 0 && Value <= 15) || (Value == 32))*/ + if ((Value >= 0 && Value <= 23) || (Value == 32)) /* 3*3*/ + { + pAd->ApCfg.MBSSID[i].DesiredTransmitSetting.field.MCS = Value; + DBGPRINT(RT_DEBUG_TRACE, ("(IF-ra%d) HT: MCS = %d\n", i, pAd->ApCfg.MBSSID[i].DesiredTransmitSetting.field.MCS)); + } + else + { + pAd->ApCfg.MBSSID[i].DesiredTransmitSetting.field.MCS = MCS_AUTO; + DBGPRINT(RT_DEBUG_TRACE, ("(IF-ra%d) HT: MCS is AUTO\n", i)); + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + Value = simple_strtol(pValueStr, 0, 10); + +/* if ((Value >= 0 && Value <= 15) || (Value == 32))*/ + if ((Value >= 0 && Value <= 23) || (Value == 32)) /* 3*3*/ + { + pAd->StaCfg.DesiredTransmitSetting.field.MCS = Value; +#ifdef P2P_SUPPORT + pAd->ApCfg.MBSSID[MAIN_MBSSID].DesiredTransmitSetting.field.MCS = Value; +#endif /* P2P_SUPPORT */ + pAd->StaCfg.bAutoTxRateSwitch = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("HT: MCS = %d\n", pAd->StaCfg.DesiredTransmitSetting.field.MCS)); + } + else + { + pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; +#ifdef P2P_SUPPORT + pAd->ApCfg.MBSSID[MAIN_MBSSID].DesiredTransmitSetting.field.MCS = MCS_AUTO; +#endif /* P2P_SUPPORT */ + pAd->StaCfg.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)); + } + + /* 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)); + } + /*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) +{ + int ret = TRUE; + + PassPh[strlen(PassPh)] = '\0'; /* make STA can process .$^& for WPAPSK input */ + + if ((pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) && + (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) && + (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPANone) +#ifdef WAPI_SUPPORT + && (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWAICERT) + && (pAd->StaCfg.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 ((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; + } +#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.IEEE8021X = pAd->StaCtIf.IEEE8021X; + pAd->StaCfg.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.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.DefaultKeyId = pAd->StaCfg.DesireSharedKeyId; + pAd->StaCtIf.IEEE8021X = pAd->StaCfg.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; + + 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; + +/* tmpbuf = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG);*/ + 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)); + } +#ifdef RTMP_EFUSE_SUPPORT +#endif /* RTMP_EFUSE_SUPPORT */ + /*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")); + } /* End of if */ +#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; + + 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), "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)); + } + /*WirelessMode*/ + /*Note: BssidNum must be put before WirelessMode in dat file*/ + if(RTMPGetKeyParameter("WirelessMode", tmpbuf, 32, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { +#ifdef CONFIG_AP_SUPPORT +#ifdef MBSS_SUPPORT + if (i >= pAd->ApCfg.BssidNum) + break; + + pAd->ApCfg.MBSSID[i].PhyMode = simple_strtol(macptr, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("BSS%d PhyMode=%d\n", i, pAd->ApCfg.MBSSID[i].PhyMode)); +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + if (i == 0) + { +#ifdef CONFIG_AP_SUPPORT +#ifdef MBSS_SUPPORT + /* for fist time, update all phy mode is same as ra0 */ + UINT32 IdBss; + for(IdBss=1; IdBssApCfg.BssidNum; IdBss++) + pAd->ApCfg.MBSSID[IdBss].PhyMode = pAd->ApCfg.MBSSID[0].PhyMode; +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + /* set mode for 1st time */ + /* in old design, we also only accept the 1st mode */ +#ifdef CONFIG_AP_SUPPORT + pAd->ApCfg.MBSSID[0].PhyMode = simple_strtol(macptr, 0, 10); +#endif /* CONFIG_AP_SUPPORT */ + 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*/ + + 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 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=%ld\n", i, pAd->ApCfg.MBSSID[i].IsolateInterStaTraffic)); + } + } + /*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=%ld\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); + 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 */ + + /*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); + } + + /* 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 */ + + +#if defined(RT2883) || defined(RT3883) + /*PhyRateLimit*/ + if(RTMPGetKeyParameter("PhyRateLimit", tmpbuf, 32, pBuffer, TRUE)) + { + pAd->CommonCfg.PhyRateLimit = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("PhyRateLimit = %ld\n", pAd->CommonCfg.PhyRateLimit)); + } + + /* FineAGC */ + if(RTMPGetKeyParameter("FineAGC", tmpbuf, 32, pBuffer, TRUE)) + { + pAd->CommonCfg.FineAGC = (simple_strtol(tmpbuf, 0, 10) != 0); + DBGPRINT(RT_DEBUG_TRACE, ("FineAGC = %d\n", pAd->CommonCfg.FineAGC)); + } +#endif /* RT2883 || RT3883 */ + +#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 + { +#ifdef RTMP_RBUS_SUPPORT + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; +#endif /* RTMP_RBUS_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)); + } + +#ifdef RTMP_RBUS_SUPPORT + /* DfsLowerLimit*/ + if(RTMPGetKeyParameter("DfsLowerLimit", tmpbuf, 10, pBuffer, TRUE)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) + pRadarDetect->DfsLowerLimit = simple_strtol(tmpbuf, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("DfsLowerLimit=%ld\n", pRadarDetect->DfsLowerLimit)); + } + + /* DfsUpperLimit*/ + if(RTMPGetKeyParameter("DfsUpperLimit", tmpbuf, 10, pBuffer, TRUE)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) + pRadarDetect->DfsUpperLimit = simple_strtol(tmpbuf, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("DfsUpperLimit=%ld\n", pRadarDetect->DfsUpperLimit)); + } +#endif /* RTMP_RBUS_SUPPORT */ + } +#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) + { + if ((strcmp(tmpbuf, "WEPAUTO") == 0) || (strcmp(tmpbuf, "wepauto") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeAutoSwitch; + else if ((strcmp(tmpbuf, "SHARED") == 0) || (strcmp(tmpbuf, "shared") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeShared; + else if ((strcmp(tmpbuf, "WPAPSK") == 0) || (strcmp(tmpbuf, "wpapsk") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK; + else if ((strcmp(tmpbuf, "WPANONE") == 0) || (strcmp(tmpbuf, "wpanone") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPANone; + else if ((strcmp(tmpbuf, "WPA2PSK") == 0) || (strcmp(tmpbuf, "wpa2psk") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK; +#ifdef WPA_SUPPLICANT_SUPPORT + else if ((strcmp(tmpbuf, "WPA") == 0) || (strcmp(tmpbuf, "wpa") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA; + else if ((strcmp(tmpbuf, "WPA2") == 0) || (strcmp(tmpbuf, "wpa2") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA2; +#endif /* WPA_SUPPLICANT_SUPPORT */ +#ifdef WAPI_SUPPORT + else if ((strcmp(tmpbuf, "WAICERT") == 0) || (strcmp(tmpbuf, "waicert") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWAICERT; + else if ((strcmp(tmpbuf, "WAIPSK") == 0) || (strcmp(tmpbuf, "waipsk") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWAIPSK; +#endif /* WAPI_SUPPORT */ + else + pAd->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + DBGPRINT(RT_DEBUG_TRACE, ("%s::(AuthMode=%d)\n", __FUNCTION__, pAd->StaCfg.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].WepStatus = Ndis802_11WEPDisabled; + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + int apidx; + + if (iApCfg.BssidNum) + { + apidx = i; + } + else + { + break; + } + + if ((strncmp(macptr, "NONE", 4) == 0) || (strncmp(macptr, "none", 4) == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11WEPDisabled; + else if ((strncmp(macptr, "WEP", 3) == 0) || (strncmp(macptr, "wep", 3) == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11WEPEnabled; + else if ((strncmp(macptr, "TKIPAES", 7) == 0) || (strncmp(macptr, "tkipaes", 7) == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11Encryption4Enabled; + else if ((strncmp(macptr, "TKIP", 4) == 0) || (strncmp(macptr, "tkip", 4) == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11Encryption2Enabled; + else if ((strncmp(macptr, "AES", 3) == 0) || (strncmp(macptr, "aes", 3) == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11Encryption3Enabled; +#ifdef WAPI_SUPPORT + else if ((strncmp(macptr, "SMS4", 4) == 0) || (strncmp(macptr, "sms4", 4) == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11EncryptionSMS4Enabled; +#endif /* WAPI_SUPPORT */ + else + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11WEPDisabled; + + /* decide the group key encryption type*/ + if (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11Encryption4Enabled) + pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus = Ndis802_11Encryption2Enabled; + else + pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus = pAd->ApCfg.MBSSID[apidx].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, ("I/F(ra%d) EncrypType=%d\n", i, pAd->ApCfg.MBSSID[apidx].WepStatus)); + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if ((strcmp(tmpbuf, "WEP") == 0) || (strcmp(tmpbuf, "wep") == 0)) + pAd->StaCfg.WepStatus = Ndis802_11WEPEnabled; + else if ((strcmp(tmpbuf, "TKIP") == 0) || (strcmp(tmpbuf, "tkip") == 0)) + pAd->StaCfg.WepStatus = Ndis802_11Encryption2Enabled; + else if ((strcmp(tmpbuf, "AES") == 0) || (strcmp(tmpbuf, "aes") == 0)) + pAd->StaCfg.WepStatus = Ndis802_11Encryption3Enabled; +#ifdef WAPI_SUPPORT + else if ((strcmp(tmpbuf, "SMS4") == 0) || (strcmp(tmpbuf, "sms4") == 0)) + pAd->StaCfg.WepStatus = Ndis802_11EncryptionSMS4Enabled; +#endif /* WAPI_SUPPORT */ + else + pAd->StaCfg.WepStatus = Ndis802_11WEPDisabled; + RTMPSetSTACipherSuites(pAd, pAd->StaCfg.WepStatus); + /*RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0);*/ + DBGPRINT(RT_DEBUG_TRACE, ("%s::(EncrypType=%d)\n", __FUNCTION__, pAd->StaCfg.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++) + { + if (pAd->ApCfg.MBSSID[i].AuthMode != Ndis802_11AuthModeWPA1WPA2 && + pAd->ApCfg.MBSSID[i].AuthMode != Ndis802_11AuthModeWPA1PSKWPA2PSK) + continue; + + if (pAd->ApCfg.MBSSID[i].WepStatus != Ndis802_11Encryption4Enabled) + continue; + + if ((strncmp(macptr, "WPA_AES_WPA2_TKIPAES", 20) == 0) || (strncmp(macptr, "wpa_aes_wpa2_tkipaes", 20) == 0)) + pAd->ApCfg.MBSSID[i].WpaMixPairCipher = WPA_AES_WPA2_TKIPAES; + else if ((strncmp(macptr, "WPA_AES_WPA2_TKIP", 17) == 0) || (strncmp(macptr, "wpa_aes_wpa2_tkip", 17) == 0)) + pAd->ApCfg.MBSSID[i].WpaMixPairCipher = WPA_AES_WPA2_TKIP; + else if ((strncmp(macptr, "WPA_TKIP_WPA2_AES", 17) == 0) || (strncmp(macptr, "wpa_tkip_wpa2_aes", 17) == 0)) + pAd->ApCfg.MBSSID[i].WpaMixPairCipher = WPA_TKIP_WPA2_AES; + else if ((strncmp(macptr, "WPA_TKIP_WPA2_TKIPAES", 21) == 0) || (strncmp(macptr, "wpa_tkip_wpa2_tkipaes", 21) == 0)) + pAd->ApCfg.MBSSID[i].WpaMixPairCipher = WPA_TKIP_WPA2_TKIPAES; + else if ((strncmp(macptr, "WPA_TKIPAES_WPA2_AES", 20) == 0) || (strncmp(macptr, "wpa_tkipaes_wpa2_aes", 20) == 0)) + pAd->ApCfg.MBSSID[i].WpaMixPairCipher = WPA_TKIPAES_WPA2_AES; + else if ((strncmp(macptr, "WPA_TKIPAES_WPA2_TKIPAES", 24) == 0) || (strncmp(macptr, "wpa_tkipaes_wpa2_tkipaes", 24) == 0)) + pAd->ApCfg.MBSSID[i].WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIPAES; + else if ((strncmp(macptr, "WPA_TKIPAES_WPA2_TKIP", 21) == 0) || (strncmp(macptr, "wpa_tkipaes_wpa2_tkip", 21) == 0)) + pAd->ApCfg.MBSSID[i].WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIP; + else /*Default*/ + pAd->ApCfg.MBSSID[i].WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIPAES; + + DBGPRINT(RT_DEBUG_OFF, ("I/F(ra%d) MixWPACipher=0x%02x\n", i, pAd->ApCfg.MBSSID[i].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 EASY_CONFIG_SETUP + /* AutoProvisionEn*/ + if(RTMPGetKeyParameter("AutoProvisionEn", tmpbuf, 32, pBuffer, TRUE)) + { + INT Value; + PEASY_CONFIG_INFO pEasyConfig = NULL; + +#ifdef CONFIG_AP_SUPPORT + UCHAR i=0; + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if (i >= pAd->ApCfg.BssidNum) + break; + + pEasyConfig = &pAd->ApCfg.MBSSID[i].EasyConfigInfo; +#endif /* CONFIG_AP_SUPPORT */ + Value = (INT) simple_strtol(tmpbuf, 0, 10); + if (Value == 0) + pEasyConfig->bEnable = FALSE; + else + pEasyConfig->bEnable = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("AutoProvisionEn=%d\n", pEasyConfig->bEnable)); +#ifdef CONFIG_AP_SUPPORT + } +#endif /* CONFIG_AP_SUPPORT */ + } +#endif /* EASY_CONFIG_SETUP */ + +#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 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 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 <= WPAPSKTKIP) + 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 */ + +#ifdef EASY_CONFIG_SETUP + /* RssiThreshold*/ + if (RTMPGetKeyParameter("RssiThreshold", tmpbuf, 32, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + INT Value; + PEASY_CONFIG_INFO pEasyConfig = NULL; + + if (i >= pAd->ApCfg.BssidNum) + break; + + pEasyConfig = &pAd->ApCfg.MBSSID[i].EasyConfigInfo; + + Value = (INT) simple_strtol(tmpbuf, 0, 10); + + if (Value > 70 || Value < 40) + pEasyConfig->RssiThreshold = -50; + else + pEasyConfig->RssiThreshold = (CHAR)(-1)*Value; + + DBGPRINT(RT_DEBUG_TRACE, ("RssiThreshold=%d dBm\n", pEasyConfig->RssiThreshold)); + } + } +#endif /* EASY_CONFIG_SETUP */ + + } +#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; +#ifdef DOT11Z_TDLS_SUPPORT + pAd->StaCfg.DefaultListenCount = 1; +#endif /* DOT11Z_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 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; + break; +#ifdef DOT11_N_SUPPORT + case MCAST_HTMIX: /* HTMIX*/ + pAd->CommonCfg.MCastPhyMode.field.MODE = MODE_HTMIX; + break; +#endif /* DOT11_N_SUPPORT */ + + default: + DBGPRINT(RT_DEBUG_OFF, ("unknow Muticast PhyMode %d.\n", PhyMode)); + DBGPRINT(RT_DEBUG_OFF, ("0:Disable 1:CCK, 2:OFDM, 3:HTMIX.\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 CCK 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 MESH_SUPPORT + rtmp_read_mesh_from_file(pAd, tmpbuf, pBuffer); +#endif /* MESH_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#endif /* CONFIG_AP_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_ERROR, ("EntryLifeCheck=%ld\n", pAd->ApCfg.EntryLifeCheck)); + } + +#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 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 */ + + +#ifdef CONFIG_ZTE_RADIO_ONOFF + if(RTMPGetKeyParameter("RadioOn", tmpbuf, 10, pBuffer, TRUE)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) + pAd->CommonCfg.bRadioEnable = TRUE; + else + pAd->CommonCfg.bRadioEnable = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("RadioOn=%d\n", pAd->CommonCfg.bRadioEnable)); + } +#endif /* CONFIG_ZTE_RADIO_ONOFF */ + +#ifdef P2P_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if(RTMPGetKeyParameter("P2P_GOIntent", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->P2pCfg.GoIntentIdx = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_ERROR, ("P2P_GOIntent=%d\n", pAd->P2pCfg.GoIntentIdx)); + } + + if(RTMPGetKeyParameter("P2P_DevName", tmpbuf, 32, pBuffer, TRUE)) + { + if ((strlen(tmpbuf) <= 32) + ) + { + pAd->P2pCfg.DeviceNameLen = (UCHAR) strlen(tmpbuf); + NdisZeroMemory(pAd->P2pCfg.DeviceName, 32); + NdisMoveMemory(pAd->P2pCfg.DeviceName, tmpbuf, pAd->P2pCfg.DeviceNameLen); + DBGPRINT(RT_DEBUG_TRACE, ("%s():P2P_DevName=%s\n", __FUNCTION__, tmpbuf)); + } + } + + if(RTMPGetKeyParameter("P2P_ListChannel", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->P2pCfg.ListenChannel = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_ERROR, ("P2P_ListChannel=%d\n", pAd->P2pCfg.ListenChannel)); + } + + if(RTMPGetKeyParameter("P2P_OpChannel", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->P2pCfg.GroupChannel = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_ERROR, ("P2P_OpChannel=%d\n", pAd->P2pCfg.GroupChannel)); + } + if(RTMPGetKeyParameter("P2P_WscCfgMethod", tmpbuf, 10, pBuffer, TRUE)) + { + UCHAR CfgMethod = simple_strtol(tmpbuf, 0, 10); + if (pAd->P2pCfg.WscMode == WSC_PIN_MODE) + { + if (CfgMethod == P2P_REG_CM_DISPLAY) + pAd->P2pCfg.DefaultConfigMethod = P2P_REG_CM_DISPLAY; + else if (CfgMethod == P2P_REG_CM_KEYPAD) + pAd->P2pCfg.DefaultConfigMethod = P2P_REG_CM_KEYPAD; + } + else if (pAd->P2pCfg.WscMode == WSC_PBC_MODE) + { + pAd->P2pCfg.DefaultConfigMethod = P2P_REG_CM_PBC; + } + DBGPRINT(RT_DEBUG_ERROR, ("P2P_WscCfgMethod=%d\n", pAd->P2pCfg.DefaultConfigMethod)); + } + + if(RTMPGetKeyParameter("P2P_ExtListenEnable", tmpbuf, 10, pBuffer, TRUE)) + { + UINT32 ExtList = simple_strtol(tmpbuf, 0, 10); + if (ExtList == 0) + pAd->P2pCfg.bExtListen = FALSE; + else if (ExtList == 1) + pAd->P2pCfg.bExtListen = TRUE; + DBGPRINT(RT_DEBUG_ERROR, ("P2P_ExtListen=%d\n", pAd->P2pCfg.bExtListen)); + } + + if(RTMPGetKeyParameter("P2P_ExtListenPrd", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->P2pCfg.ExtListenPeriod = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_ERROR, ("P2P_ExtListenPrd=%d\n", pAd->P2pCfg.ExtListenPeriod)); + } + + if(RTMPGetKeyParameter("P2P_ExtenListenInv", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->P2pCfg.ExtListenInterval = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_ERROR, ("P2P_ExtenListenInv=%d\n", pAd->P2pCfg.ExtListenInterval)); + } + + if(RTMPGetKeyParameter("P2P_IntraBss", tmpbuf, 10, pBuffer, TRUE)) + { + UINT32 IntraBss = simple_strtol(tmpbuf, 0, 10); + if (IntraBss == 0) + pAd->P2pCfg.bIntraBss = FALSE; + else if (IntraBss == 1) + pAd->P2pCfg.bIntraBss = TRUE; + DBGPRINT(RT_DEBUG_ERROR, ("P2P_IntraBss=%d\n", pAd->P2pCfg.bIntraBss)); + } + + if(RTMPGetKeyParameter("P2P_NoACnt", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->P2pCfg.GONoASchedule.Count = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_ERROR, ("P2P_NoACnt=%d\n", pAd->P2pCfg.GONoASchedule.Count)); + } + + if(RTMPGetKeyParameter("P2P_NoADuration", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->P2pCfg.GONoASchedule.Duration = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_ERROR, ("P2P_NoADuration=%ld\n", pAd->P2pCfg.GONoASchedule.Duration)); + } + + if(RTMPGetKeyParameter("P2P_NoAInv", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->P2pCfg.GONoASchedule.Interval = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_ERROR, ("P2P_NoAInv=%d\n", pAd->P2pCfg.GONoASchedule.Interval)); + } + + + } +#endif /* P2P_SUPPORT */ + +#ifdef WOW_SUPPORT +#endif /* WOW_SUPPORT */ + + }while(0); + +/* kfree(tmpbuf);*/ + os_free_mem(NULL, tmpbuf); + + return NDIS_STATUS_SUCCESS; + } + + +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 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]; + +#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); +/* kfree(buffer);*/ +/* kfree(tmpbuf);*/ + 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) +{ + PSTRING buffer; + PSTRING readline, token; + RTMP_OS_FD srcf; + INT retval; + PSTRING ptr; + int index, i; + CH_POWER *StartCh = NULL; + UCHAR MaxPwr; + 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; + + /* open card information file*/ + srcf = RtmpOSFileOpen(SINGLE_SKU_TABLE_FILE_NAME, O_RDONLY, 0); + if (IS_FILE_OPEN_ERR(srcf)) + { + /* card information file does not exist */ + DBGPRINT(RT_DEBUG_ERROR, + ("--> Error opening %s\n", SINGLE_SKU_TABLE_FILE_NAME)); + goto free_resource; + } + + /* 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", SINGLE_SKU_TABLE_FILE_NAME, -retval)); + goto free_resource; + } + 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; + + os_alloc_mem(NULL, (UCHAR **)&pwr, sizeof(*pwr)); + NdisZeroMemory(pwr, sizeof(*pwr)); + + token= rstrtok(readline +2 ," "); + pwr->channel = simple_strtol(token, 0, 10); + + 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; + } + + + 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; + } + } + } + + if ( isSame == TRUE ) + { + os_free_mem(NULL, pwr); + } + else + { + StartCh = pwr; + DlListAddTail(&pAd->SingleSkuPwrList, &StartCh->List); + pwr = NULL; + } + + + } + StartCh->num ++; + + } + } + + + } + + { + CH_POWER *ch, *ch_temp; + DlListForEachSafe(ch, ch_temp, &pAd->SingleSkuPwrList, CH_POWER, List) + { + int i; + printk("start ch = %d, ch->num = %d\n", ch->channel, ch->num); + + for ( i= 0 ; i < SINGLE_SKU_TABLE_CCK_LENGTH ; i++ ) + { + printk("%d ", ch->PwrCCK[i]); + } + printk("\n"); + + for ( i= 0 ; i < SINGLE_SKU_TABLE_OFDM_LENGTH ; i++ ) + { + printk("%d ", ch->PwrOFDM[i]); + } + printk("\n"); + + for ( i= 0 ; i < SINGLE_SKU_TABLE_HT_LENGTH ; i++ ) + { + printk("%d ", ch->PwrHT20[i]); + } + printk("\n"); + + for ( i= 0 ; i < SINGLE_SKU_TABLE_HT_LENGTH ; i++ ) + { + printk("%d ", ch->PwrHT40[i]); + } + printk("\n"); + + } + } + + pAd->bOpenFileSuccess = TRUE; + +free_resource: + + if (!IS_FILE_OPEN_ERR(srcf)) + { + /* close file*/ + retval = RtmpOSFileClose(srcf); + } + + RtmpOSFSInfoChange(&osFSInfo, FALSE); + + os_free_mem(NULL, buffer); + +} + +VOID 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 GetSkuChannelBasePwr( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel) +{ + CH_POWER *ch, *ch_temp; + UCHAR start_ch, end_ch; + UCHAR base_pwr; + int i; + CHAR tx_pwr1; + CHAR max_tx1_pwr; + UINT16 TargetPwr = 0; + UINT32 MacReg; + + 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->channel; + end_ch = start_ch + ch->num -1; + + if ( (channel >= start_ch) && ( channel <= end_ch ) ) + { + 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; + +} + +#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 + +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); + + 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->channel; + 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; + + + DBGPRINT(RT_DEBUG_TRACE, ("%s: pwr_diff = 0x%x, rate_pwr = 0x%x, base rate_pwr = 0x%x !!!\n", + __FUNCTION__, pwr_diff, rate_pwr, rate_pwr1)); + return rate_pwr; + +} +#endif /* SINGLE_SKU_V2 */ + diff --git a/mt7620/src/common/cmm_radar.c b/mt7620/src/common/cmm_radar.c new file mode 100644 index 0000000..2f543ab --- /dev/null +++ b/mt7620/src/common/cmm_radar.c @@ -0,0 +1,329 @@ +/* + *************************************************************************** + * 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) +{ + /* need to check channel availability, after switch channel*/ + if (pAd->Dot11_H.RDMode != RD_SILENCE_MODE) + return; + + /* channel availability check time is 60sec, use 65 for assurance*/ + if (pAd->Dot11_H.RDCount++ > pAd->Dot11_H.ChMovingTime) + { + DBGPRINT(RT_DEBUG_TRACE, ("Not found radar signal, start send beacon and radar detection in service monitor\n\n")); + AsicEnableBssSync(pAd); + pAd->Dot11_H.RDMode = RD_NORMAL_MODE; + return; + } +} + +/* + ======================================================================== + + 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; +} + +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*/ + +} + +#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) +{ + UINT8 Value; + + Value = (UINT8) 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 + int i; + UINT8 idx; + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam; + PDFS_SW_DETECT_PARAM pDfsSwParam = &pRadarDetect->DfsSwParam; + + 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("Fcc5Thrd = %d\n", pDfsSwParam->fcc_5_threshold); + 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("CeSwCheck = %d\n", pAd->CommonCfg.ce_sw_check);*/ + /*printk("CEStagCheck = %d\n", pAd->CommonCfg.ce_staggered_check);*/ + /*printk("HWDFSDisabled = %d\n", pAd->CommonCfg.hw_dfs_disabled);*/ + 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 (i =0; i < pRadarDetect->fdf_num; i++) + { + printk("ChBusyThrd[%d] = %d\n", i, pRadarDetect->ch_busy_threshold[i]); + printk("RssiThrd[%d] = %d\n", i, pRadarDetect->rssi_threshold[i]); + } + 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]); +#ifdef DFS_DEBUG + printk("Total[0] = %lu\n", pDfsSwParam->TotalEntries[0]); + printk("Total[1] = %lu\n", pDfsSwParam->TotalEntries[1]); + printk("Total[2] = %lu\n", pDfsSwParam->TotalEntries[2]); + printk("Total[3] = %lu\n", pDfsSwParam->TotalEntries[3]); + + pDfsSwParam->TotalEntries[0] = pDfsSwParam->TotalEntries[1] = pDfsSwParam->TotalEntries[2] = pDfsSwParam->TotalEntries[3] = 0; + + printk("T_Matched_2 = %lu\n", pDfsSwParam->T_Matched_2); + printk("T_Matched_3 = %lu\n", pDfsSwParam->T_Matched_3); + printk("T_Matched_4 = %lu\n", pDfsSwParam->T_Matched_4); + printk("T_Matched_5 = %lu\n", pDfsSwParam->T_Matched_5); +#endif /* DFS_DEBUG */ + + printk("pAd->Dot11_H.ChMovingTime = %d\n", pAd->Dot11_H.ChMovingTime); + printk("pAd->Dot11_H.RDMode = %d\n", pAd->Dot11_H.RDMode); +#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/mt7620/src/common/cmm_rf_cal.c b/mt7620/src/common/cmm_rf_cal.c new file mode 100644 index 0000000..245671a --- /dev/null +++ b/mt7620/src/common/cmm_rf_cal.c @@ -0,0 +1,3025 @@ +/* + *************************************************************************** + * 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, 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, 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, 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) +{ + UINT32 Value; + + Value = simple_strtol(arg, 0, 10); + + 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_STRUC 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 = BTYPE_DATA; + pNullFr->FC.SubType = SUBTYPE_NULL_FUNC; + 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, + 0, + Length, + 15, + 0, + 15, + IFS_HTTXOP, + FALSE, + &MlmeTransmit); + + pTxWI->MCS = 15; + pTxWI->PHYMODE = MODE_HTMIX; + pTxWI->BW = 0; + pTxWI->ACK = 0; + pTxWI->BAWinSize = 0; + pTxWI->PacketId = 15; + + 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_WARN, ("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_TRACE, ("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_TRACE, ("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; + + DBGPRINT(RT_DEBUG_INFO, (" gain_atten_bb = %d, gain_atten_rf = %d !\n", gain_atten_bb, gain_atten_rf)); + DBGPRINT(RT_DEBUG_INFO, (" txALC_init = %d, txALC_limit = %d !\n", txALC_init, txALC_limit)); + DBGPRINT(RT_DEBUG_INFO, (" temp_comp = %d, tx_alc_txwi = %d !\n", temp_comp, tx_alc_txwi)); + DBGPRINT(RT_DEBUG_INFO, (" txvga2 = %d, txvga3 = %d !\n", txvga2, txvga3)); + DBGPRINT(RT_DEBUG_INFO, (" mac_gain_atten = %d !\n", mac_gain_atten)); + DBGPRINT(RT_DEBUG_INFO, (" txALC_req = %d !\n", txALC_req)); + DBGPRINT(RT_DEBUG_INFO, (" txALC_req_at = %d !\n", txALC_req_at)); + DBGPRINT(RT_DEBUG_INFO, (" txALC_req_skip2 = %d !\n", txALC_req_skip2)); + DBGPRINT(RT_DEBUG_INFO, (" txALC_req_skip3 = %d !\n", txALC_req_skip3)); + DBGPRINT(RT_DEBUG_INFO, (" TX0: txALC_req_sat = %d !!!\n", txALC_req_sat)); + + // 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 */ + { + if (!ATE_ON(pAd)) + { + 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; + + DBGPRINT(RT_DEBUG_INFO, (" gain_atten_bb = %d, gain_atten_rf = %d !\n", gain_atten_bb, gain_atten_rf)); + DBGPRINT(RT_DEBUG_INFO, (" txALC_init = %d, txALC_limit = %d !\n", txALC_init, txALC_limit)); + DBGPRINT(RT_DEBUG_INFO, (" temp_comp = %d, tx_alc_txwi = %d !\n", temp_comp, tx_alc_txwi)); + DBGPRINT(RT_DEBUG_INFO, (" txvga2 = %d, txvga3 = %d !\n", txvga2, txvga3)); + DBGPRINT(RT_DEBUG_INFO, (" mac_gain_atten = %d !\n", mac_gain_atten)); + DBGPRINT(RT_DEBUG_INFO, (" txALC_req = %d !\n", txALC_req)); + DBGPRINT(RT_DEBUG_INFO, (" txALC_req_at = %d !\n", txALC_req_at)); + DBGPRINT(RT_DEBUG_INFO, (" txALC_req_skip2 = %d !\n", txALC_req_skip2)); + DBGPRINT(RT_DEBUG_INFO, (" txALC_req_skip3 = %d !\n", txALC_req_skip3)); + DBGPRINT(RT_DEBUG_INFO, (" TX1: txALC_req_sat = %d !!!\n", txALC_req_sat)); + + // 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 */ + { + if (!ATE_ON(pAd)) + { + /* 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 !!!\n")); + + 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_TRACE, ("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_TRACE, ("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_TRACE, ("Appropriate VGA Gain(%d), R66(%x)\n", RT6352_VGA_TABLE[VGA_code_idx].Register, VGA_code)); + DBGPRINT(RT_DEBUG_TRACE, ("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_TRACE, ("AM_SUM = %d, AM_10 = %d !!!\n", AM_SUM, AM_10)); + DBGPRINT(RT_DEBUG_TRACE, ("(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; + } + } + } + } + + if (DPD_Cal_success) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x01); + + 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, &byteValue); + DBGPRINT(RT_DEBUG_INFO, ("%s(): AM[%d] = %d !\n", __FUNCTION__, k_count, byteValue)); + } + } + } + + /* 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.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(3); + 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); + 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.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.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.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_TRACE, + ("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, RF_BYPASS0, 0x06); + } + else + { + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x02); + RTMP_IO_WRITE32(pAd, 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; + UINT32 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, 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_TRACE, ("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_TRACE, ("%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, 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_TRACE, (" RxIQ Calibration !!!\n")); + + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &saveMacSysCtrl); + RTMP_IO_READ32(pAd, RF_CONTROL0 , &orig_RF_CONTROL0); + RTMP_IO_READ32(pAd, 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, 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_ERROR, ("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_ERROR, ("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_ERROR, ("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_ERROR, ("RXIQ G_imb=%d, Ph_rx=%d\n", G_imb, Ph_rx)); + + if((Ph_rx > 20 ) || (Ph_rx < -20) ) + { + Ph_rx = 0; + DBGPRINT(RT_DEBUG_ERROR, ("RXIQ calibration FAIL\n")); + } + + if((G_imb > 12) ||(G_imb < -12)) + { + 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, 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 + // 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_TRACE, ("RF Tx_0 self calibration start\n")); + RTMP_IO_READ32(pAd, RF_CONTROL0, &mac0518); + RTMP_IO_READ32(pAd, RF_BYPASS0 , &mac051c); + RTMP_IO_READ32(pAd, RF_CONTROL2, &mac0528); + RTMP_IO_READ32(pAd, RF_BYPASS2 , &mac052c); + + RTMP_IO_WRITE32(pAd, RF_BYPASS0 , 0x0); + RTMP_IO_WRITE32(pAd, RF_BYPASS2 , 0x0); + + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0xC); + RTMP_IO_WRITE32(pAd, 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, RF_BYPASS0 , 0x0); + RTMP_IO_WRITE32(pAd, RF_BYPASS2 , 0x0); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, mac0518); + RTMP_IO_WRITE32(pAd, RF_BYPASS0 , mac051c); + RTMP_IO_WRITE32(pAd, RF_CONTROL2, mac0528); + RTMP_IO_WRITE32(pAd, RF_BYPASS2 , mac052c); + + DBGPRINT(RT_DEBUG_TRACE, ("RF Tx self calibration end\n")); + +} + diff --git a/mt7620/src/common/cmm_sanity.c b/mt7620/src/common/cmm_sanity.c new file mode 100644 index 0000000..34e6104 --- /dev/null +++ b/mt7620/src/common/cmm_sanity.c @@ -0,0 +1,1923 @@ +/* + *************************************************************************** + * 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" + +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 WAC_SUPPORT +extern UCHAR SAMSUNG_OUI[]; +#endif /* WAC_SUPPORT */ + +#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; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + + 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 >= MaxWcidNum)) + { + 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; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + pInfo = (MLME_DELBA_REQ_STRUCT *)Msg; + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + if ((MsgLen != sizeof(MLME_DELBA_REQ_STRUCT))) + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - message lenght not correct.\n")); + return FALSE; + } + + if ((pInfo->Wcid >= MaxWcidNum)) + { + 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 VOID *pMsg, + IN ULONG MsgLen) +{ + /*PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg;*/ + PFRAME_ADDBA_RSP pAddFrame; + + pAddFrame = (PFRAME_ADDBA_RSP)(pMsg); + if (MsgLen < (sizeof(FRAME_ADDBA_RSP))) + { + DBGPRINT(RT_DEBUG_ERROR,("PeerAddBARspActionSanity: ADDBA Response 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->StatusCode = cpu2le16(pAddFrame->StatusCode); + pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue); + + if (pAddFrame->BaParm.BAPolicy != IMMED_BA) + { + DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Response Ba Policy[%d] not support\n", pAddFrame->BaParm.BAPolicy)); + return FALSE; + } + + return TRUE; + +} + +BOOLEAN PeerDelBAActionSanity( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN VOID *pMsg, + IN ULONG MsgLen ) +{ + /*PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg;*/ + PFRAME_DELBA_REQ pDelFrame; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + + if (MsgLen != (sizeof(FRAME_DELBA_REQ))) + return FALSE; + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + if (Wcid >= MaxWcidNum) + return FALSE; + + pDelFrame = (PFRAME_DELBA_REQ)(pMsg); + + *(USHORT *)(&pDelFrame->DelbaParm) = cpu2le16(*(USHORT *)(&pDelFrame->DelbaParm)); + pDelFrame->ReasonCode = cpu2le16(pDelFrame->ReasonCode); + + 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 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, +#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; + 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*/ +#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, ("PeerBeaconAndProbeRspSanity - Variable IEs out of resource [len(=%d) > MAX_VIE_LEN(=%d)]\n", + (*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, ("PeerBeaconAndProbeRspSanity - wrong IE_SSID (len=%d)\n",pEid->Len)); + 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, ("PeerBeaconAndProbeRspSanity - wrong IE_SUPP_RATES (len=%d)\n",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, ("PeerBeaconAndProbeRspSanity - wrong IE_HT_CAP. pEid->Len = %d\n", 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, ("PeerBeaconAndProbeRspSanity - wrong IE_ADD_HT. \n")); + } + + break; + case IE_SECONDARY_CH_OFFSET: + if (pEid->Len == 1) + { + *NewExtChannelOffset = pEid->Octet[0]; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n")); + } + + break; + case IE_FH_PARM: + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity(IE_FH_PARM) \n")); + 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, ("PeerBeaconAndProbeRspSanity - wrong IE_DS_PARM (len=%d)\n",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, ("PeerBeaconAndProbeRspSanity - wrong IE_CF_PARM\n")); + 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, ("PeerBeaconAndProbeRspSanity - wrong IE_IBSS_PARM\n")); + if (pPeerWscIe) + os_free_mem(NULL, pPeerWscIe); + return FALSE; + } + break; + +#ifdef CONFIG_STA_SUPPORT + case IE_TIM: + if(SubType == SUBTYPE_BEACON) + { +#ifdef P2P_SUPPORT + if (P2P_CLI_ON(pAd) && NdisEqualMemory(pBssid, pAd->ApCfg.ApCliTab[BSS0].ApCliMlmeAux.Bssid, MAC_ADDR_LEN)) + { + GetTimBit((PCHAR)pEid, pAd->ApCfg.ApCliTab[BSS0].ApCliMlmeAux.Aid, &TimLen, pBcastFlag, pDtimCount, pDtimPeriod, pMessageToMe); + } +#endif /* P2P_SUPPORT */ + 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)) + { + /**pRalinkIe = pEid->Octet[3];*/ + 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, PRE_N_HT_OUI, 3) && (pEid->Len >= 4) && (pAd->OpMode == OPMODE_STA)) + { + if ((pEid->Octet[3] == OUI_PREN_HT_CAP) && (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] = CW_MIN_IN_BITS; + pEdcaParm->Cwmax[QID_AC_BE] = CW_MAX_IN_BITS; + pEdcaParm->Txop[QID_AC_BE] = 0; + + pEdcaParm->bACM[QID_AC_BK] = 0; + pEdcaParm->Aifsn[QID_AC_BK] = 7; + pEdcaParm->Cwmin[QID_AC_BK] = CW_MIN_IN_BITS; + pEdcaParm->Cwmax[QID_AC_BK] = CW_MAX_IN_BITS; + pEdcaParm->Txop[QID_AC_BK] = 0; + + pEdcaParm->bACM[QID_AC_VI] = 0; + pEdcaParm->Aifsn[QID_AC_VI] = 2; + pEdcaParm->Cwmin[QID_AC_VI] = CW_MIN_IN_BITS-1; + pEdcaParm->Cwmax[QID_AC_VI] = CW_MAX_IN_BITS; + 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] = CW_MIN_IN_BITS-2; + pEdcaParm->Cwmax[QID_AC_VO] = CW_MAX_IN_BITS-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 (PeerWscIeLen >= 512) + DBGPRINT(RT_DEBUG_ERROR, ("%s: PeerWscIeLen = %d (>= 512)\n", __FUNCTION__, PeerWscIeLen)); + if (pPeerWscIe && (PeerWscIeLen < 512)) + { + NdisMoveMemory(pPeerWscIe+PeerWscIeLen, pEid->Octet+4, pEid->Len-4); + PeerWscIeLen += (pEid->Len - 4); + } +#ifdef IWSC_SUPPORT + if (NdisEqualMemory(pEid->Octet, IWSC_OUI, 4)) + bFoundIWscIe = TRUE; +#endif /* IWSC_SUPPORT */ + + + + } +#ifdef WAC_SUPPORT + else if (NdisEqualMemory(pEid->Octet, SAMSUNG_OUI, 3)) + { + /* Copy to pVIE which will report to bssid list. */ + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } +#endif /* WAC_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; + + + + 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)) + { + 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) + { + DBGPRINT(RT_DEBUG_LOUD, ("PeerBeaconAndProbeRspSanity - missing field, Sanity=0x%02x\n", 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; + } + +} + +#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) +{ + 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; + + if ((*pBssType == BSS_INFRA || *pBssType == BSS_ADHOC || *pBssType == BSS_ANY) + && (*pScanType == SCAN_ACTIVE || *pScanType == SCAN_PASSIVE +#ifdef WSC_INCLUDED + || (*pScanType == SCAN_WSC_ACTIVE) +#endif /* WSC_INCLUDED */ +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + || (*pScanType == SCAN_2040_BSS_COEXIST) +#endif /*DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ +#ifdef P2P_SUPPORT + || (*pScanType == SCAN_P2P) + || (*pScanType == SCAN_P2P_SEARCH) +#endif /* P2P_SUPPORT */ + )) + { + 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; + } + } + 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) + ) && + ((*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 */ +#ifdef WAC_SUPPORT + if (pAd->StaCfg.EasyConfigInfo.bDoAutoWps && + pAd->StaCfg.EasyConfigInfo.bEnableWAC && + pAd->StaCfg.EasyConfigInfo.bWACAP) + *pAlg = AUTH_MODE_OPEN; +#endif /* WAC_SUPPORT */ +#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( + IN PBSS_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) + 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 PUCHAR pAddr2, + OUT CHAR Ssid[], + OUT UCHAR *SsidLen, + OUT BOOLEAN *bRssiRequested) +{ + 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; +#endif /* WSC_INCLUDED */ +#endif /* CONFIG_AP_SUPPORT */ + UINT total_ie_len = 0; + + /* to prevent caller from using garbage output value*/ +#ifdef CONFIG_AP_SUPPORT + apidx = apidx; /* avoid compile warning */ +#endif /* CONFIG_AP_SUPPORT */ + *SsidLen = 0; + + COPY_MAC_ADDR(pAddr2, &Fr->Hdr.Addr2); + + if (Fr->Octet[0] != IE_SSID || Fr->Octet[1] > MAX_LEN_OF_SSID) + { + DBGPRINT(RT_DEBUG_TRACE, ("APPeerProbeReqSanity fail - wrong SSID IE\n")); + return FALSE; + } + + *SsidLen = Fr->Octet[1]; + NdisMoveMemory(Ssid, &Fr->Octet[2], *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 */ + + Ptr = Fr->Octet; + eid = Ptr[0]; + eid_len = Ptr[1]; + total_ie_len = eid_len + 2; + eid_data = Ptr+2; + + /* 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 (bRssiRequested && NdisEqualMemory(eid_data, RALINK_OUI, 3) && (eid_len == 7)) + { + if (*(eid_data + 3/* skip RALINK_OUI */) & 0x8) + *bRssiRequested = 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 +#ifdef EASY_CONFIG_SETUP + /* + Only when bHideSsid is TRUE, driver will check SSID from probe request of STA. + */ + if (pAd->ApCfg.MBSSID[apidx].bHideSsid) + AutoProvisionAssignSSID(pAd, eid_data, eid_len, pAddr2, apidx, SsidLen, Ssid); +#endif /* EASY_CONFIG_SETUP */ +#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 (PeerWscIeLen >= 512) + DBGPRINT(RT_DEBUG_ERROR, ("APPeerProbeReqSanity : PeerWscIeLen = %d (>= 512)\n", PeerWscIeLen)); + if (pPeerWscIe && (PeerWscIeLen < 512)) + { + NdisMoveMemory(pPeerWscIe+PeerWscIeLen, eid_data+4, eid_len-4); + PeerWscIeLen += (eid_len - 4); + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* WSC_INCLUDED */ + break; + } + + 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)) + { + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + if (NdisEqualMemory(Addr1, pAd->ApCfg.MBSSID[apidx].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 >= *SsidLen) /*Well, I think that it must be TRUE!*/ + { + NdisMoveMemory(pprobreq->ssid, Ssid, *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/mt7620/src/common/cmm_sync.c b/mt7620/src/common/cmm_sync.c new file mode 100644 index 0000000..e8d309f --- /dev/null +++ b/mt7620/src/common/cmm_sync.c @@ -0,0 +1,1487 @@ +/* + *************************************************************************** + * 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}; + +#ifdef P2P_SUPPORT +extern UCHAR WILDP2PSSID[]; +extern UCHAR WILDP2PSSIDLEN; +#endif /* P2P_SUPPORT */ + +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( + IN PRTMP_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 ((pAd->CommonCfg.PhyMode != PHY_11A) +#ifdef DOT11_N_SUPPORT + && (pAd->CommonCfg.PhyMode != PHY_11AN_MIXED) && (pAd->CommonCfg.PhyMode != PHY_11N_5G) +#endif /* DOT11_N_SUPPORT */ + ) + { + 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; +#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 ((pAd->CommonCfg.PhyMode == PHY_11A) || (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) +#ifdef DOT11_N_SUPPORT + || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) + || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11N_5G) +#endif /* DOT11_N_SUPPORT */ + ) + { + 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[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; +#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; +#endif /* DOT11_N_SUPPORT */ + + for (j=0; j<15; j++) + { + if (pChannelList[i] == RadarCh[j]) + pAd->ChannelList[index+i].DfsReq = TRUE; + } + 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, + (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED), + (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( + IN PRTMP_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( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel) +{ + int i; + UCHAR next_channel = 0; +#ifdef P2P_SUPPORT + UCHAR CurrentChannel = channel; + + if (pAd->MlmeAux.ScanType == SCAN_P2P_SEARCH) + { + if (IS_P2P_LISTEN(pAd)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Error !! P2P Discovery state machine has change to Listen state during scanning !\n")); + return next_channel; + } + + for (i = 0; i < (pAd->P2pCfg.P2pProprietary.ListenChanelCount - 1); i++) + { + if (CurrentChannel == pAd->P2pCfg.P2pProprietary.ListenChanel[i]) + next_channel = pAd->P2pCfg.P2pProprietary.ListenChanel[i+1]; + } + P2P_INC_CHA_INDEX(pAd->P2pCfg.P2pProprietary.ListenChanelIndex, pAd->P2pCfg.P2pProprietary.ListenChanelCount); + if (next_channel == CurrentChannel) + { + DBGPRINT(RT_DEBUG_INFO, ("SYNC - next_channel equals to CurrentChannel= %d\n", next_channel)); + DBGPRINT(RT_DEBUG_INFO, ("SYNC - ListenChannel List : %d %d %d\n", pAd->P2pCfg.P2pProprietary.ListenChanel[0], pAd->P2pCfg.P2pProprietary.ListenChanel[1], pAd->P2pCfg.P2pProprietary.ListenChanel[2])); + + next_channel = 0; + } + + DBGPRINT(RT_DEBUG_INFO, ("SYNC - P2P Scan return channel = %d. Listen Channel = %d.\n", next_channel, pAd->CommonCfg.Channel)); + + return next_channel; + } +#endif /* P2P_SUPPORT */ + + 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: + 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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi, + IN UCHAR RssiNumber) +{ + UCHAR RssiOffset, LNAGain; + CHAR BaseVal; + + /* Rssi equals to zero should be an invalid value*/ + if (Rssi == 0) + return -99; + + LNAGain = GET_LNA_GAIN(pAd); + if (pAd->LatchRfRegs.Channel > 14) + { + if (RssiNumber == 0) + RssiOffset = pAd->ARssiOffset0; + else if (RssiNumber == 1) + RssiOffset = pAd->ARssiOffset1; + else + RssiOffset = pAd->ARssiOffset2; + } + else + { + if (RssiNumber == 0) + RssiOffset = pAd->BGRssiOffset0; + else if (RssiNumber == 1) + RssiOffset = pAd->BGRssiOffset1; + else + RssiOffset = pAd->BGRssiOffset2; + } + + BaseVal = -12; + +#ifdef RT6352 + if (IS_RT6352(pAd)) + BaseVal = -2; +#endif /* RT6352 */ + + return (BaseVal - RssiOffset - LNAGain - Rssi); +} + +CHAR ConvertToSnr( + IN PRTMP_ADAPTER pAd, + IN 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 ; +} + +#if defined(AP_SCAN_SUPPORT) || defined(CONFIG_STA_SUPPORT) +/* + ========================================================================== + Description: + Scan next channel + ========================================================================== + */ +VOID ScanNextChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR OpMode) +{ + HEADER_802_11 Hdr80211; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + UCHAR SsidLen = 0, ScanType = pAd->MlmeAux.ScanType, BBPValue = 0; +#ifdef CONFIG_STA_SUPPORT + USHORT Status; +/* PHEADER_802_11 pHdr80211; no use*/ +#endif /* CONFIG_STA_SUPPORT */ + UINT ScanTimeIn5gChannel = SHORT_CHANNEL_TIME; + BOOLEAN ScanPending = FALSE; + + +#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 RALINK_ATE + /* Nothing to do in ATE mode. */ + if (ATE_ON(pAd)) + return; +#endif /* RALINK_ATE */ + +#ifdef CONFIG_AP_SUPPORT + ScanPending = ((pAd->ApCfg.bImprovedScan) && (pAd->ApCfg.ScanChannelCnt>=3));//7 +#endif + + if ((pAd->MlmeAux.Channel == 0) || ScanPending) + { + + + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + UINT32 Data = 0, macStatus; + UINT32 MTxCycle; + + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, TRUE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + + //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, &BBPValue); + BBPValue &= (~0x18); + BBPValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + + //Enable MAC Tx/Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Data); + Data |= 0x0C; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Data); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr)); + } + else + { + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, TRUE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to channel %d, Total BSS[%02d]\n",pAd->CommonCfg.Channel, 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__)); + } + + /* 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); + } + +#ifdef LINUX +#ifdef RT_CFG80211_SUPPORT + RTEnqueueInternalCmd(pAd, CMDTHREAD_SCAN_END, NULL, 0); +#endif /* RT_CFG80211_SUPPORT */ +#endif /* LINUX */ + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + if (OpMode == OPMODE_AP) + { +#ifdef P2P_APCLI_SUPPORT + /* P2P CLIENT in WSC Scan or Re-Connect scanning. */ + if (P2P_CLI_ON(pAd) && (ApScanRunning(pAd) == TRUE)) + { + /*MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_JOIN_REQ_TIMEOUT, 0, NULL, 0);*/ + DBGPRINT(RT_DEBUG_INFO, ("%s:: Scan Done! reset APCLI CTRL State Machine!\n", __FUNCTION__)); + pAd->ApCfg.ApCliTab[0].CtrlCurrState = APCLI_CTRL_DISCONNECTED; + } +#endif /* P2P_APCLI_SUPPORT */ +#ifdef APCLI_SUPPORT +#ifdef APCLI_AUTO_CONNECT_SUPPORT + if (pAd->ApCfg.ApCliAutoConnectRunning == TRUE) + { + if (!ApCliAutoConnectExec(pAd)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Error in %s\n", __FUNCTION__)); + } + } +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + + /* to prevent AP no beacon when do sitesurvey. each time we get back to origin channel, update RcvBcnTime */ + int loop; + for (loop = 0; loop < MAX_APCLI_NUM; loop++) + { + PAPCLI_STRUCT pApCliEntry = &pAd->ApCfg.ApCliTab[loop]; + if (pApCliEntry->Valid == TRUE) + { + pApCliEntry->ApCliRcvBeaconTime = pAd->Mlme.Now32; + } + } +#endif /* APCLI_SUPPORT */ + + pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; + RTMPResumeMsduTransmission(pAd); + + /* keep the latest scan channel, could be 0 for scan complete, or other channel */ + pAd->ApCfg.LastScanChannel = pAd->MlmeAux.Channel; + pAd->ApCfg.ScanChannelCnt=0; + /* Suspend scanning and Resume TxData for Fast Scanning */ + if ((pAd->MlmeAux.Channel != 0) && + (pAd->ApCfg.bImprovedScan)) + { + pAd->Mlme.ApSyncMachine.CurrState = AP_SCAN_PENDING; + DBGPRINT(RT_DEBUG_TRACE, ("bImprovedScan ~~ Get back to send data\n")); + } + else + { + pAd->ApCfg.bImprovedScan = FALSE; +#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))) + { + 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 MESH_SUPPORT + MlmeEnqueue(pAd, MESH_CTRL_STATE_MACHINE, APMT2_MLME_SCAN_FINISH, 0, NULL, 0); +#endif /* MESH_SUPPORT */ +#ifdef P2P_SUPPORT +/* move to state machine */ +/* + if (pAd->P2pCfg.P2pCounter.bStartScan && + ((ScanType == SCAN_P2P) || (ScanType == SCAN_P2P_SEARCH))) + P2PSetListenTimer(pAd, 0); +*/ +#endif /* P2P_SUPPORT */ + } + 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 */ + + AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, TRUE); + AsicLockChannel(pAd, pAd->MlmeAux.Channel); + +#ifdef CONFIG_STA_SUPPORT + if (OpMode == OPMODE_STA) + { + BOOLEAN bScanPassive = FALSE; + if (pAd->MlmeAux.Channel > 14) + { + + if ((pAd->CommonCfg.bIEEE80211H == 1) + && RadarChannelCheck(pAd, pAd->MlmeAux.Channel)) + { + bScanPassive = TRUE; + } + + } +#ifdef CARRIER_DETECTION_SUPPORT /* Roger sync Carrier*/ + /* carrier detection*/ + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + { + bScanPassive = TRUE; + } +#endif /* CARRIER_DETECTION_SUPPORT */ + + if (bScanPassive) + { + ScanType = SCAN_PASSIVE; + ScanTimeIn5gChannel = MIN_CHANNEL_TIME; + } + } + +#endif /* CONFIG_STA_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; + + + /* 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*/ +#ifdef CONFIG_STA_SUPPORT + if (ScanType == FAST_SCAN_ACTIVE) + RTMPSetTimer(&pAd->MlmeAux.ScanTimer, FAST_ACTIVE_SCAN_TIME); + else /* must be SCAN_PASSIVE or SCAN_ACTIVE*/ +#endif +#ifdef CONFIG_AP_SUPPORT + if (ScanType == FAST_SCAN_ACTIVE) { + RTMPSetTimer(&pAd->MlmeAux.APScanTimer, MIN_CHANNEL_TIME);//use MIN_CHANNEL_TIME instead of Fast_Scan_Time + pAd->ApCfg.ScanChannelCnt++; + } + else /* must be SCAN_PASSIVE or SCAN_ACTIVE*/ +#endif + { +#ifdef CONFIG_STA_SUPPORT + pAd->StaCfg.ScanChannelCnt++; +#endif /* CONFIG_STA_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + pAd->ApCfg.ScanChannelCnt++; +#endif + if ((pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) +#ifdef DOT11_N_SUPPORT + || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) +#endif /* DOT11_N_SUPPORT */ + ) + { +#ifdef CONFIG_AP_SUPPORT + if ((OpMode == OPMODE_AP) && (pAd->ApCfg.bAutoChannelAtBootup)) + { + /* wait 400 ms*/ + RTMPSetTimer(&pAd->MlmeAux.APScanTimer, AUTO_CHANNEL_SEL_TIMEOUT); + } + else +#endif /* CONFIG_AP_SUPPORT */ + { + if (pAd->MlmeAux.Channel > 14) + { + if (OpMode == OPMODE_AP) + RTMPSetTimer(&pAd->MlmeAux.APScanTimer, ScanTimeIn5gChannel); + else + RTMPSetTimer(&pAd->MlmeAux.ScanTimer, ScanTimeIn5gChannel); + } + else + { + if (OpMode == OPMODE_AP) + RTMPSetTimer(&pAd->MlmeAux.APScanTimer, MIN_CHANNEL_TIME); + else + RTMPSetTimer(&pAd->MlmeAux.ScanTimer, MIN_CHANNEL_TIME); + } + } + } + else + { +#ifdef CONFIG_AP_SUPPORT + if ((OpMode == OPMODE_AP) && (pAd->ApCfg.bAutoChannelAtBootup)) + { + /* wait 400 ms*/ + RTMPSetTimer(&pAd->MlmeAux.APScanTimer, AUTO_CHANNEL_SEL_TIMEOUT); + } + else +#endif /* CONFIG_AP_SUPPORT */ + { + if (OpMode == OPMODE_AP) + RTMPSetTimer(&pAd->MlmeAux.APScanTimer, MAX_CHANNEL_TIME); + else + RTMPSetTimer(&pAd->MlmeAux.ScanTimer, MAX_CHANNEL_TIME); + } + } + } + if ((ScanType == SCAN_ACTIVE) + || (ScanType == FAST_SCAN_ACTIVE) +#ifdef WSC_STA_SUPPORT + || ((ScanType == SCAN_WSC_ACTIVE) && (OpMode == OPMODE_STA)) +#endif /* WSC_STA_SUPPORT */ +#ifdef WSC_AP_SUPPORT + || ((ScanType == SCAN_WSC_ACTIVE) && (OpMode == OPMODE_AP)) +#endif /* WSC_AP_SUPPORT */ +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + || (ScanType == SCAN_2040_BSS_COEXIST) +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ +#ifdef P2P_SUPPORT + || (ScanType == SCAN_P2P) + || (ScanType == SCAN_P2P_SEARCH) +#endif /* P2P_SUPPORT */ + ) + { + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/ + if (NStatus != 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; + } + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (ScanType == SCAN_2040_BSS_COEXIST) + { + DBGPRINT(RT_DEBUG_TRACE, ("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; + 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; + +#ifdef P2P_SUPPORT + if ((pAd->MlmeAux.ScanType == SCAN_P2P) || (pAd->MlmeAux.ScanType == SCAN_P2P_SEARCH) +#ifdef P2P_APCLI_SUPPORT + || ((pAd->MlmeAux.ScanType == SCAN_WSC_ACTIVE) && (OpMode == OPMODE_AP) && (P2P_CLI_ON(pAd))) +#endif /* P2P_APCLI_SUPPORT */ + ) + { + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + /*UCHAR SupRateIe = IE_SUPP_RATES;*/ + UCHAR SupRateLen = 0; + /* JANTEMP */ + /* Use Wildword SSID */ + + SsidLen = WILDP2PSSIDLEN; + 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; + /* P2P scan must use P2P mac address. */ + MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, + pP2PCtrl->CurrentAddress, + BROADCAST_ADDR); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr80211, + 1, &SsidIe, + 1, &SsidLen, + SsidLen, &WILDP2PSSID[0], + 1, &SupRateIe, + 1, &SupRateLen, + SupRateLen, SupRate, + END_OF_ARGS); + } + else +#endif /* P2P_SUPPORT */ + { +#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) + MgtMacHeaderInitExt(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, + pAd->ApCfg.ApCliTab[0].CurrentAddress, + BROADCAST_ADDR); + else +#endif /* WSC_INCLUDED */ +#endif /* APCLI_SUPPORT */ + MgtMacHeaderInitExt(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, + pAd->ApCfg.MBSSID[0].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, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + BROADCAST_ADDR); + } +#endif /* CONFIG_STA_SUPPORT */ + + MakeOutgoingFrame(pOutBuffer, &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(pOutBuffer + FrameLen, &Tmp, + 1, &ExtRateIe, + 1, &pAd->CommonCfg.ExtRateLen, + pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, + END_OF_ARGS); + FrameLen += Tmp; + } + } +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + { + 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(pOutBuffer + FrameLen, &Tmp, + 1, &WpaIe, + 1, &HtLen, + 4, &BROADCOM[0], + pAd->MlmeAux.HtCapabilityLen, &HtCapabilityTmp, + END_OF_ARGS); +#else + MakeOutgoingFrame(pOutBuffer + 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(pOutBuffer + FrameLen, &Tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, + END_OF_ARGS); +#else + MakeOutgoingFrame(pOutBuffer + 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(pOutBuffer + 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 */ + + 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->ApCfg.ApCliTab[0].WscControl, STA_MODE, 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_INCLUDED */ +#endif /* APCLI_SUPPORT */ + +#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 */ + +#ifdef P2P_SUPPORT + /* + P2pMakeProbeReqIE will build WSC IE for P2P, + it is not good to append normal WSC IE into P2P probe request frame here. + */ + if ((pAd->MlmeAux.ScanType == SCAN_P2P) || (pAd->MlmeAux.ScanType == SCAN_P2P_SEARCH) || + ((pAd->MlmeAux.ScanType == SCAN_WSC_ACTIVE) && (OpMode == OPMODE_AP) && (P2P_CLI_ON(pAd)))) + bHasWscIe = FALSE; +#endif /* P2P_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->StaCfg.WscControl, STA_MODE, 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__)); + } + } + +#ifdef WAC_SUPPORT + WAC_AddDevAdvAttrIE(pAd, BSS0, pOutBuffer, &FrameLen); +#endif /* WAC_SUPPORT */ +#endif /* WSC_STA_SUPPORT */ + +#ifdef WPA_SUPPLICANT_SUPPORT + if ((OpMode == OPMODE_STA) && + (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) && + (pAd->StaCfg.WpsProbeReqIeLen != 0)) + { + ULONG WpsTmpLen = 0; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &WpsTmpLen, + pAd->StaCfg.WpsProbeReqIeLen, pAd->StaCfg.pWpsProbeReqIe, + END_OF_ARGS); + + FrameLen += WpsTmpLen; + } +#endif /* WPA_SUPPLICANT_SUPPORT */ + +#ifdef P2P_SUPPORT + if ((pAd->MlmeAux.ScanType == SCAN_P2P) || (pAd->MlmeAux.ScanType == SCAN_P2P_SEARCH) +#ifdef P2P_APCLI_SUPPORT + || ((pAd->MlmeAux.ScanType == SCAN_WSC_ACTIVE) && (OpMode == OPMODE_AP) && (P2P_CLI_ON(pAd))) +#endif /* P2P_APCLI_SUPPORT */ + ) + { + ULONG P2PIeLen; + PUCHAR ptr; + ptr = pOutBuffer + FrameLen; + P2pMakeProbeReqIE(pAd, ptr, &BBPValue); + FrameLen += BBPValue; + + /* Put P2P IE to the last. */ + ptr = pOutBuffer + FrameLen; + P2pMakeP2pIE(pAd, SUBTYPE_PROBE_REQ, ptr, &P2PIeLen); + + FrameLen += P2PIeLen; + } + +#endif /* P2P_SUPPORT */ + + MiniportMMRequest(pAd, 0, pOutBuffer, 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, pOutBuffer); + } + + /* 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 */ +#ifdef CONFIG_AP_SUPPORT + if (OpMode == OPMODE_AP) + pAd->Mlme.ApSyncMachine.CurrState = AP_SCAN_LISTEN; +#endif /* CONFIG_AP_SUPPORT */ + } +} +#endif + + + +#ifdef CONFIG_AP_SUPPORT +#ifdef DOT11_N_SUPPORT +extern int DetectOverlappingPeriodicRound; + +VOID Handle_BSS_Width_Trigger_Events( + IN PRTMP_ADAPTER pAd) +{ + ULONG Now32; + + 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 /* DOT11_N_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +BOOLEAN ScanRunning( + IN PRTMP_ADAPTER pAd) +{ + BOOLEAN rv = FALSE; + +#ifdef CONFIG_STA_SUPPORT +#ifdef P2P_SUPPORT + rv = ((pAd->Mlme.ApSyncMachine.CurrState == AP_SCAN_LISTEN) ? TRUE : FALSE); + + if (rv == FALSE) + { + if ((pAd->Mlme.SyncMachine.CurrState == SCAN_LISTEN) || (pAd->Mlme.SyncMachine.CurrState == SCAN_PENDING)) + rv = TRUE; + } +#else + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if ((pAd->Mlme.SyncMachine.CurrState == SCAN_LISTEN) || (pAd->Mlme.SyncMachine.CurrState == SCAN_PENDING)) + rv = TRUE; + } +#endif /* P2P_SUPPORT */ +#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) */ + diff --git a/mt7620/src/common/cmm_tkip.c b/mt7620/src/common/cmm_tkip.c new file mode 100644 index 0000000..f60d6a3 --- /dev/null +++ b/mt7620/src/common/cmm_tkip.c @@ -0,0 +1,951 @@ +/* + *************************************************************************** + * 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].CurrentAddress, + 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)) + { + RTMPInitMICEngine( + pAd, + pKey->Key, + pAd->MacTab.Content[RTMP_GET_PACKET_WCID(pPacket)].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); /* End of copying payload*/ + + /* 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! +*/ +BOOLEAN 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 frame_type; + UINT8 frame_subtype; + UINT8 from_ds; + UINT8 to_ds; + UINT8 a4_exists; + UINT8 qc_exists; + 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 FALSE; + } + + /* 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 = ((frame_subtype == SUBTYPE_QDATA) || + (frame_subtype == SUBTYPE_QDATA_CFACK) || + (frame_subtype == SUBTYPE_QDATA_CFPOLL) || + (frame_subtype == SUBTYPE_QDATA_CFACK_CFPOLL)); + + /* 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; + + /* 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 FALSE; + } + + /* 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.WpaSupplicantUP) { + WpaSendMicFailureToWpaSupplicant(pAd->net_dev, + (pKey->Type == + PAIRWISEKEY) ? TRUE : + FALSE); + } else +#endif /* WPA_SUPPLICANT_SUPPORT */ + RTMPReportMicError(pAd, pKey); +#endif /* CONFIG_STA_SUPPORT */ + return FALSE; + } + + /* Update the total data length */ + *DataByteCnt = plaintext_len; + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, pHdr, DIR_READ, FALSE); +#endif + return TRUE; +} + +/* + ======================================================================== + + 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/mt7620/src/common/cmm_txbf.c b/mt7620/src/common/cmm_txbf.c new file mode 100644 index 0000000..9035846 --- /dev/null +++ b/mt7620/src/common/cmm_txbf.c @@ -0,0 +1,1226 @@ +/* + *************************************************************************** + * 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 */ + + +static inline VOID rtmp_asic_etxbf_write_change( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN bWriteEnable) +{ + UINT8 byteValue; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_REG_BF, &byteValue); + if (bWriteEnable) + byteValue |= 0x80; + else + byteValue &= (~0x80); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_REG_BF, byteValue); +} + + +VOID rtmp_asic_set_bf( + IN RTMP_ADAPTER *pAd) +{ + UINT8 byteValue = 0; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_REG_BF, &byteValue); + + /* Leave bit3 unchanged. It must be enabled to report BF SNR. */ + if (pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn) + byteValue |= 0x20; + else + byteValue &= (~0x20); + + if (pAd->CommonCfg.ETxBfEnCond) + byteValue |= 0x90; + else + byteValue &= ~0x90; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_REG_BF, byteValue); +} + +/* + 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) +{ + INT calIdx, calCnt; + USHORT offset, eeVal, *calptr; + 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}; + UINT32 ee_sum; + BOOLEAN bCalibrated = TRUE; + + + 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)); + } + + 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->bfState==READY_FOR_SNDG0 && 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); +} + + +/* + setETxBFCap - sets our ETxBF capabilities +*/ +void setETxBFCap( + IN PRTMP_ADAPTER pAd, + OUT 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; + pTxBFCap->NoComSteerBFAntSup = 2; + pTxBFCap->ComSteerBFAntSup = 2; + pTxBFCap->ChanEstimation = pAd->Antenna.field.RxPath-1; + } +} + + +#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) +{ + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; + MAC_TABLE_ENTRY *pEntry = NULL; + + if (pRxWI->WirelessCliID >= MAX_LEN_OF_MAC_TABLE) + { + return; + } + pEntry = &(pAd->MacTab.Content[pRxWI->WirelessCliID]); + + /* + 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", + pRxWI->WirelessCliID, + 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( + IN PRTMP_ADAPTER pAd, + IN 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; + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; + MAC_TABLE_ENTRY *pEntry = NULL; + UCHAR i, j; + PUCHAR 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; + PRTMP_TX_RATE_SWITCH_3S pLegalMfbRS3S = NULL; + PRTMP_TX_RATE_SWITCH pLegalMfbRS = NULL; + + if (pRxWI->WirelessCliID >= MAX_LEN_OF_MAC_TABLE) + { + return; + } + pEntry = &(pAd->MacTab.Content[pRxWI->WirelessCliID]); + + /* 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 = (PRTMP_TX_RATE_SWITCH_3S) &pTable[i*10]; + pLegalMfbRS = (PRTMP_TX_RATE_SWITCH) &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 = (PRTMP_TX_RATE_SWITCH) &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); + /* APMlmeSetTxRate(pAd, pEntry, pLegalMfbRS); */ + NdisMoveMemory(pEntry->LegalMfbRS, pLegalMfbRS, sizeof(RTMP_TX_RATE_SWITCH)); + 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 PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PRTMP_TX_RATE_SWITCH 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/mt7620/src/common/cmm_txbf_cal.c b/mt7620/src/common/cmm_txbf_cal.c new file mode 100644 index 0000000..a7b00ac --- /dev/null +++ b/mt7620/src/common/cmm_txbf_cal.c @@ -0,0 +1,2659 @@ +/* + *************************************************************************** + * 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 -------- +*/ + +#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 DBG +#ifdef LINUX +/* #define TIMESTAMP_CAL_CAPTURE0 */ +/* #define TIMESTAMP_CAL_CAPTURE1 */ +#endif /* LINUX */ +#endif /* DBG */ + +/* + DoCalibrationCapture - perform capture with specified BBP and RF register settings + txAnt - antenna to enable (0, 1 or 2). -1 enables all antennas + papdIQParam - table of PAPD IQ values. Optional, if NULL then PAPD is not used + lnaSettings - LNA settings for the 3 chains. LNA is encoded in b3:b2, same as R65 + r66Setting, r36r37Setting, r25Setting - Other BBP/RF reg settings +*/ +static void DoCalibrationCapture( + PRTMP_ADAPTER pAd, + int txAnt, + USHORT papdIQParam[3], + UCHAR lnaSettings[3], + UCHAR r66Setting, + USHORT r36r37Setting, + UCHAR r25Setting) +{ + UINT32 capCtrl; + UINT8 r25Value, r27Value, r65Value, r66Value[3], r186Value, r250Value, tmpValue; + UINT8 rf36Value, rf37Value; + + UINT16 papdIQ[3] = {0,0,0}; + BOOLEAN usePapd = FALSE; + + int i, j; +#ifdef TIMESTAMP_CAL_CAPTURE0 + struct timeval tval0, tval1, tval2; +#endif + + r25Value = r186Value = r65Value = r250Value = r27Value = tmpValue = 0; + + /* + For backwards compatibility txAnt: + 0, 1, 2 = only enable Ant0/1/2 + -1 = if no papd parameters then don't use papd. Otherwise read papd parameters + */ + if (txAnt==0 || txAnt==1 || txAnt==2) + { + papdIQ[txAnt] = 0x7F00; + usePapd = TRUE; + } + else if (papdIQParam != NULL) + { + papdIQ[0] = papdIQParam[0]; + papdIQ[1] = papdIQParam[1]; + papdIQ[2] = papdIQParam[2]; + usePapd = TRUE; + } + /* Read RF R25 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R25, &r25Value); + + /* Disable MAC Tx/Rx */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x00); + + /* Wait up to 50ms for MAC to empty queues */ + for (i=0; i<2500; i++) + { + UINT32 MacCsr12; + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacCsr12); + if ((MacCsr12 & 0x3)==0) + break; + RTMPusecDelay(20); + } + /*DBGPRINT(RT_DEBUG_ERROR, ("==>CalCap: i=%dus\n", i*20)); */ + + /* Disable Tx/Rx Queue */ + RTMP_IO_WRITE32(pAd, PBF_CFG, 0x00000000); + + /* Overwrite PAPD table and enable PAPD */ + if (usePapd) { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R186, &r186Value); + for (i=0; i<3; i++) { + for (j=0; j<32; j++) { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, (i<<6) | (j<<1)); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, (papdIQ[i]>>8) & 0xFF); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, (i<<6) | (j<<1) | 1); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, papdIQ[i] & 0xFF); + } + } + /* printk("PAPD = [%4x %4x %4x]\n", papdIQ[0], papdIQ[1], papdIQ[2]); */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x80); + } + + /* Enable Capture mode */ + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x00004E80); + +#ifdef TIMESTAMP_CAL_CAPTURE0 + do_gettimeofday(&tval0); +#endif + + /* Save and set LNA - BBP R65 and R250 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R65, &r65Value); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R250, &r250Value); + if (lnaSettings != NULL) { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R65, lnaSettings[0]); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R250, (r250Value & ~0x3c) | 0x40 | lnaSettings[1] | (lnaSettings[2]<<2)); + } + + /* Save and set R66 (VGA) */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R27, &r27Value); + for (i=0; i<3; i++) { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, (r27Value & ~0x60) | (i<<5)); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &r66Value[i]); + if (r66Setting != 0) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, r66Setting); + } + + /* Enable RF Loopback */ + RT30xxReadRFRegister(pAd, RF_R36, &rf36Value); + RT30xxWriteRFRegister(pAd, RF_R36, rf36Value | (r36r37Setting & 0xFF)); + RT30xxReadRFRegister(pAd, RF_R37, &rf37Value); + RT30xxWriteRFRegister(pAd, RF_R37, rf37Value | (r36r37Setting >> 8)); + + /* Initialize Capture. */ + capCtrl = 0; /* ADC capture. Offset=0 */ + RTMP_IO_WRITE32(pAd, PBF_CAP_CTRL, capCtrl | 0x40000000); + + /* Enable MAC RX, trigger capture and start RF loopback */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x08); + RTMP_IO_WRITE32(pAd, PBF_CAP_CTRL, capCtrl | 0x20000000); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R25, r25Value | r25Setting); + +#ifdef TIMESTAMP_CAL_CAPTURE0 + do_gettimeofday(&tval1); +#endif + + /* Wait up to 1ms for capture buffer to fill */ + for (i=0; i<20; i++) + { + RTMP_IO_READ32(pAd, PBF_CAP_CTRL, &capCtrl); + if ((capCtrl & 0x40000000)==0) + break; + RTMPusecDelay(50); + } + + /* Stop RX */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x00); + + /* Wait up to 5ms for RC Cal to finish */ + for (i=0; i<100; i++) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R25, &tmpValue); + if ((tmpValue & 0x10)==0) + break; + RTMPusecDelay(50); + } + + /* Restore BBP R65, R250, R66, R27, R186 and RF_R36 */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R65, r65Value); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R250, r250Value); + + for (i=0; i<3; i++) { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, (r27Value & ~0x60) | (i<<5)); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, r66Value[i]); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, r27Value); + + if (usePapd) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, r186Value); + + RT30xxWriteRFRegister(pAd, RF_R36, rf36Value); + RT30xxWriteRFRegister(pAd, RF_R37, rf37Value); + +#ifdef TIMESTAMP_CAL_CAPTURE0 + do_gettimeofday(&tval2); + + DBGPRINT(RT_DEBUG_WARN, ("DoCalibrationCapture c=%x, t1=%ld t2=%ld\n", capCtrl, + tval1.tv_usec - tval0.tv_usec, tval2.tv_usec - tval0.tv_usec)); +#endif + +} + + +/* + ReadCaptureData - Read capture data from MAC memory + iqData - used to return the data read. Array of samples for three RF chains + numSamples - the number of samples to read +*/ +static void ReadCaptureData(PRTMP_ADAPTER pAd, COMPLEX_VALUE iqData[][3], int numSamples) +{ + UINT32 CaptureStartAddr; + UINT32 PKT_Addr; + UINT32 SMM_Addr; + int i; + + /*********************************************************/ + /* Read [0x440] bit[12:0] */ + RTMP_IO_READ32(pAd, PBF_CAP_CTRL, &CaptureStartAddr); + CaptureStartAddr = CaptureStartAddr & 0x00001FFF; + + PKT_Addr = 0x8000+(CaptureStartAddr*4); + SMM_Addr = 0x4000+(CaptureStartAddr*2); + + for (i=0; i= 0x8000) SMM_Addr = SMM_Addr - 0x4000; + + RTMP_IO_READ32(pAd, PKT_Addr, &PKT1.Value); + PKT_Addr += 4; + if (PKT_Addr >= 0x10000) PKT_Addr = PKT_Addr - 0x8000; + + RTMP_IO_READ32(pAd, PKT_Addr, &PKT2.Value); + PKT_Addr += 4; + if (PKT_Addr >= 0x10000) PKT_Addr = PKT_Addr - 0x8000; + + /* Reorder samples so iqData[i][0] is Ant0, iqData[i][1] is Ant1, iqData[i][2] is Ant2 */ + iqData[i][2].i = SMM.field.BYTE0; + iqData[i][2].q = SMM.field.BYTE1; + iqData[i][1].i = PKT1.field.BYTE2; + iqData[i][1].q = PKT1.field.BYTE3; + iqData[i][0].i = PKT1.field.BYTE0; + iqData[i][0].q = PKT1.field.BYTE1; + if (++i >= numSamples) + break; + + iqData[i][2].i = SMM.field.BYTE2; + iqData[i][2].q = SMM.field.BYTE3; + iqData[i][1].i = PKT2.field.BYTE2; + iqData[i][1].q = PKT2.field.BYTE3; + iqData[i][0].i = PKT2.field.BYTE0; + iqData[i][0].q = PKT2.field.BYTE1; + } +} + + +/* + CaptureRFCal - Capture a single RF calibration loopback + iqData - returns 2048 samples of the 3 channels of IQ data + txAnt - selects active antenna (0, 1 or 2). -1 selects all +*/ +static void CaptureRFCal(PRTMP_ADAPTER pAd, COMPLEX_VALUE iqData[][3], int txAnt) +{ + UCHAR lnaValues[3] = {R65_LNA_HIGH, R65_LNA_HIGH, R65_LNA_HIGH}; + UCHAR channel = pAd->CommonCfg.Channel; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + channel = pAd->ate.Channel; +#endif /* RALINK_ATE */ + + DoCalibrationCapture(pAd, txAnt, NULL, lnaValues, channel<=14? 0x0e: 0x12, 0x70, 0x50); + + ReadCaptureData(pAd, iqData, DIVCAL_CAPTURE_LENGTH); +} + + +/* + DisplayCaptureData - Display capture data + iqData - 3 channels of IQ data + numSamples - number of samples to display +*/ +static void DisplayCaptureData(COMPLEX_VALUE iqData[][3], int numSamples) +{ + int i; + for (i=0; i= 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 +*/ +static void ITxBFDivParams(UCHAR divValues[2], int channel, ITXBF_DIV_PARAMS *divParams) +{ + if (channel <= 14) { + divValues[0] = InterpParam(channel, 1, 14, divParams->gBeg[0], divParams->gEnd[0]); + divValues[1] = InterpParam(channel, 1, 14, divParams->gBeg[1], divParams->gEnd[1]); + } + else if (channel <= 64) { + divValues[0] = divParams->aLow[0]; + divValues[1] = divParams->aLow[1]; + } + else if (channel <= 128) { + divValues[0] = divParams->aMid[0]; + divValues[1] = divParams->aMid[1]; + } + else { + divValues[0] = divParams->aHigh[0]; + divValues[1] = divParams->aHigh[1]; + } +} + + +/* + 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 +*/ +static void ITxBFLnaParams(UCHAR lnaValues[3], int channel, ITXBF_LNA_PARAMS *lnaParams) +{ + int i; + + if (channel <= 14) { + lnaValues[0] = InterpParam(channel, 1, 14, lnaParams->gBeg[0], lnaParams->gEnd[0]); + lnaValues[2] = InterpParam(channel, 1, 14, lnaParams->gBeg[1], lnaParams->gEnd[1]); + } + else if (channel <= 64) { + lnaValues[0] = InterpParam(channel, 36, 64, lnaParams->aLowBeg[0], lnaParams->aLowEnd[0]); + lnaValues[2] = InterpParam(channel, 36, 64, lnaParams->aLowBeg[1], lnaParams->aLowEnd[1]); + } + else if (channel <= 128) { + lnaValues[0] = InterpParam(channel, 100, 128, lnaParams->aMidBeg[0], lnaParams->aMidEnd[0]); + lnaValues[2] = InterpParam(channel, 100, 128, lnaParams->aMidBeg[1], lnaParams->aMidEnd[1]); + } + else { + lnaValues[0] = InterpParam(channel, 132, 165, lnaParams->aHighBeg[0], lnaParams->aHighEnd[0]); + lnaValues[2] = InterpParam(channel, 132, 165, lnaParams->aHighBeg[1], lnaParams->aHighEnd[1]); + } + + /* Compute L-H from M-H and M-L and quantize */ + lnaValues[1] = lnaValues[2]-lnaValues[0]; + for (i=0; i<3; i++) + lnaValues[i] = (lnaValues[i] + 0x8) & 0xF0; +} + + +/* + 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 +*/ +static void ITxBFPhaseParams(UCHAR phaseValues[2], int channel, ITXBF_PHASE_PARAMS *phaseParams) +{ + + if (channel <= 14) { + phaseValues[0] = InterpParam(channel, 1, 14, phaseParams->gBeg[0], phaseParams->gEnd[0]); + phaseValues[1] = InterpParam(channel, 1, 14, phaseParams->gBeg[1], phaseParams->gEnd[1]); + } + else if (channel <= 64) { + phaseValues[0] = InterpParam(channel, 36, 64, phaseParams->aLowBeg[0], phaseParams->aLowEnd[0]); + phaseValues[1] = InterpParam(channel, 36, 64, phaseParams->aLowBeg[1], phaseParams->aLowEnd[1]); + } + else if (channel <= 128) { + phaseValues[0] = InterpParam(channel, 100, 128, phaseParams->aMidBeg[0], phaseParams->aMidEnd[0]); + phaseValues[1] = InterpParam(channel, 100, 128, phaseParams->aMidBeg[1], phaseParams->aMidEnd[1]); + } + else { + phaseValues[0] = InterpParam(channel, 132, 165, phaseParams->aHighBeg[0], phaseParams->aHighEnd[0]); + phaseValues[1] = InterpParam(channel, 132, 165, phaseParams->aHighBeg[1], phaseParams->aHighEnd[1]); + } +} + + +#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 +*/ +void ITxBFGetEEPROM( + IN RTMP_ADAPTER *pAd, + IN ITXBF_PHASE_PARAMS *phaseParams, + IN ITXBF_LNA_PARAMS *lnaParams, + IN ITXBF_DIV_PARAMS *divParams) +{ + USHORT EE_Value[8], andValue; + int i; + + /* Get Phase parameters */ + if (phaseParams != NULL) { + /* Read and check for initialized values */ + andValue = 0xFFFF; + for (i=0; i<8; i++) { + RT28xx_EEPROM_READ16(pAd, EEPROM_ITXBF_CAL + 2*i, EE_Value[i]); + andValue &= EE_Value[i]; + } + + if (andValue == 0xFFFF) { + memset(phaseParams, 0, sizeof(*phaseParams)); + } else { + phaseParams->gBeg[0] = (EE_Value[0] & 0x00FF); + phaseParams->gBeg[1] = (EE_Value[0] & 0xFF00)>>8; + phaseParams->gEnd[0] = (EE_Value[1] & 0x00FF); + phaseParams->gEnd[1] = (EE_Value[1] & 0xFF00)>>8; + + phaseParams->aLowBeg[0] = (EE_Value[2] & 0x00FF); + phaseParams->aLowBeg[1] = (EE_Value[2] & 0xFF00)>>8; + phaseParams->aLowEnd[0] = (EE_Value[3] & 0x00FF); + phaseParams->aLowEnd[1] = (EE_Value[3] & 0xFF00)>>8; + phaseParams->aMidBeg[0] = (EE_Value[4] & 0x00FF); + phaseParams->aMidBeg[1] = (EE_Value[4] & 0xFF00)>>8; + phaseParams->aMidEnd[0] = (EE_Value[5] & 0x00FF); + phaseParams->aMidEnd[1] = (EE_Value[5] & 0xFF00)>>8; + phaseParams->aHighBeg[0] = (EE_Value[6] & 0x00FF); + phaseParams->aHighBeg[1] = (EE_Value[6] & 0xFF00)>>8; + phaseParams->aHighEnd[0] = (EE_Value[7] & 0x00FF); + phaseParams->aHighEnd[1] = (EE_Value[7] & 0xFF00)>>8; + } + } + + /* Get Divider Phase parameters */ + if (divParams != NULL) { + /* Read and check for initialized values */ + andValue = 0xFFFF; + for (i=0; i<5; i++) { + int eeAddr = i<3? EEPROM_ITXBF_CAL+16+2*i: EEPROM_ITXBF_CAL+38+(i-3)*2; + RT28xx_EEPROM_READ16(pAd, eeAddr, EE_Value[i]); + andValue &= EE_Value[i]; + } + + if (andValue == 0xFFFF) { + memset(divParams, 0, sizeof(*divParams)); + } + else { + divParams->gBeg[0] = (EE_Value[0] & 0x00FF); + divParams->gBeg[1] = (EE_Value[0] & 0xFF00)>>8; + divParams->gEnd[0] = (EE_Value[1] & 0x00FF); + divParams->gEnd[1] = (EE_Value[1] & 0xFF00)>>8; + + divParams->aLow[0] = (EE_Value[2] & 0x00FF); + divParams->aLow[1] = (EE_Value[2] & 0xFF00)>>8; + divParams->aMid[0] = (EE_Value[3] & 0x00FF); + divParams->aMid[1] = (EE_Value[3] & 0xFF00)>>8; + divParams->aHigh[0] = (EE_Value[4] & 0x00FF); + divParams->aHigh[1] = (EE_Value[4] & 0xFF00)>>8; + } + } + + /* Get LNA Parameters */ + if (lnaParams != NULL) { + /* Read and check for initialized values */ + andValue = 0xFFFF; + for (i=0; i<8; i++) { + RT28xx_EEPROM_READ16(pAd, EEPROM_ITXBF_CAL + 22 + 2*i, EE_Value[i]); + andValue &= EE_Value[i]; + } + + if (andValue == 0xFFFF) { + memset(lnaParams, 0, sizeof(*lnaParams)); + } + else { + lnaParams->gBeg[0] = (EE_Value[0] & 0x00FF); + lnaParams->gBeg[1] = (EE_Value[0] & 0xFF00)>>8; + lnaParams->gEnd[0] = (EE_Value[1] & 0x00FF); + lnaParams->gEnd[1] = (EE_Value[1] & 0xFF00)>>8; + + lnaParams->aLowBeg[0] = (EE_Value[2] & 0x00FF); + lnaParams->aLowBeg[1] = (EE_Value[2] & 0xFF00)>>8; + lnaParams->aLowEnd[0] = (EE_Value[3] & 0x00FF); + lnaParams->aLowEnd[1] = (EE_Value[3] & 0xFF00)>>8; + lnaParams->aMidBeg[0] = (EE_Value[4] & 0x00FF); + lnaParams->aMidBeg[1] = (EE_Value[4] & 0xFF00)>>8; + lnaParams->aMidEnd[0] = (EE_Value[5] & 0x00FF); + lnaParams->aMidEnd[1] = (EE_Value[5] & 0xFF00)>>8; + lnaParams->aHighBeg[0] = (EE_Value[6] & 0x00FF); + lnaParams->aHighBeg[1] = (EE_Value[6] & 0xFF00)>>8; + lnaParams->aHighEnd[0] = (EE_Value[7] & 0x00FF); + lnaParams->aHighEnd[1] = (EE_Value[7] & 0xFF00)>>8; + } + } +} + + +/* + 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) +{ + USHORT EE_Value[8], eeTmp; + int i, eeAddr; + + /* Set EEPROM parameters */ + + /* Phase parameters */ + if (phaseParams != NULL) { + EE_Value[0] = phaseParams->gBeg[0] | (phaseParams->gBeg[1]<<8); + EE_Value[1] = phaseParams->gEnd[0] | (phaseParams->gEnd[1]<<8); + + EE_Value[2] = phaseParams->aLowBeg[0] | (phaseParams->aLowBeg[1]<<8); + EE_Value[3] = phaseParams->aLowEnd[0] | (phaseParams->aLowEnd[1]<<8); + EE_Value[4] = phaseParams->aMidBeg[0] | (phaseParams->aMidBeg[1]<<8); + EE_Value[5] = phaseParams->aMidEnd[0] | (phaseParams->aMidEnd[1]<<8); + EE_Value[6] = phaseParams->aHighBeg[0] | (phaseParams->aHighBeg[1]<<8); + EE_Value[7] = phaseParams->aHighEnd[0] | (phaseParams->aHighEnd[1]<<8); + + for (i=0; i<8; i++) + { + eeAddr = EEPROM_ITXBF_CAL+2*i; + RT28xx_EEPROM_READ16(pAd, eeAddr, eeTmp); + if (eeTmp != EE_Value[i]) + RT28xx_EEPROM_WRITE16(pAd, eeAddr, EE_Value[i]); + } + } + + /* Divider Phase parameters */ + if (divParams != NULL) { + EE_Value[0] = divParams->gBeg[0] | (divParams->gBeg[1]<<8); + EE_Value[1] = divParams->gEnd[0] | (divParams->gEnd[1]<<8); + EE_Value[2] = divParams->aLow[0] | (divParams->aLow[1]<<8); + EE_Value[3] = divParams->aMid[0] | (divParams->aMid[1]<<8); + EE_Value[4] = divParams->aHigh[0] | (divParams->aHigh[1]<<8); + + for (i=0; i<5; i++) + { + eeAddr = i<3? EEPROM_ITXBF_CAL+16+2*i: EEPROM_ITXBF_CAL+38+(i-3)*2; + RT28xx_EEPROM_READ16(pAd, eeAddr, eeTmp); + if (eeTmp != EE_Value[i]) + RT28xx_EEPROM_WRITE16(pAd, eeAddr, EE_Value[i]); + } + } + + /* LNA Phase parameters */ + if (lnaParams != NULL) { + EE_Value[0] = lnaParams->gBeg[0] | (lnaParams->gBeg[1]<<8); + EE_Value[1] = lnaParams->gEnd[0] | (lnaParams->gEnd[1]<<8); + + EE_Value[2] = lnaParams->aLowBeg[0] | (lnaParams->aLowBeg[1]<<8); + EE_Value[3] = lnaParams->aLowEnd[0] | (lnaParams->aLowEnd[1]<<8); + EE_Value[4] = lnaParams->aMidBeg[0] | (lnaParams->aMidBeg[1]<<8); + EE_Value[5] = lnaParams->aMidEnd[0] | (lnaParams->aMidEnd[1]<<8); + EE_Value[6] = lnaParams->aHighBeg[0] | (lnaParams->aHighBeg[1]<<8); + EE_Value[7] = lnaParams->aHighEnd[0] | (lnaParams->aHighEnd[1]<<8); + + for (i=0; i<8; i++) + { + eeAddr = EEPROM_ITXBF_CAL+22+2*i; + RT28xx_EEPROM_READ16(pAd, eeAddr, eeTmp); + if (eeTmp != EE_Value[i]) + RT28xx_EEPROM_WRITE16(pAd, eeAddr, EE_Value[i]); + } + } +} + + +/* + ITxBFLoadLNAComp - load the LNA compensation registers +*/ +VOID ITxBFLoadLNAComp( + IN RTMP_ADAPTER *pAd) +{ + ITXBF_LNA_PARAMS lnaParams; + UCHAR lnaValues[3]; + UCHAR bbpValue = 0; + int i; + UCHAR channel = pAd->CommonCfg.Channel; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + channel = pAd->ate.Channel; +#endif /* RALINK_ATE */ + + /* Get values */ + ITxBFGetEEPROM(pAd, 0, &lnaParams, 0); + ITxBFLnaParams(lnaValues, channel, &lnaParams); + + /* Update R174 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R27, &bbpValue); + bbpValue &= ~0x60; + + for (i=0; i<3; i++) { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, bbpValue | (i<<5)); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R174, lnaValues[i]); + } + + /* Enable RX Phase Compensation */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R173, &bbpValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R173, bbpValue | 0x20); +} + + +/* + 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 +INT ITxBFDividerCalibration( + IN RTMP_ADAPTER *pAd, + IN int calFunction, + IN int calMethod, + OUT UCHAR *divPhase) +{ + int i; + ITXBF_DIV_PARAMS divParams; + UCHAR calRefValue[2]; + UCHAR channel = pAd->CommonCfg.Channel; + UCHAR newRefValue[2]; + LONG refValue[2]; + LONG phase[3][3]; + int avgI[3], avgQ[3]; + int peak[3][3]; + LONG d01, d21; + int result = TRUE; + + PCAP_IQ_DATA capIqData = NULL; + UINT32 *saveData = NULL; + UINT32 saveSysCtrl, savePbfCfg, saveMacSysCtrl, saveDmaCtrl; + + int allocSize = (calFunction==11? MAX_CAPTURE_LENGTH: DIVCAL_CAPTURE_LENGTH)*sizeof(COMPLEX_VALUE)*3; + + UCHAR r27Value, bbpValue; + UCHAR divPhaseValue[2]; + ITXBF_PHASE_PARAMS phaseParams; + UCHAR phaseValues[2]; + + BOOLEAN displayParams = (calFunction==0 || calFunction==10); + BOOLEAN gBand; +#ifdef TIMESTAMP_CAL_CAPTURE1 + struct timeval tval0, tval1, tval2, tval3, tval4, tval5; +#endif +#ifdef TIMESTAMP_CAL_CAPTURE1 + do_gettimeofday(&tval0); +#endif + + r27Value = bbpValue = 0; +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + channel = pAd->ate.Channel; +#endif /* RALINK_ATE */ + + gBand = channel<=14; + + //DBGPRINT(RT_DEBUG_ERROR, ("==> ITxBFDividerCalibration cf=%d cm=%d\n", calFunction, calMethod)); + + /* Handle optional divPhase parameter */ + if (divPhase == NULL) + divPhase = divPhaseValue; + + /* If calMethod is 0 then choose default method for the band */ + if (calMethod==0) + calMethod = channel<=14? 1: 2; + + /* Allocate buffer for capture data */ + capIqData = (PCAP_IQ_DATA) kmalloc(allocSize, MEM_ALLOC_FLAG); + if (capIqData == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__)); + return FALSE; + } + + /* Save MAC registers */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &saveMacSysCtrl); + RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &saveSysCtrl); + RTMP_IO_READ32(pAd, PBF_CFG, &savePbfCfg); + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &saveDmaCtrl); + + { + UINT32 dmaCfg, macCfg, macStatus, txrxPgcnt; + UINT32 DTxCycle, DRxCycle, MTxCycle, MRxCycle; + ULONG stTime, dt_time, dr_time, mt_time, mr_time; + + DTxCycle = DRxCycle = MTxCycle = MRxCycle = 0; + RTMP_IO_READ32(pAd, 0x438, &txrxPgcnt); + + /* Disable DMA Tx and wait DMA Tx status in idle state */ + NdisGetSystemUpTime(&stTime); + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &dmaCfg); + dmaCfg &= (~0x1); + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, dmaCfg); + for (DTxCycle = 0; DTxCycle < ITXBF_MAX_WAIT_CYCLE; DTxCycle++) + { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &dmaCfg); + if (dmaCfg & 0x2) + RTMPusecDelay(50); + else + break; + } + NdisGetSystemUpTime(&dt_time); + dt_time -= stTime; + if (DTxCycle == ITXBF_MAX_WAIT_CYCLE) + { + DBGPRINT(RT_DEBUG_WARN, ("%s(cnt=%d,time=0x%lx):stop DTx,dmaCfg=%d!\n", + __FUNCTION__, DTxCycle, dt_time, dmaCfg)); + } + + /* stop PBF txQ */ + RTMP_IO_WRITE32(pAd, PBF_CFG, (savePbfCfg & (~0x14))); + + /* 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 < ITXBF_MAX_WAIT_CYCLE; MTxCycle++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &macStatus); + if (macStatus & 0x1) + RTMPusecDelay(50); + else + break; + } + NdisGetSystemUpTime(&mt_time); + mt_time -= stTime; + if (MTxCycle == ITXBF_MAX_WAIT_CYCLE) + { + 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 < ITXBF_MAX_WAIT_CYCLE; MRxCycle++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &macStatus); + if (macStatus & 0x2) + RTMPusecDelay(50); + else + break; + } + NdisGetSystemUpTime(&mr_time); + mr_time -= stTime; + if (MRxCycle == ITXBF_MAX_WAIT_CYCLE) + { + DBGPRINT(RT_DEBUG_WARN, ("%s(cnt=%d,time=0x%lx):stop MRx, macStatus=%d!\n", + __FUNCTION__, MRxCycle, mr_time, macStatus)); + } + + /* stop PBF rxQ */ + RTMP_IO_WRITE32(pAd, PBF_CFG, (savePbfCfg & (~0x1e))); + + + /* Disable DMA Rx */ + NdisGetSystemUpTime(&stTime); + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &dmaCfg); + dmaCfg &= (~0x4); + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, dmaCfg); + for (DRxCycle = 0; DRxCycle < ITXBF_MAX_WAIT_CYCLE; DRxCycle++) + { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &dmaCfg); + if (dmaCfg & 0x8) + RTMPusecDelay(50); + else + break; + } + NdisGetSystemUpTime(&dr_time); + dr_time -= stTime; + if (DRxCycle == ITXBF_MAX_WAIT_CYCLE) + { + DBGPRINT(RT_DEBUG_WARN, ("%s(cnt=%d,time=0x%lx):stop DRx, dmaCfg=%d!\n", + __FUNCTION__, DRxCycle, dr_time, dmaCfg)); + } + + /* Check status */ + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &dmaCfg); + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &macStatus); + if ((dmaCfg & 0xa) || (macStatus & 0x3) || + (dt_time > 50) || (dr_time > 50) || (mr_time> 50) || (mt_time > 50)) + { + UINT32 txrxPgcnt2; + + RTMP_IO_READ32(pAd, 0x438, &txrxPgcnt2); + + DBGPRINT(RT_DEBUG_WARN, ("%s():After Disable DMA/MAC Tx/Rx, dmaBusy=%d,macBusy=%d!\n", + __FUNCTION__, (dmaCfg & 0xa), (macStatus & 0x3))); + DBGPRINT(RT_DEBUG_WARN, ("%s():DMA=>Tx(time:cycle)=(0x%lx:%d), Rx(time:cycle)=(0x%lx:%d)!\n", + __FUNCTION__, dt_time, DTxCycle, dr_time, DRxCycle)); + DBGPRINT(RT_DEBUG_WARN, ("%s():MAC=>Tx(time:cycle)=(0x%lx:%d), Rx(time:cycle)=(0x%lx:%d)!\n", + __FUNCTION__, mt_time, MTxCycle, mr_time, MRxCycle)); + DBGPRINT(RT_DEBUG_WARN, ("%s():PBF=>Original:0x%x, now:0x%x!\n", + __FUNCTION__, txrxPgcnt, txrxPgcnt2)); + } + } + + /* Save MAC data */ + saveData = ITxBFSaveData(pAd); + if (saveData == NULL) { + os_free_mem(pAd, capIqData); + + /* Restore MAC/DMA cfg register to HW */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, saveMacSysCtrl); + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, saveDmaCtrl); + return FALSE; + } + + /* Handle special mode */ + if (calFunction == 11) + { + /* Special mode - Capture all antennas without doing RF Calibration loopback. Leave LNA/VGA unchanged */ + DoCalibrationCapture(pAd, -1, NULL, NULL, 0, 0, 0); + ReadCaptureData(pAd, capIqData, MAX_CAPTURE_LENGTH); + DisplayCaptureData(capIqData, MAX_CAPTURE_LENGTH); + goto exitDivCal; + } + + /* Normal Divider Calibration mode */ + + /* Read Divider calibration values from EEPROM */ + ITxBFGetEEPROM(pAd, 0, 0, &divParams); + ITxBFDivParams(calRefValue, channel, &divParams); + refValue[0] = calRefValue[0]<0x40 && deltaPhase<0xC0) + newRefValue[0] -= 0x80; + deltaPhase = newRefValue[1] - divParams.aLow[1]; + if (deltaPhase>0x40 && deltaPhase<0xC0) + newRefValue[1] -= 0x80; + + divParams.aMid[0] = newRefValue[0]; + divParams.aMid[1] = newRefValue[1]; + } + else if (channel == 140) { + /* + Remove any 180 phase shift relative to Ch116. Needed if we + interpolate between Ch116 and Ch140. + */ + UCHAR deltaPhase; + + deltaPhase = newRefValue[0] - divParams.aMid[0]; + if (deltaPhase>0x40 && deltaPhase<0xC0) + newRefValue[0] -= 0x80; + deltaPhase = newRefValue[1] - divParams.aMid[1]; + if (deltaPhase>0x40 && deltaPhase<0xC0) + newRefValue[1] -= 0x80; + + divParams.aHigh[0] = newRefValue[0]; + divParams.aHigh[1] = newRefValue[1]; + } + else { + DBGPRINT(RT_DEBUG_ERROR, ("Invalid channel: %d\nMust calibrate channel 1, 14, 36, 116 or 140", channel) ); + result = FALSE; + goto exitDivCal; + } + + ITxBFSetEEPROM(pAd, 0, 0, &divParams); + 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); + ITxBFPhaseParams(phaseValues, channel, &phaseParams); + + /* Ant0 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R27, &r27Value); + r27Value &= ~0x60; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, r27Value); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R176, phaseValues[0]+divPhase[0]); + + /* Ant2 */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, r27Value | 0x40); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R176, phaseValues[1]+divPhase[1]); + + /* Enable TX Phase Compensation */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R173, &bbpValue); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R173, bbpValue | 0x08); + break; + + case 3: + /* Just return the Divider Phase */ + break; + + case 10: + /* Dump capture data */ + DisplayCaptureData(capIqData, DIVCAL_CAPTURE_LENGTH); + break; + + default: + result = FALSE; + break; + } + +exitDivCal: + /* Return to normal mode */ + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, saveSysCtrl); + + /* Restore MAC data */ + ITxBFRestoreData(pAd, saveData); + +#ifdef TIMESTAMP_CAL_CAPTURE1 + do_gettimeofday(&tval4); +#endif + + /* Restore registers */ + /* reset packet buffer */ + /* RTMP_IO_WRITE32(pAd, PBF_CTRL, 0x00000020); */ + + /* enable Tx/Rx Queue */ + RTMP_IO_WRITE32(pAd, PBF_CFG, savePbfCfg); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, saveMacSysCtrl); + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, saveDmaCtrl); + + /* Free data */ + if (saveData != NULL) + os_free_mem(pAd, saveData); + if (capIqData != NULL) + os_free_mem(pAd, capIqData); + +#ifdef TIMESTAMP_CAL_CAPTURE1 + do_gettimeofday(&tval5); + + DBGPRINT(RT_DEBUG_ERROR, ("%s t1=%ld t2=%ld t3=%ld t4=%ld t5=%ld\n", __FUNCTION__, + tval1.tv_usec - tval0.tv_usec, tval2.tv_usec - tval0.tv_usec, + tval3.tv_usec - tval0.tv_usec, tval4.tv_usec - tval0.tv_usec, + tval5.tv_usec - tval0.tv_usec)); +#endif + + return result; +} + +#define MAX_LNA_CAPS 10 /* Maximum number of LNA captures per calibration */ + + +/* + ITxBFOldLNACalCapLoop - do the old LNA capture loop (method 2). All Tx are active. + phase - returns capture phase results for three chains. One row for each capture. + peak - returns peak value results for three chains. One row for each capture. + capIqData - buffer to hold one capture + lnaValues - table of lnaValues for each chain + capCount - number of captures to do + displayParams - flag to enable display of intermediate results + calMethod - calibration method (used for debug display) +*/ +static void ITxBFOldLNACalCapLoop( + IN PRTMP_ADAPTER pAd, + IN LONG phase[][3], + IN int peak[][3], + IN PCAP_IQ_DATA capIqData, + IN UCHAR lnaValues[][3], + IN int capCount, + IN BOOLEAN displayParams, + IN int calMethod) +{ + int i; + int avgI[MAX_LNA_CAPS][3], avgQ[MAX_LNA_CAPS][3]; + UCHAR channel = pAd->CommonCfg.Channel; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + channel = pAd->ate.Channel; +#endif /* RALINK_ATE */ + + /* Do the LNA capture loop */ + for (i=0; iCommonCfg.Channel; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + channel = pAd->ate.Channel; +#endif /* RALINK_ATE */ + + for (i=0; itempPeak[1][0]? tempPeak[0][0]: tempPeak[1][0]; + peak[i][1] = tempPeak[0][1]>tempPeak[1][1]? tempPeak[0][1]: tempPeak[1][1]; + peak[i][2] = tempPeak[2][2]>tempPeak[3][2]? tempPeak[2][2]: tempPeak[3][2]; + } + if (displayParams) { + /* static char *lnaString[5] = {"M/M/M", "L /M/L ", "H/M/H", "L /L /L ", "H/H/H"}; */ + + DBGPRINT(RT_DEBUG_WARN, ("Diff LNA Method #%d\n", calMethod)); + + for (i=0; iCommonCfg.Channel; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + channel = pAd->ate.Channel; +#endif /* RALINK_ATE */ + + for (i=0; iDisplay cal param, + 1=>Update EEPROM and BBP, + 2=>Update BBP only, + 10=>Display and dump data + calMethod - the calibration method to use (0=default, 1=simple, 2=old, 3=diff, 4=oneTx) + gBand - specifies G band or A band + returns TRUE if no errors +*/ +int ITxBFLNACalibration( + IN RTMP_ADAPTER *pAd, + IN int calFunction, + IN int calMethod, + IN BOOLEAN gBand) +{ + PCAP_IQ_DATA capIqData; + UINT32 *saveData, saveSysCtrl, savePbfCfg, saveMacSysCtrl; + + LONG phase[2]; + LONG mPhase[MAX_LNA_CAPS]; + LONG cap[MAX_LNA_CAPS][3]; + + static UCHAR lnaValuesOneTx[9][3] = { + {R65_LNA_MID, R65_LNA_MID, R65_LNA_MID}, + {R65_LNA_LOW, R65_LNA_MID, R65_LNA_MID}, + {R65_LNA_HIGH, R65_LNA_MID, R65_LNA_MID}, + {R65_LNA_MID, R65_LNA_MID, R65_LNA_MID}, + {R65_LNA_MID, R65_LNA_LOW, R65_LNA_MID}, + {R65_LNA_MID, R65_LNA_HIGH, R65_LNA_MID}, + {R65_LNA_MID, R65_LNA_MID, R65_LNA_MID}, + {R65_LNA_MID, R65_LNA_MID, R65_LNA_LOW}, + {R65_LNA_MID, R65_LNA_MID, R65_LNA_HIGH}}; + static USHORT papdIQOneTx[9][3] = { + {0x7f00, 0x0000, 0x0000}, + {0x7f00, 0x0000, 0x0000}, + {0x7f00, 0x0000, 0x0000}, + {0x0000, 0x7f00, 0x0000}, + {0x0000, 0x7f00, 0x0000}, + {0x0000, 0x7f00, 0x0000}, + {0x0000, 0x0000, 0x7f00}, + {0x0000, 0x0000, 0x7f00}, + {0x0000, 0x0000, 0x7f00}}; + + static UCHAR lnaValues5[5][3] = { + {R65_LNA_MID, R65_LNA_MID, R65_LNA_MID}, + {R65_LNA_LOW, R65_LNA_MID, R65_LNA_LOW}, + {R65_LNA_HIGH, R65_LNA_MID, R65_LNA_HIGH}, + {R65_LNA_LOW, R65_LNA_LOW, R65_LNA_LOW}, + {R65_LNA_HIGH, R65_LNA_HIGH, R65_LNA_HIGH}}; + static UCHAR lnaValues2[2][3] = { + {R65_LNA_MID, R65_LNA_MID, R65_LNA_MID}, + {R65_LNA_LOW, R65_LNA_MID, R65_LNA_HIGH}}; + + int peak[MAX_LNA_CAPS][3]; + int txAntennas = pAd->Antenna.field.TxPath; /* # of Tx Antennas */ + UCHAR channel = pAd->CommonCfg.Channel; + + ITXBF_LNA_PARAMS lnaParams; + UCHAR quantPhase[3], hexPhaseValues[2]; + UCHAR bbpValue = 0; + BOOLEAN displayParams = (calFunction==0 || calFunction==10); + int result = TRUE; + int i; +#ifdef TIMESTAMP_CAL_CAPTURE1 + struct timeval tval0, tval1, tval2, tval3, tval4; +#endif + +#ifdef TIMESTAMP_CAL_CAPTURE1 + do_gettimeofday(&tval0); +#endif + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + channel = pAd->ate.Channel; +#endif /* RALINK_ATE */ + + /* Default is Method 4 */ + if (calMethod <= 0) + calMethod = 4; + + /* Allocate buffer for capture data */ + capIqData = (PCAP_IQ_DATA) kmalloc(DIVCAL_CAPTURE_LENGTH*sizeof(COMPLEX_VALUE)*3, MEM_ALLOC_FLAG); + if (capIqData == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__)); + return FALSE; + } + + /* Save MAC data */ + saveData = ITxBFSaveData(pAd); + if (saveData == NULL) { + os_free_mem(pAd, capIqData); + return FALSE; + } + + /* Save MAC registers */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &saveMacSysCtrl); + RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &saveSysCtrl); + RTMP_IO_READ32(pAd, PBF_CFG, &savePbfCfg); + + /* Do LNA Calibration. */ + switch (calMethod) { + case 1: + /* Method 1. Two Measurements. */ + ITxBFOldLNACalCapLoop(pAd, cap, peak, capIqData, lnaValues2, 2, displayParams, calMethod); + + /* Compute LNA Compensation parameters */ + phase[0] = cap[0][0]-cap[1][0]; /* A0-B0 = M-L */ + phase[1] = cap[0][2]-cap[1][2]; /* A2-B2 = M-H */ + break; + + case 2: + case 3: + /* Method 2. Five Measurements. */ + if (calMethod == 3) + ITxBFDiffLNACalCapLoop(pAd, cap, peak, capIqData, lnaValues5, 5, displayParams, calMethod); + else + ITxBFOldLNACalCapLoop(pAd, cap, peak, capIqData, lnaValues5, 5, displayParams, calMethod); + + if (txAntennas == 2) { + for (i=0; i<5; i++) + cap[i][2] = 0; + } + + /* Derive LNA Compensation values by averaging M-L and M-H for each chain. */ + mPhase[0] = radMod2pi(-cap[1][0]+cap[0][0]); /* Mid-low */ + mPhase[1] = radMod2pi(cap[3][0]-cap[1][0]); + mPhase[2] = radMod2pi(-cap[1][2]+cap[0][2]); + mPhase[3] = radMod2pi(-cap[2][0]+cap[0][0]); /* Mid-High */ + mPhase[4] = radMod2pi(cap[4][0]-cap[2][0]); + mPhase[5] = radMod2pi(-cap[2][2]+cap[0][2]); + + phase[0] = avgPhase(mPhase, txAntennas); + phase[1] = avgPhase(mPhase+3, txAntennas); + /* Display table of LNA phase vs Ant */ + if (displayParams) { + DBGPRINT(RT_DEBUG_WARN, ( + "Phase vs Ant (deg) Ch%02d\n" + " L [%1d %1d/%1d %1d] = %1d\n" + " H [%1d %1d/%1d %1d] = %1d\n", + channel, + DEG180(mPhase[0]), DEG180(mPhase[1]), DEG180(cap[3][2]-cap[1][2]), + DEG180(mPhase[2]), DEG180(phase[0]), + DEG180(mPhase[3]), DEG180(mPhase[4]), DEG180(cap[4][2]-cap[2][2]), + DEG180(mPhase[5]), DEG180(phase[1]) ) ); + } + break; + + default: + /* Method 4. Nine captures with only one Tx enabled for each capture */ + ITxBFLNACalCapLoop(pAd, cap, peak, capIqData, papdIQOneTx, lnaValuesOneTx, txAntennas==2? 6: 9, displayParams, calMethod); + + if (txAntennas == 2) { + for (i=0; i<9; i++) { + if (i >= 6) + cap[i][0] = cap[i][1] = 0; + cap[i][2] = 0; + } + } + + /* Calculate M-L and M-H for each chain */ + /* Mid-Low. */ + mPhase[0] = radMod2pi(cap[0][0]-cap[1][0]); + mPhase[1] = radMod2pi(cap[4][0]-cap[3][0]); + if (txAntennas == 3) { + mPhase[2] = radMod2pi(cap[4][2]-cap[3][2]); + mPhase[1] = avgPhase(mPhase+1, 2); + } + mPhase[2] = radMod2pi(cap[6][2]-cap[7][2]); + + /* High-Mid */ + mPhase[3] = radMod2pi(cap[0][0]-cap[2][0]); + mPhase[4] = radMod2pi(cap[5][0]-cap[3][0]); + if (txAntennas == 3) { + mPhase[5] = radMod2pi(cap[5][2]-cap[3][2]); + mPhase[4] = avgPhase(mPhase+4, 2); + } + mPhase[5] = radMod2pi(cap[6][2]-cap[8][2]); + + /* Derive LNA Compensation values by averaging M-L and M-H for each chain. */ + phase[0] = avgPhase(mPhase, txAntennas); + phase[1] = avgPhase(mPhase+3, txAntennas); + + if (displayParams) { + DBGPRINT(RT_DEBUG_WARN, ( + "Phase vs Ant (deg) Ch%02d\n" + " L : (a-b/e-d/g-h) [%1d, %1d/%1d, %1d] = %1d\n" + " H: (a-c/f-d/g-i) [%1d, %1d/%1d, %1d] = %1d\n\n", + channel, DEG180(mPhase[0]), + DEG180(cap[4][0]-cap[3][0]), DEG180(cap[4][2]-cap[3][2]), + DEG180(mPhase[2]), DEG180(phase[0]), + DEG180(mPhase[3]), + DEG180(cap[5][0]-cap[3][0]), DEG180(cap[5][2]-cap[3][2]), + DEG180(mPhase[5]), DEG180(phase[1]) ) ); + } + break; + } + + /* Calculate hex phase correction */ + hexPhaseValues[0] = CONVERT_TO_BYTE_PHASE(phase[0]); /* M-L */ + hexPhaseValues[1] = -CONVERT_TO_BYTE_PHASE(phase[1]); /* H-M */ + + /* Calulate LNA compensation and quantize to 4 bits */ + quantPhase[0] = hexPhaseValues[0]; /* M-L */ + quantPhase[1] = hexPhaseValues[1]-hexPhaseValues[0]; /* H-L */ + quantPhase[2] = hexPhaseValues[1]; /* H-M */ + + for (i=0; i<3; i++) + quantPhase[i] = (quantPhase[i] + 0x8) & 0xF0; + + /* Either display parameters, update EEPROM and BBP registers or dump capture data */ + switch (calFunction) { + case 0: + DBGPRINT(RT_DEBUG_WARN, ("M-L/H-L/H-M: [%d %d %d] deg = [0x%02X 0x%02X]\n" + "R174: [%d %d %d] deg = [%02x %02x %02x]\n", + DEG(phase[0]), DEG(phase[0]+phase[1]), DEG(phase[1]), + hexPhaseValues[0], hexPhaseValues[1], + quantPhase[0]*360/256, quantPhase[1]*360/256, quantPhase[2]*360/256, + quantPhase[0], quantPhase[1], quantPhase[2]) ); + break; + + case 1: + /* Save new reference values in EEPROM and BBP */ + ITxBFGetEEPROM(pAd, 0, &lnaParams, 0); + + /* Only allow calibration on specific channels */ + if (channel == 1) { + lnaParams.gBeg[0] = hexPhaseValues[0]; + lnaParams.gBeg[1] = hexPhaseValues[1]; + } + else if (channel == 14) { + lnaParams.gEnd[0] = hexPhaseValues[0]; + lnaParams.gEnd[1] = hexPhaseValues[1]; + } + else if (channel == 36) { + lnaParams.aLowBeg[0] = hexPhaseValues[0]; + lnaParams.aLowBeg[1] = hexPhaseValues[1]; + } + else if (channel == 64) { + lnaParams.aLowEnd[0] = hexPhaseValues[0]; + lnaParams.aLowEnd[1] = hexPhaseValues[1]; + } + else if (channel == 100) { + lnaParams.aMidBeg[0] = hexPhaseValues[0]; + lnaParams.aMidBeg[1] = hexPhaseValues[1]; + } + else if (channel == 128) { + lnaParams.aMidEnd[0] = hexPhaseValues[0]; + lnaParams.aMidEnd[1] = hexPhaseValues[1]; + } + else if (channel == 132) { + lnaParams.aHighBeg[0] = hexPhaseValues[0]; + lnaParams.aHighBeg[1] = hexPhaseValues[1]; + } + else if (channel == 165) { + lnaParams.aHighEnd[0] = hexPhaseValues[0]; + lnaParams.aHighEnd[1] = hexPhaseValues[1]; + } + else { + DBGPRINT(RT_DEBUG_OFF, + ("Invalid channel: %d\nMust calibrate channel 1, 14, 36, 64, 100, 128, 132 or 165", channel) ); + result = FALSE; + goto exitLnaCal; + } + + ITxBFSetEEPROM(pAd, 0, &lnaParams, 0); + /* FALL THROUGH to update BBP */ + case 2: + /* Update BBP */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R27, &bbpValue); + bbpValue &= ~0x60; + + /* Update R174 registers */ + for (i=0; i<3; i++) { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, bbpValue | (i<<5)); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R174, quantPhase[i]); + } + break; + + case 10: + /* Dump capture data */ + DisplayCaptureData(capIqData, DIVCAL_CAPTURE_LENGTH); + break; + + default: + result = FALSE; + break; + } + +exitLnaCal: + /* Return to normal mode */ + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, saveSysCtrl); + + /* Restore MAC data */ + ITxBFRestoreData(pAd, saveData); +#ifdef TIMESTAMP_CAL_CAPTURE1 + do_gettimeofday(&tval3); +#endif + /* Restore registers */ + /* reset packet buffer */ + RTMP_IO_WRITE32(pAd, PBF_CTRL, 0x00000020); + + /* enable Tx/Rx Queue */ + RTMP_IO_WRITE32(pAd, PBF_CFG, savePbfCfg); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, saveMacSysCtrl); + +#ifdef TIMESTAMP_CAL_CAPTURE1 + do_gettimeofday(&tval4); + + printk("%s t1=%ld t2=%ld t3=%ld t4=%ld\n", __FUNCTION__, + tval1.tv_usec - tval0.tv_usec, tval2.tv_usec - tval0.tv_usec, + tval3.tv_usec - tval0.tv_usec, tval4.tv_usec - tval0.tv_usec); +#endif + + /* Free data */ + os_free_mem(pAd, saveData); + os_free_mem(pAd, capIqData); + + return result; +} + + +/* ------------ BEAMFORMING PROFILE HANDLING ------------ */ +static SC_TABLE_ENTRY impSubCarrierTable[2] = { {36, 63, 1, 28}, {70, 126, 2, 58} }; +static SC_TABLE_ENTRY expSubCarrierTable[2] = { {100, 127, 1, 28}, {70, 126, 2, 58} }; + +PROFILE_DATA profData; + +/* Read_TagField - read a profile tagfield */ +void Read_TagField( + IN PRTMP_ADAPTER pAd, + IN UCHAR *row, + IN int profileNum) +{ + int byteIndex; + + /* Assume R179 has already been set to select Explicit or Implicit profiles */ + + /* Read a tagfield */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R181, 0x80); + for (byteIndex=0; byteIndex= 0; ) + DBGPRINT(RT_DEBUG_OFF, ("%02X ", row[byteIndex])); + + /* Decode the tag */ + DBGPRINT(RT_DEBUG_OFF, (" - ")); + if (implicitProfile) { + static char *modeTable[8] = {"INV", "1 Leg", "1 HT", "2 HT", "INV", "INV", "INV", "INV"}; + static char *bwTable[8] = {"20M", "10M", "40Mh", "INV", "INV", "INV", "40Mf", "INV"}; + int mode = (row[7]>>4) & 0x7; + + switch (mode) { + case 1: + case 2: + case 3: + DBGPRINT(RT_DEBUG_OFF, ("%s %dx%s %c", bwTable[row[7] & 0x7], + (row[0] & 0x3)+1, modeTable[mode], (row[7] & 0x80)? 'S': 'L') ); + break; + default: + DBGPRINT(RT_DEBUG_OFF, ("Invalid")); + } + } + else { + static char *tagTable[16] = { + "INV", "INV", "INV", "INV", "2x1", "2x2", "INV", "INV", + "3x1", "3x2", "3x3", "INV", "INV", "INV", "INV", "INV"}; + switch (row[7] & 0xF) { + case 4: + case 5: + case 8: + case 9: + case 10: + DBGPRINT(RT_DEBUG_OFF, ("%2dM %s", (row[7] & 0x10)? 40: 20, tagTable[row[7] & 0xF]) ); + break; + default: + DBGPRINT(RT_DEBUG_OFF, ("Invalid")); + } + } + DBGPRINT(RT_DEBUG_OFF, ("\n")); +} + + +/* + Unpack an ITxBF matrix element from a row of bytes +*/ +int Unpack_IBFValue( + IN UCHAR *row, + IN int elemNum) +{ + int bitNum, byteOffset, bitOffset; + int val; + + bitNum = elemNum*IMP_COEFF_SIZE; + byteOffset = bitNum/8; + bitOffset = bitNum - byteOffset*8; + + val = row[byteOffset] | (row[byteOffset+1]<<8); + val = (val>>bitOffset) & IMP_COEFF_MASK; + if (val >= 1<<(IMP_COEFF_SIZE-1) ) + val -= 1<> 8) & 0xFF; +} + + +/* + Read_BFRow - read a row from a BF profile +*/ +void Read_BFRow( + IN PRTMP_ADAPTER pAd, + IN UCHAR *row, + IN int profileNum, + IN int rowIndex, + IN int bytesPerRow) +{ + int byteIndex; + + /* Assume R179 has already been set to select Explicit or Implicit profiles */ + + /* Read a row of data */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R181, rowIndex); + + for (byteIndex=0; byteIndex data[carrierIndex]; + + /* Optimize the number of bytes written */ + if (pExp->impProfile) + bytesPerRow = pExp->columns==1? IMP_MAX_BYTES_ONE_COL: IMP_MAX_BYTES; + else + bytesPerRow = EXP_MAX_BYTES; + + /* Assume R179 has already been set to select Explicit or Implicit profiles */ + + /* Write a row of data */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R181, rowIndex); + + for (byteIndex=0; byteIndex tag, profileNum); + + if (implicitProfile) { + prof->impProfile = TRUE; + prof->fortyMHz = (prof->tag[7] & 0x7)==6; + + switch (prof->tag[0] & 0x3) + { + case 0: + prof->rows = 1; + break; + case 1: + prof->rows = 2; + break; + default: + prof->rows = 3; + break; + } + + prof->columns = (prof->tag[7] & 0x70)==0x30? 2: 1; + prof->grouping = 1; + + /* Read subcarrier data */ + pTab = &impSubCarrierTable[prof->fortyMHz]; + maxBytes = prof->columns==1? IMP_MAX_BYTES_ONE_COL: IMP_MAX_BYTES; + + /* Negative subcarriers */ + carrierIndex = 0; + for (scIndex=pTab->lwb1; scIndex <= pTab->upb1; scIndex++) + Read_BFRow(pAd, prof->data[carrierIndex++], profileNum, scIndex, maxBytes); + + /* Positive subcarriers */ + for (scIndex=pTab->lwb2; scIndex <= pTab->upb2; scIndex++) + Read_BFRow(pAd, prof->data[carrierIndex++], profileNum, scIndex, maxBytes); + } + else { + prof->impProfile = FALSE; + prof->fortyMHz = (prof->tag[7] & 0x10)!=0; + prof->rows = 1 + (prof->tag[7]>>2 & 0x3); + prof->columns = 1 + (prof->tag[7] & 0x03); + + switch (prof->tag[7] & 0x60) { + case 0x20: + prof->grouping = 2; + break; + case 0x40: + prof->grouping = 4; + break; + default: /* 1 or invalid values */ + prof->grouping = 1; + break; + } + + /* Read subcarrier data */ + pTab = &expSubCarrierTable[prof->fortyMHz]; + carrierIndex = 0; + + /* Negative subcarriers */ + for (scIndex=pTab->lwb1; scIndex < pTab->upb1; scIndex += prof->grouping) { + c = carrierIndex; + Read_BFRow(pAd, prof->data[carrierIndex++], profileNum, scIndex, EXP_MAX_BYTES); + + /* + Replicate data if subcarriers are grouped. For 20Mhz the last carrier requires + special handling to make sure it isn't overwritten when replicating the data + */ + for (j=1; jgrouping; j++) { + if (!prof->fortyMHz && carrierIndex==(PROFILE_MAX_CARRIERS_20/2 - 1)) + break; + memcpy(prof->data[carrierIndex++], prof->data[c], sizeof(prof->data[c])); + } + } + Read_BFRow(pAd, prof->data[carrierIndex++], profileNum, pTab->upb1, EXP_MAX_BYTES); + + /* Positive subcarriers */ + for (scIndex=pTab->lwb2; scIndex < pTab->upb2; scIndex += prof->grouping) { + c = carrierIndex; + Read_BFRow(pAd, prof->data[carrierIndex++], profileNum, scIndex, EXP_MAX_BYTES); + + /* + Replicate data if subcarriers are grouped. For 20Mhz the last carrier requires + special handling to make sure it isn't overwritten when replicating the data + */ + for (j=1; jgrouping; j++) { + if (!prof->fortyMHz && carrierIndex==(PROFILE_MAX_CARRIERS_20-1)) + break; + memcpy(prof->data[carrierIndex++], prof->data[c], sizeof(prof->data[c])); + } + } + Read_BFRow(pAd, prof->data[carrierIndex++], profileNum, pTab->upb2, EXP_MAX_BYTES); + } + + /* Restore Profile Updates */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R163, r163Value); + +#ifdef TIMESTAMP_BF_PROFILE + do_gettimeofday(&tval2); + DBGPRINT(RT_DEBUG_WARN, ("BF Read elasped = %ld usec\n", tval2.tv_usec - tval1.tv_usec)); +#endif +} + + +void Write_TxBfProfile( + IN PRTMP_ADAPTER pAd, + IN PROFILE_DATA *prof, + IN int profileNum) +{ + int carrierIndex, scIndex; + SC_TABLE_ENTRY *pTab; + int maxBytes; + UCHAR r163Value = 0; +#ifdef TIMESTAMP_BF_PROFILE + struct timeval tval1, tval2; + do_gettimeofday(&tval1); +#endif + + /* Disable Profile Updates during access */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R163, &r163Value); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R163, r163Value & ~0x88); + + /* Select Implicit/Explicit profile */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R179, prof->impProfile? 0: 0x04); + + /* Write Tagfield format byte so it matches the profile */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R181, 0x80); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R180, (profileNum<<5) | 0x7); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R182, profData.tag[7]); + + /* Write Implicit or Explicit profile */ + if (prof->impProfile) { + /* Write subcarrier data */ + pTab = &impSubCarrierTable[profData.fortyMHz]; + maxBytes = profData.columns==1? IMP_MAX_BYTES_ONE_COL: IMP_MAX_BYTES; + + carrierIndex = 0; + for (scIndex=pTab->lwb1; scIndex <= pTab->upb1; scIndex++) + Write_BFRow(pAd, profileNum, scIndex, &profData, carrierIndex++); + + for (scIndex=pTab->lwb2; scIndex <= pTab->upb2; scIndex++) + Write_BFRow(pAd, profileNum, scIndex, &profData, carrierIndex++); + } + else { + /* Write subcarrier data. If data is grouped then just write every n-th subcarrier */ + pTab = &expSubCarrierTable[profData.fortyMHz]; + carrierIndex = 0; + + /* Negative subcarriers */ + for (scIndex=pTab->lwb1; scIndexupb1; scIndex += profData.grouping) { + Write_BFRow(pAd, profileNum, scIndex, &profData, carrierIndex); + carrierIndex += profData.grouping; + } + /* In 20MHz mode the last carrier in the group is a special case */ + if (!profData.fortyMHz) + carrierIndex--; + Write_BFRow(pAd, profileNum, pTab->upb1, &profData, carrierIndex++); + + /* Positive subcarriers */ + for (scIndex=pTab->lwb2; scIndexupb2; scIndex += profData.grouping) { + Write_BFRow(pAd, profileNum, scIndex, &profData, carrierIndex); + carrierIndex += profData.grouping; + } + if (!profData.fortyMHz) + carrierIndex--; + Write_BFRow(pAd, profileNum, pTab->upb2, &profData, carrierIndex); + } + + /* Restore Profile Updates */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R163, r163Value); + +#ifdef TIMESTAMP_BF_PROFILE + do_gettimeofday(&tval2); + DBGPRINT(RT_DEBUG_WARN, ("BF Write elasped = %ld usec\n", tval2.tv_usec - tval1.tv_usec)); +#endif +} + + +#ifdef DBG +#ifdef LINUX +/* #define TIMESTAMP_CALC_CALIBRATION */ +#endif /* LINUX */ +#endif /* DBG */ + +#define P_RESOLUTION 256 /* Resolution of phase calculation: 2pi/256 */ + +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 +*/ +int iCalcCalibration(PRTMP_ADAPTER pAd, int calParams[2], int profileNum) +{ + int pi, maxCarriers, ii; + + short rot[2], rot1[2]; + INT32 c0[2], c1[2]; + INT32 minSum=0; + int di1=0, di2=0; + + PROFILE_DATA *pExpData, *pImpData; + int result = 0; +#ifdef TIMESTAMP_CALC_CALIBRATION + struct timeval tval1, tval2; +#endif + + if (os_alloc_mem(pAd, (UCHAR **)&pExpData, sizeof(PROFILE_DATA))!= NDIS_STATUS_SUCCESS) + { + return -3; + } + + if (os_alloc_mem(pAd, (UCHAR **)&pImpData, sizeof(PROFILE_DATA)) != NDIS_STATUS_SUCCESS) + { + os_free_mem(pAd, pExpData); + return -3; + } + /* Read Implicit and Explicit data */ + Read_TxBfProfile(pAd, pImpData, profileNum, TRUE); + Read_TxBfProfile(pAd, pExpData, profileNum, FALSE); + + hex_dump("pImpData", &pImpData->tag[1], 6); + hex_dump("pExpData", &pExpData->tag[1], 6); + + /* Quit if MAC addresses don't match */ + for (ii=1; ii<7; ii++) { + if (pImpData->tag[ii]!=pExpData->tag[ii]) { + result = -2; + goto exitCalcCal; + } + } + + /* Quit if profiles cannot be used */ + if (pImpData->fortyMHz!=pExpData->fortyMHz || pImpData->rows<2 || pExpData->rows<2) { + result = -1; + goto exitCalcCal; + } + + /* + If Implicit profile is legacy then zero out the unused carriers so they don't + affect the calculation + */ + if ((pImpData->tag[7] & 0x70)==0x10) { + 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 = pImpData->fortyMHz? PROFILE_MAX_CARRIERS_40: PROFILE_MAX_CARRIERS_20; + + /* Compute Exp .* conj(Imp). ei0 is 2p25, ei1 and ei2 are are 2p15 */ + for (pi=0; pidata[pi][0])<<10; + ed[1] = ((CHAR)pExpData->data[pi][1])<<10; + icMult(ei0[pi], ed, Unpack_IBFValue(pImpData->data[pi], 1), -Unpack_IBFValue(pImpData->data[pi], 0)); + ed[0] = (CHAR)pExpData->data[pi][6]; + ed[1] = (CHAR)pExpData->data[pi][7]; + icMult(ei1[pi], ed, Unpack_IBFValue(pImpData->data[pi], 3), -Unpack_IBFValue(pImpData->data[pi], 2)); + ed[0] = (CHAR)pExpData->data[pi][12]; + ed[1] = (CHAR)pExpData->data[pi][13]; + icMult(ei2[pi], ed, Unpack_IBFValue(pImpData->data[pi], 5), -Unpack_IBFValue(pImpData->data[pi], 4)); + } + + /* Search for best Phase 1 */ + for (ii=0; ii 1p13 */ + c0[0] = (ei0[pi][0] + c1[0])>>12; + c0[1] = (ei0[pi][1] + c1[1])>>12; + sum -= isqrt(c0[0]*c0[0] + c0[1]*c0[1]); + } + /* ATEDBGPRINT(RT_DEBUG_OFF, ("%d s=%d %d %d\n", ii, sum, c0[0], c1[0])); */ + + /* Record minimum */ + if (ii==0 || minSum>sum) { + di1 = ii; + minSum = sum; + } + } + + /* Search for best Phase 2 */ + if (pImpData->rows==2 || pExpData->rows==2) { + di2 = 0; + } + else { + icexp(rot1, di1); + /* ei0 = ei0 + rot1*ei1 */ + for (pi=0; pi 1p13 */ + icMult(c1, ei2[pi], rot[0], rot[1]); + c0[0] = (ei0[pi][0] + c1[0]) >> 12; + c0[1] = (ei0[pi][1] + c1[1]) >> 12; + sum -= isqrt(c0[0]*c0[0] + c0[1]*c0[1]); + } + + /* Record minimum */ + if (ii==0 || minSum>sum) { + di2 = ii; + minSum = sum; + } + } + } + + /* Convert to calibration parameters */ + calParams[0] = -di1 & 0xFF; + calParams[1] = -(di1-di2) & 0xFF; + +#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); + + return result; +} + diff --git a/mt7620/src/common/cmm_video.c b/mt7620/src/common/cmm_video.c new file mode 100644 index 0000000..d3ca5be --- /dev/null +++ b/mt7620/src/common/cmm_video.c @@ -0,0 +1,193 @@ +/**************************************************************************** + * 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; + +#ifdef RT3883 + if (IS_RT3883(pAd)) + { + RTMP_IO_READ32(pAd, TX_AC_RTY_LIMIT, &MacReg); + MacReg = 0x0f1f0f0f; + RTMP_IO_WRITE32(pAd, TX_AC_RTY_LIMIT, MacReg); + + RTMP_IO_READ32(pAd, TX_AC_FBK_SPEED, &MacReg); + MacReg = 0x06000003; + RTMP_IO_WRITE32(pAd, TX_AC_FBK_SPEED, MacReg); + } + else +#endif /* RT3883 */ + { + /* 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; + +#ifdef RT3883 + if (IS_RT3883(pAd)) + { + RTMP_IO_READ32(pAd, TX_AC_RTY_LIMIT, &MacReg); + MacReg = 0x07070707; + RTMP_IO_WRITE32(pAd, TX_AC_RTY_LIMIT, MacReg); + + RTMP_IO_READ32(pAd, TX_AC_FBK_SPEED, &MacReg); + MacReg = 0x0; + RTMP_IO_WRITE32(pAd, TX_AC_FBK_SPEED, MacReg); + } +#endif /* RT3883 */ + + /* 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_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/mt7620/src/common/cmm_wep.c b/mt7620/src/common/cmm_wep.c new file mode 100644 index 0000000..51147f6 --- /dev/null +++ b/mt7620/src/common/cmm_wep.c @@ -0,0 +1,365 @@ +/* + *************************************************************************** + * 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) +{ +/* UCHAR seed[16];*/ + 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) + { + 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) + { + 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; + + /* 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)) + { + 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/mt7620/src/common/cmm_wpa.c b/mt7620/src/common/cmm_wpa.c new file mode 100644 index 0000000..6b68dd5 --- /dev/null +++ b/mt7620/src/common/cmm_wpa.c @@ -0,0 +1,5309 @@ +/* + *************************************************************************** + * 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 MESH_SUPPORT +/* IEEE 802.11s OUI*/ +UCHAR OUI_MSA_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x05}; /* Not yet final - IEEE 802.11s-D1.06*/ +UCHAR OUI_MSA_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x06}; /* Not yet final - IEEE 802.11s-D1.06*/ +#endif /* MESH_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) + pEntry = &pAd->MacTab.Content[pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].MacTabWCID]; + else +#endif /* MAC_REPEATER_SUPPORT */ + 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 or 3.*/ + else if ((pEntry->WepStatus == Ndis802_11Encryption3Enabled) + && (peerKeyInfo.KeyDescVer != KEY_DESC_AES) + && (peerKeyInfo.KeyDescVer != KEY_DESC_EXT)) + { + 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; + PMULTISSID_STRUCT pMbssEntry; + + DBGPRINT(RT_DEBUG_TRACE, ("REQUEST=1, ERROR=0, update group key\n")); + + pMbssEntry = &pAd->ApCfg.MBSSID[apidx]; + + GenRandom(pAd, pMbssEntry->Bssid, pMbssEntry->GNonce); + pMbssEntry->DefaultKeyId = (pMbssEntry->DefaultKeyId == 1) ? 2 : 1; + WpaDeriveGTK(pMbssEntry->GMK, + pMbssEntry->GNonce, + pMbssEntry->Bssid, + pMbssEntry->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; + 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, + pMbssEntry->GroupKeyWepStatus, + apidx, + pMbssEntry->DefaultKeyId, + Wcid, + TRUE, + pMbssEntry->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->Aid); + + 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) +#ifdef DOT11Z_TDLS_SUPPORT + && (!IS_ENTRY_TDLS(pEntry)) +#endif /* DOT11Z_TDLS_SUPPORT */ + )) + return; + + do { + /* build a NDIS packet*/ + 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_SOURCE(pPacket, PKTSRC_NDIS); + RTMP_SET_PACKET_MOREDATA(pPacket, FALSE); + RTMP_SET_PACKET_NET_DEVICE_APCLI(pPacket, pEntry->MatchAPCLITabIdx); + RTMP_SET_PACKET_WCID(pPacket, pEntry->Aid); /* to ApClient links.*/ +#ifdef P2P_SUPPORT + RTMP_SET_PACKET_OPMODE(pPacket, OPMODE_AP); +#endif /* P2P_SUPPORT */ + } + else +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + { + RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS); + + 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); +#ifdef P2P_SUPPORT + if (IS_P2P_GO_ENTRY(pEntry)) + { + RTMP_SET_PACKET_NET_DEVICE_P2P(pPacket, MAIN_MBSSID); + RTMP_SET_PACKET_OPMODE(pPacket, OPMODE_AP); + } +#endif /* P2P_SUPPORT */ + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* send out the packet*/ + APSendPacket(pAd, pPacket); /* send to one of TX queue*/ + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); /* Dequeue outgoing frames from TxSwQueue0..3 queue and process it*/ + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef P2P_SUPPORT + if (IS_ENTRY_APCLI(pEntry) || IS_P2P_GO_ENTRY(pEntry)) + { + /* send out the packet */ + APSendPacket(pAd, pPacket); /* send to one of TX queue */ + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); /* Dequeue outgoing frames from TxSwQueue0..3 queue and process it */ + break; + } +#endif /* P2P_SUPPORT */ + /* 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); + } + } + } +#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)); + } + 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); + } + + + 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); + 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 + UCHAR apidx = 0; +#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 +#ifdef P2P_SUPPORT + if (P2P_GO_ON(pAd)) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { + if ((!pEntry) || !IS_ENTRY_CLIENT(pEntry)) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : The entry doesn't exist.\n")); + return; + } + + if (pEntry->apidx < pAd->ApCfg.BssidNum) + { + apidx = pEntry->apidx; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : The apidx(%d) is invalid.\n", pEntry->apidx)); + return; + } + + /* pointer to the corresponding position*/ + pBssid = pAd->ApCfg.MBSSID[apidx].Bssid; + group_cipher = pAd->ApCfg.MBSSID[apidx].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, pAd->ApCfg.MBSSID[apidx].WscControl.EntryAddr) && + pAd->ApCfg.MBSSID[apidx].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], &pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[pEntry->PMKID_CacheIdx].PMKID, LEN_PMKID); + NdisMoveMemory(&pAd->ApCfg.MBSSID[apidx].PMK, &pAd->ApCfg.MBSSID[apidx].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); + } +#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->MatchAPCLITabIdx; +#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].CurrentAddress; + 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) + { +#ifdef P2P_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { + UINT IfIndex = 0; + + IfIndex = pEntry->MatchAPCLITabIdx; + if (IfIndex >= MAX_APCLI_NUM) + return; + + pCurrentAddr = pAd->ApCfg.ApCliTab[IfIndex].CurrentAddress; + 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; + } + else +#endif /* P2P_SUPPORT */ + { + 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); + + { + /* 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; + 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; + 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 +#ifdef P2P_SUPPORT + if (P2P_GO_ON(pAd)) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { + if (pEntry->apidx >= pAd->ApCfg.BssidNum) + return; + else + apidx = pEntry->apidx; + + pBssid = pAd->ApCfg.MBSSID[apidx].Bssid; + pmk_ptr = pAd->ApCfg.MBSSID[apidx].PMK; + gtk_ptr = pAd->ApCfg.MBSSID[apidx].GTK; + group_cipher = pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus; + default_key = pAd->ApCfg.MBSSID[apidx].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 ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) || + (pAd->ApCfg.MBSSID[apidx].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 */ + + + /* 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(pEntry->SNonce, pMsg2->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE); + + { + /* 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 + { + /* 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); + + /* 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_MSG3_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")); +} + +/* + ======================================================================== + + 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) +{ + 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; +#ifdef P2P_SUPPORT + BOOLEAN Cancelled; +#endif /* P2P_SUPPORT */ +#ifdef MAC_REPEATER_SUPPORT + USHORT ifIndex = (USHORT)(Elem->Priv); + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + 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->MatchAPCLITabIdx; +#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].CurrentAddress; + 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) + { +#ifdef P2P_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { + UINT IfIndex = 0; + + IfIndex = pEntry->MatchAPCLITabIdx; + if (IfIndex >= MAX_APCLI_NUM) + return; + + pCurrentAddr = pAd->ApCfg.ApCliTab[IfIndex].CurrentAddress; + group_cipher = pAd->ApCfg.ApCliTab[IfIndex].GroupCipher; + + } + else +#endif /* P2P_SUPPORT */ + { + 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*/ + 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 (PeerWpaMessageSanity(pAd, pMsg3, MsgLen, EAPOL_PAIR_MSG_3, pEntry) == FALSE) + return; + + /* 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; +#ifdef P2P_SUPPORT + if (IS_P2P_CLI_ENTRY(pEntry) && (pEntry->bP2pClient)) + { + if (pAd->P2pCfg.bP2pCliReConnectTimerRunning) + { + pAd->P2pCfg.bP2pCliReConnectTimerRunning = FALSE; + RTMPCancelTimer(&pAd->P2pCfg.P2pCliReConnectTimer, &Cancelled); + } + RTMPCancelTimer(&pAd->P2pCfg.P2pWscTimer, &Cancelled); +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT + P2pSendWirelessEvent(pAd, RT_P2P_CONNECTED, NULL, pEntry->HdrAddr3); +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ + } +#endif /* P2P_SUPPORT */ + /* Update pairwise key */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + APCliInstallPairwiseKey(pAd, pEntry); +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef P2P_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { +#ifdef DPA_S + UCHAR p2pIndex = P2P_NOT_FOUND; +#endif /* DPA_S */ + + APCliInstallPairwiseKey(pAd, pEntry); + +#ifdef DPA_S + p2pIndex = P2pGroupTabSearch(pAd, pEntry->Addr); + if (p2pIndex != P2P_NOT_FOUND) + { + PRT_P2P_CLIENT_ENTRY pP2pEntry = &pAd->P2pTable.Client[p2pIndex]; + P2pSendSamsungEvent(pAd, P2P_NOTIF_CREATE_LINK_COMPLETE, pEntry->Addr, pP2pEntry->DeviceName, pP2pEntry->DeviceNameLen); + } + else + P2pSendSamsungEvent(pAd, P2P_NOTIF_CREATE_LINK_COMPLETE, pEntry->Addr, NULL, 0); +#endif /* DPA_S */ + } + else +#endif /* P2P_SUPPORT */ + { + NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK); + WPAInstallPairwiseKey(pAd, + BSS0, + pEntry, + FALSE); + NdisMoveMemory(&pAd->SharedKey[BSS0][0], &pEntry->PairwiseKey, sizeof(CIPHER_KEY)); + } + } +#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 */ +#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; + PHEADER_802_11 pHeader; + 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 +#ifdef P2P_SUPPORT + if (P2P_GO_ON(pAd)) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { + UCHAR apidx = 0; + + if (pEntry->apidx >= pAd->ApCfg.BssidNum) + break; + else + apidx = pEntry->apidx; + + group_cipher = pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus; + } +#endif /* CONFIG_AP_SUPPORT */ + + /* 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 (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 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].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 */ +#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 P2P_SUPPORT + if (IS_P2P_GO_ENTRY(pEntry)) + { + if (pEntry->bP2pClient) + { +#ifdef DPA_S + UCHAR p2pIndex = P2P_NOT_FOUND; + + p2pIndex = P2pGroupTabSearch(pAd, pEntry->Addr); + if (p2pIndex != P2P_NOT_FOUND) + { + PRT_P2P_CLIENT_ENTRY pP2pEntry = &pAd->P2pTable.Client[p2pIndex]; + P2pSendSamsungEvent(pAd, P2P_NOTIF_CREATE_LINK_COMPLETE, pEntry->Addr, pP2pEntry->DeviceName, pP2pEntry->DeviceNameLen); + } +#endif /* DPA_S */ + pAd->P2pCfg.bPeriodicListen = TRUE; + RTMPCancelTimer(&pAd->P2pCfg.P2pWscTimer, &Cancelled); +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT + P2pSendWirelessEvent(pAd, RT_P2P_CONNECTED, NULL, pEntry->Addr); +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ + } + else + { +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT + P2pSendWirelessEvent(pAd, RT_P2P_LEGACY_CONNECTED, NULL, pEntry->Addr); +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ +#ifdef DPA_S + P2pSendSamsungEvent(pAd, P2P_NOTIF_CREATE_LINK_COMPLETE, pEntry->Addr, NULL, 0); +#endif /* DPA_S */ + } + } +#endif /* P2P_SUPPORT */ + + 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; + 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; + + DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart2WayGroupHS\n")); + + if ((!pEntry) || !IS_ENTRY_CLIENT(pEntry)) + return; + +#ifdef CONFIG_AP_SUPPORT +#ifdef P2P_SUPPORT + if (P2P_GO_ON(pAd)) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { + UCHAR apidx = 0; + + if (pEntry->apidx >= pAd->ApCfg.BssidNum) + return; + else + apidx = pEntry->apidx; + + group_cipher = pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus; + default_key = pAd->ApCfg.MBSSID[apidx].DefaultKeyId; + gnonce_ptr = pAd->ApCfg.MBSSID[apidx].GNonce; + gtk_ptr = pAd->ApCfg.MBSSID[apidx].GTK; + pBssid = pAd->ApCfg.MBSSID[apidx].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); + + 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 */ + + 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->MatchAPCLITabIdx; + 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].CurrentAddress; + group_cipher = pAd->ApCfg.ApCliTab[IfIndex].GroupCipher; + default_key = pAd->ApCfg.ApCliTab[IfIndex].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.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; + + /* delete retry timer*/ +#ifdef CONFIG_AP_SUPPORT +#ifdef P2P_SUPPORT + if (P2P_GO_ON(pAd)) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { +#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 */ +#endif /* APLCI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef P2P_SUPPORT + if (IS_ENTRY_CLIENT(pEntry)) +#endif /* P2P_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) +#ifdef P2P_SUPPORT + && IS_ENTRY_CLIENT(pEntry) +#endif /* P2P_SUPPORT */ + ) + { + /* 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))); + + MlmeEnqueue(pAd, WPA_STATE_MACHINE, MT2_EAPOLStart, 6, &pEntry->Addr, 0); + 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))); + +#ifdef P2P_SUPPORT + MgtMacHeaderInit(pAd, &DeAuthHdr, SUBTYPE_DEAUTH, 0, pEntry->Addr, pEntry->HdrAddr2, pEntry->HdrAddr3); +#else +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + MgtMacHeaderInit(pAd, &DeAuthHdr, SUBTYPE_DEAUTH, 0, pEntry->Addr, 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].Bssid); + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* P2P_SUPPORT */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DeAuthHdr, + 2, &Reason, + END_OF_ARGS); + + + + 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);*/ + MacTableDeleteEntry(pAd, pEntry->Aid, 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 +#ifdef P2P_SUPPORT + if (P2P_GO_ON(pAd)) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { + UCHAR apidx = 0; + + if (pEntry->apidx >= pAd->ApCfg.BssidNum) + return; + else + apidx = pEntry->apidx; + + group_cipher = pAd->ApCfg.MBSSID[apidx].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 + { + /* send wireless event - for set key done WPA*/ + RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA1_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); + + 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; + } /* End of if */ + + 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; + + { + 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_11Encryption2Enabled: + 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_11Encryption3Enabled: + 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_11Encryption4Enabled: + 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_11Encryption2Enabled) && + (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled) +#ifdef P2P_SUPPORT + && (apidx == BSS0) +#endif /* P2P_SUPPORT */ + ) + { + 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_11Encryption2Enabled: + 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_11Encryption3Enabled: + 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_11Encryption4Enabled: + 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_11Encryption2Enabled) && + (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled) +#ifdef P2P_SUPPORT + && (apidx == BSS0) +#endif /* P2P_SUPPORT */ + ) + { + 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*/ + + pRsnie_auth = (RSNIE_AUTH*)(pRsnIe + (*rsn_len)); + + /* decide WPA2 or WPA1 */ + if (ElementID == Wpa2Ie) + { + + switch (AuthMode) + { + case Ndis802_11AuthModeWPA2: + case Ndis802_11AuthModeWPA1WPA2: +#ifdef MESH_SUPPORT + if ((apidx >= MIN_NET_DEVICE_FOR_MESH) +#ifdef P2P_SUPPORT + && (apidx < MIN_NET_DEVICE_FOR_DLS) +#endif /* P2P_SUPPORT */ + ) + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_MSA_8021X_AKM, 4); + else +#endif /* MESH_SUPPORT */ + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_8021X_AKM, 4); + + break; + + case Ndis802_11AuthModeWPA2PSK: + case Ndis802_11AuthModeWPA1PSKWPA2PSK: +#ifdef MESH_SUPPORT + if ((apidx >= MIN_NET_DEVICE_FOR_MESH) +#ifdef P2P_SUPPORT + && (apidx < MIN_NET_DEVICE_FOR_DLS) +#endif /* P2P_SUPPORT */ + ) + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_MSA_PSK_AKM, 4); + else +#endif /* MESH_SUPPORT */ + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4); + + 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 */ + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + +#ifdef P2P_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_P2P_GO) + { + PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[MAIN_MBSSID]; + +#ifdef DOT1X_SUPPORT + pRSN_Cap->field.PreAuth = (pMbss->PreAuth == TRUE) ? 1 : 0; +#endif /* DOT1X_SUPPORT */ + } +#endif /* P2P_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: + + ======================================================================== +*/ + +/* + ======================================================================== + + 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( + IN PRTMP_ADAPTER pAd, + IN UINT AuthMode, + IN UINT WepStatus, + IN 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 P2P_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_P2P_GO) + { + 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(p2p%d)\n", MAIN_MBSSID)); + + /* decide the group key encryption type */ + if (WepStatus == Ndis802_11Encryption4Enabled) + { + pAd->ApCfg.MBSSID[MAIN_MBSSID].GroupKeyWepStatus = Ndis802_11Encryption2Enabled; + FlexibleCipher = pAd->ApCfg.MBSSID[MAIN_MBSSID].WpaMixPairCipher; + } + else + pAd->ApCfg.MBSSID[MAIN_MBSSID].GroupKeyWepStatus = WepStatus; + + /* Initiate some related information */ + pAd->ApCfg.MBSSID[MAIN_MBSSID].RSNIE_Len[0] = 0; + pAd->ApCfg.MBSSID[MAIN_MBSSID].RSNIE_Len[1] = 0; + NdisZeroMemory(pAd->ApCfg.MBSSID[MAIN_MBSSID].RSN_IE[0], MAX_LEN_OF_RSNIE); + NdisZeroMemory(pAd->ApCfg.MBSSID[MAIN_MBSSID].RSN_IE[1], MAX_LEN_OF_RSNIE); + + /* Pointer to the first RSNIE context */ + rsnielen_cur_p = &pAd->ApCfg.MBSSID[MAIN_MBSSID].RSNIE_Len[0]; + pRsnIe = pAd->ApCfg.MBSSID[MAIN_MBSSID].RSN_IE[0]; + + /* Pointer to the secondary RSNIE context */ + rsnielen_ex_cur_p = &pAd->ApCfg.MBSSID[MAIN_MBSSID].RSNIE_Len[1]; + pRsnIe_ex = pAd->ApCfg.MBSSID[MAIN_MBSSID].RSN_IE[1]; + + /* Decide whether the authentication mode is WPA1-WPA2 mixed mode */ + if ((AuthMode == Ndis802_11AuthModeWPA1WPA2) || + (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) + { + bMixRsnIe = TRUE; + } + break; + } +#endif /* P2P_SUPPORT */ +#ifdef MESH_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_MESH) + { + /* Only support WPANONE for Mesh Link */ + if ((AuthMode != Ndis802_11AuthModeWPANone)/* && + (AuthMode != Ndis802_11AuthModeWPA2PSK) && + (AuthMode != Ndis802_11AuthModeWPA2)*/) + return; + + /* ONLY support TKIP or AES, not mix mode */ + if ((WepStatus != Ndis802_11Encryption2Enabled) && + (WepStatus != Ndis802_11Encryption3Enabled)) + return; + + DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(mesh)\n")); + + /* initiate the related information*/ + pAd->MeshTab.RSNIE_Len = 0; + NdisZeroMemory(pAd->MeshTab.RSN_IE, MAX_LEN_OF_RSNIE); + rsnielen_cur_p = &pAd->MeshTab.RSNIE_Len; + pRsnIe = pAd->MeshTab.RSN_IE; + break; + } + else +#endif /* MESH_SUPPORT */ + +#ifdef APCLI_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_APCLI) + { + UINT apcliIfidx = 0; + + /* Only support WPAPSK or WPA2PSK for AP-Client mode */ +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + if (pAd->ApCfg.ApCliTab[apcliIfidx].WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) + { + if (AuthMode < Ndis802_11AuthModeWPA) + return; + } + else +#endif /* APCLI_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) + 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_11Encryption4Enabled) + { + pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus = Ndis802_11Encryption2Enabled; + FlexibleCipher = pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher; + } + else + pAd->ApCfg.MBSSID[apidx].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.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); + + } + + /* 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) +#ifdef P2P_SUPPORT + || (apidx >= MIN_NET_DEVICE_FOR_P2P_GO) +#endif /* P2P_SUPPORT */ + ) + { + /* 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); + + + /* 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 PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pData, + IN ULONG DataByteCount, + IN UCHAR FromWhichBSSID) +{ + ULONG Body_len; + BOOLEAN Cancelled; + + do + { +#ifdef P2P_SUPPORT + if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_P2P_GO) + break; +#endif /* P2P_SUPPORT */ +#ifdef MESH_SUPPORT + if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_MESH) + { + UINT mesh_header_len = GetMeshHederLen(pData); + + pData += mesh_header_len; + DataByteCount -= mesh_header_len; + break; + } +#endif /* MESH_SUPPORT */ + } 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; +} + +/* + ========================================================================== + 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);*/ + + + /* 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)); + } + } + } + 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)) + { + /* Set Group key material, TxMic and RxMic for AP-Client*/ + if (!APCliInstallSharedKey(pAd, GTK, GTKLEN, DefaultIdx, pEntry)) + { + return FALSE; + } + } +#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_11Encryption3Enabled) { + 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 */ + { +#ifdef P2P_SUPPORT + if (IS_ENTRY_CLIENT(pEntry)) +#endif /* P2P_SUPPORT */ + { + /* set key material, TxMic and RxMic */ + NdisMoveMemory(pAd->StaCfg.GTK, GTK, GTKLEN); + pAd->StaCfg.DefaultKeyId = DefaultIdx; + + WPAInstallSharedKey(pAd, + pAd->StaCfg.GroupCipher, + BSS0, + pAd->StaCfg.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*/ + { + /* 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)); + } + + 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_11Encryption2Enabled) ? 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_11Encryption2Enabled) ? LEN_TKIP_GTK : LEN_AES_GTK); + } + else + { + /* the length of pairwise key cipher*/ + pMsg->KeyDesc.KeyLength[1] = ((pEntry->WepStatus == Ndis802_11Encryption2Enabled) ? 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; + + /* 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; + + + 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) + { + /*hex_dump("GTK_Included", Key_Data, data_offset);*/ + + 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, + &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) + { + 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_11Encryption1Enabled: + case Ndis802_11Encryption2Enabled: + case Ndis802_11Encryption3Enabled: + keyIdx = (*(pIV + 3) & 0xc0) >> 6; + break; + +#ifdef WAPI_SUPPORT + case Ndis802_11EncryptionSMS4Enabled: + keyIdx = *(pIV) & 0xFF; + break; +#endif /* WAPI_SUPPORT */ + } + + return keyIdx; + +} + +PCIPHER_KEY RTMPSwCipherKeySelection( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pIV, + IN RX_BLK *pRxBlk, + IN PMAC_TABLE_ENTRY pEntry) +{ + PCIPHER_KEY pKey = NULL; + UCHAR keyIdx = 0; + UINT8 CipherAlg = Ndis802_11EncryptionDisabled; + PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); + + 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 (pRxD->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_11Encryption1Enabled) + { + pKey = &pAd->SharedKey[pEntry->apidx][keyIdx]; + } + else if ((CipherAlg == Ndis802_11Encryption2Enabled) || + (CipherAlg == Ndis802_11Encryption3Enabled)) + { + if (pRxD->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 (pRxD->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) +{ + 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 */ + if (RTMPSoftDecryptTKIP(pAd, pHdr, UserPriority, + pKey, pData, &(*DataByteCnt)) == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR : SW decrypt TKIP data fails.\n")); + /* give up this frame*/ + return NDIS_STATUS_FAILURE; + } + 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; + + } + + +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_11Encryption2Enabled) + pEntry->PairwiseKey.CipherAlg = CIPHER_TKIP; + else if (pEntry->WepStatus == Ndis802_11Encryption3Enabled) + pEntry->PairwiseKey.CipherAlg = CIPHER_AES; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : fails (wcid-%d)\n", + __FUNCTION__, pEntry->Aid)); + 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->Aid)); + 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->Aid, + &pEntry->PairwiseKey); + + RTMPSetWcidSecurityInfo(pAd, + BssIdx, + 0, + pEntry->PairwiseKey.CipherAlg, + (UCHAR)pEntry->Aid, + 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_11Encryption2Enabled) + pSharedKey->CipherAlg = CIPHER_TKIP; + else if (GroupCipher == Ndis802_11Encryption3Enabled) + 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) */ + RTMP_ASIC_SHARED_KEY_TABLE(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); + +} + +/** 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--; + } +} \ No newline at end of file diff --git a/mt7620/src/common/cmm_wpa_adhoc.c b/mt7620/src/common/cmm_wpa_adhoc.c new file mode 100644 index 0000000..2735ce7 --- /dev/null +++ b/mt7620/src/common/cmm_wpa_adhoc.c @@ -0,0 +1,1635 @@ +/* + *************************************************************************** + * 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]; +/* int i; */ + UINT32 IV = 0; + UINT32 EIV = 0; + + /* Get apidx for this BSSID */ + GET_GroupKey_WCID(pAd, Wcid, apidx); + + /* Read IVEIV from Asic */ + offset = MAC_IVEIV_TABLE_BASE + (Wcid * HW_IVEIV_ENTRY_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); + } + } +} /*End of Adhoc_WpaEAPOLStartAction */ + + +/* + ========================================================================== + 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; + +} /*End of Adhoc_PeerWpaMessageSanity */ + + +/* + ========================================================================== + 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); +} /* End of Adhoc_WpaEAPOLKeyAction */ + + + +/* + ========================================================================== + 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")); + +} /* End of Adhoc_WPAStart4WayHS */ + + +/* + ======================================================================== + + 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")); +} /*End of Adhoc_PeerPairMsg1Action */ + + +/* + ========================================================================== + 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.DefaultKeyId; + if (pAd->StaCfg.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")); +} /*End of Adhoc_PeerPairMsg2Action */ + + +/* + ======================================================================== + + 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")); +} /* End of Adhoc_PeerPairMsg3Action */ + + +/* + ========================================================================== + 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); + +} /* End of Adhoc_PeerPairMsg4Action */ + + +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.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")); +} /*End of Adhoc_PeerGroupMsg1Action */ + + +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))); +} /* End of Adhoc_Wpa4WayComplete */ + + +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--; + } +} /* End of Adhoc_WPARetryExec */ + + +/* + ======================================================================== + + 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))); +} /*End of Adhoc_ConstructEapolMsg */ + + +/* + ======================================================================== + + 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); + +} /* End of Adhoc_ConstructEapolKeyData */ +#endif /* ADHOC_WPA2PSK_SUPPORT */ + diff --git a/mt7620/src/common/crypt_aes.c b/mt7620/src/common/crypt_aes.c new file mode 100644 index 0000000..a71ad35 --- /dev/null +++ b/mt7620/src/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++; + } /* End of while */ + + 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++; + } /* End of while */ +} /* End of RT_AES_KeyExpansion */ + + +/* +======================================================================== +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; + } /* End of if */ + 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; + } /* End of if */ + 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; + } /* End of if */ + + /* 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]; + } /* End of for */ + + /* 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); +} /* End of RT_AES_Encrypt */ + + +/* +======================================================================== +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; + } /* End of if */ + 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; + } /* End of if */ + 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; + } /* End of if */ + + /* 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]; + } + } /* End of for */ + + /* 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); +} /* End of RT_AES_Decrypt */ + + + +/* +======================================================================== +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; + } /* End of if */ + + 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; + } /* End of if */ + 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); + } /* End of while */ + + /* + * 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; + } /* End of while */ + for (Temp_Index = 0; Temp_Index < MACLength; Temp_Index++) + MACText[Temp_Index] = Block_MAC[Temp_Index]; +} /* End of AES_CCM_MAC */ + + +/* +======================================================================== +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; + } /* End of if */ + + if ((NonceLength < 7) || (NonceLength > 13)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Encrypt: A valid nonce length is 7-13 bytes\n")); + return -2; + } /* End of if */ + + 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; + } /* End of if */ + + if (*CipherTextLength < (PlainTextLength + MACLength)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Encrypt: The CipherTextLength is not enough.\n")); + return -4; + } /* End of if */ + + + /* + * 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; + } /* End of while */ + for (Temp_Index = 0; Temp_Index < MACLength; Temp_Index++) + CipherText[PlainTextLength + Temp_Index] = Block_MAC[Temp_Index]; + *CipherTextLength = PlainTextLength + MACLength; + + return 0; +} /* End of AES_CCM_Encrypt */ + + +/* +======================================================================== +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; + } /* End of if */ + + if ((NonceLength < 7) || (NonceLength > 13)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Decrypt: A valid nonce length is 7-13 bytes\n")); + return -2; + } /* End of if */ + + 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; + } /* End of if */ + + if (*PlainTextLength < (CipherTextLength - MACLength)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Decrypt: The PlainTextLength is not enough.\n")); + return -4; + } /* End of if */ + + /* + * 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; + } /* End of while */ + *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; + } /* End of if */ + + return 0; +} /* End of AES_CCM_Decrypt */ + + +/* +======================================================================== +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; + } /* End of if */ + + /* 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]; + } /* End of if */ + + /* + * 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]; + } /* End of if */ +} /* End of AES_CMAC_GenerateSubKey */ + + +/* +======================================================================== +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; + } /* End of if */ + 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; + } /* End of if */ + + /* 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); + } /* End of while */ + 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]; + } /* End of if */ + RT_AES_Encrypt(Y, sizeof(Y) , Key, KeyLength, MACText, MACTextLength); +} /* End of AES_CMAC */ + + +/* 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; + } /* End of if */ + 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; + } /* End of if */ + 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; + } /* End of if */ + + + /* + * 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]; + } /* End of if */ + + CipherBlockSize = *CipherTextLength - CipherBlockStart; + RT_AES_Encrypt(Block, AES_BLOCK_SIZES , Key, KeyLength, CipherText + CipherBlockStart, &CipherBlockSize); + + PlainBlockStart += ((UINT) AES_BLOCK_SIZES); + CipherBlockStart += CipherBlockSize; + } /* End of while */ + + 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]; + } /* End of if */ + CipherBlockSize = *CipherTextLength - CipherBlockStart; + RT_AES_Encrypt(Block, AES_BLOCK_SIZES , Key, KeyLength, CipherText + CipherBlockStart, &CipherBlockSize); + CipherBlockStart += CipherBlockSize; + *CipherTextLength = CipherBlockStart; +} /* End of AES_CBC_Encrypt */ + + +/* +======================================================================== +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; + } /* End of if */ + 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; + } /* End of if */ + 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; + } /* End of if */ + + + /* + * 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)]; + } /* End of if */ + + CipherBlockStart += AES_BLOCK_SIZES; + PlainBlockStart += PlainBlockSize; + } /* End of while */ + + PaddingSize = (UINT8) PlainText[PlainBlockStart -1]; + *PlainTextLength = PlainBlockStart - PaddingSize; + +} /* End of AES_CBC_Encrypt */ + + +/* +======================================================================== +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/mt7620/src/common/crypt_arc4.c b/mt7620/src/common/crypt_arc4.c new file mode 100644 index 0000000..382b896 --- /dev/null +++ b/mt7620/src/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/mt7620/src/common/crypt_biginteger.c b/mt7620/src/common/crypt_biginteger.c new file mode 100644 index 0000000..b27d4ca --- /dev/null +++ b/mt7620/src/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/mt7620/src/common/crypt_dh.c b/mt7620/src/common/crypt_dh.c new file mode 100644 index 0000000..d2bc0ef --- /dev/null +++ b/mt7620/src/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/mt7620/src/common/crypt_hmac.c b/mt7620/src/common/crypt_hmac.c new file mode 100644 index 0000000..2e3a6dc --- /dev/null +++ b/mt7620/src/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 x¡¦36¡¦ repeated B times. */ + for (index = 0; index < SHA1_BLOCK_SIZE; index++) + K0[index] ^= 0x36; + /* End of for */ + + RT_SHA1_Init(&sha_ctx1); + /* H(K0^ipad) */ + RT_SHA1_Append(&sha_ctx1, K0, sizeof(K0)); + /* H((K0^ipad)||text) */ + RT_SHA1_Append(&sha_ctx1, Message, MessageLen); + RT_SHA1_End(&sha_ctx1, Digest); + + /* Exclusive-Or K0 with opad and remove ipad */ + /* opad: Outer pad; the byte x¡¦5c¡¦ repeated B times. */ + for (index = 0; index < SHA1_BLOCK_SIZE; index++) + K0[index] ^= 0x36^0x5c; + /* End of for */ + + RT_SHA1_Init(&sha_ctx2); + /* H(K0^opad) */ + RT_SHA1_Append(&sha_ctx2, K0, sizeof(K0)); + /* H( (K0^opad) || H((K0^ipad)||text) ) */ + RT_SHA1_Append(&sha_ctx2, Digest, SHA1_DIGEST_SIZE); + RT_SHA1_End(&sha_ctx2, Digest); + + if (MACLen > SHA1_DIGEST_SIZE) + NdisMoveMemory(MAC, Digest, SHA1_DIGEST_SIZE); + else + NdisMoveMemory(MAC, Digest, MACLen); +} /* End of RT_HMAC_SHA1 */ +#endif /* HMAC_SHA1_SUPPORT */ + + +#ifdef HMAC_SHA256_SUPPORT +/* +======================================================================== +Routine Description: + HMAC using SHA256 hash function + +Arguments: + key Secret key + key_len The length of the key in bytes + message Message context + message_len The length of message in bytes + macLen Request the length of message authentication code + +Return Value: + mac Message authentication code + +Note: + None +======================================================================== +*/ +VOID RT_HMAC_SHA256 ( + IN const UINT8 Key[], + IN UINT KeyLen, + IN const UINT8 Message[], + IN UINT MessageLen, + OUT UINT8 MAC[], + IN UINT MACLen) +{ + SHA256_CTX_STRUC sha_ctx1; + SHA256_CTX_STRUC sha_ctx2; + UINT8 K0[SHA256_BLOCK_SIZE]; + UINT8 Digest[SHA256_DIGEST_SIZE]; + UINT index; + + NdisZeroMemory(&sha_ctx1, sizeof(SHA256_CTX_STRUC)); + NdisZeroMemory(&sha_ctx2, sizeof(SHA256_CTX_STRUC)); + /* + * If the length of K = B(Block size): K0 = K. + * If the length of K > B: hash K to obtain an L byte string, + * then append (B-L) zeros to create a B-byte string K0 (i.e., K0 = H(K) || 00...00). + * If the length of K < B: append zeros to the end of K to create a B-byte string K0 + */ + NdisZeroMemory(K0, SHA256_BLOCK_SIZE); + if (KeyLen <= SHA256_BLOCK_SIZE) { + NdisMoveMemory(K0, Key, KeyLen); + } else { + RT_SHA256(Key, KeyLen, K0); + } + + /* Exclusive-Or K0 with ipad */ + /* ipad: Inner pad; the byte x¡¦36¡¦ repeated B times. */ + for (index = 0; index < SHA256_BLOCK_SIZE; index++) + K0[index] ^= 0x36; + /* End of for */ + + RT_SHA256_Init(&sha_ctx1); + /* H(K0^ipad) */ + RT_SHA256_Append(&sha_ctx1, K0, sizeof(K0)); + /* H((K0^ipad)||text) */ + RT_SHA256_Append(&sha_ctx1, Message, MessageLen); + RT_SHA256_End(&sha_ctx1, Digest); + + /* Exclusive-Or K0 with opad and remove ipad */ + /* opad: Outer pad; the byte x¡¦5c¡¦ repeated B times. */ + for (index = 0; index < SHA256_BLOCK_SIZE; index++) + K0[index] ^= 0x36^0x5c; + /* End of for */ + + RT_SHA256_Init(&sha_ctx2); + /* H(K0^opad) */ + RT_SHA256_Append(&sha_ctx2, K0, sizeof(K0)); + /* H( (K0^opad) || H((K0^ipad)||text) ) */ + RT_SHA256_Append(&sha_ctx2, Digest, SHA256_DIGEST_SIZE); + RT_SHA256_End(&sha_ctx2, Digest); + + if (MACLen > SHA256_DIGEST_SIZE) + NdisMoveMemory(MAC, Digest,SHA256_DIGEST_SIZE); + else + NdisMoveMemory(MAC, Digest, MACLen); + +} /* End of RT_HMAC_SHA256 */ +#endif /* HMAC_SHA256_SUPPORT */ + + +#ifdef HMAC_MD5_SUPPORT +/* +======================================================================== +Routine Description: + HMAC using MD5 hash function + +Arguments: + key Secret key + key_len The length of the key in bytes + message Message context + message_len The length of message in bytes + macLen Request the length of message authentication code + +Return Value: + mac Message authentication code + +Note: + None +======================================================================== +*/ +VOID RT_HMAC_MD5( + IN const UINT8 Key[], + IN UINT KeyLen, + IN const UINT8 Message[], + IN UINT MessageLen, + OUT UINT8 MAC[], + IN UINT MACLen) +{ + MD5_CTX_STRUC md5_ctx1; + MD5_CTX_STRUC md5_ctx2; + UINT8 K0[MD5_BLOCK_SIZE]; + UINT8 Digest[MD5_DIGEST_SIZE]; + UINT index; + + NdisZeroMemory(&md5_ctx1, sizeof(MD5_CTX_STRUC)); + NdisZeroMemory(&md5_ctx2, sizeof(MD5_CTX_STRUC)); + /* + * If the length of K = B(Block size): K0 = K. + * If the length of K > B: hash K to obtain an L byte string, + * then append (B-L) zeros to create a B-byte string K0 (i.e., K0 = H(K) || 00...00). + * If the length of K < B: append zeros to the end of K to create a B-byte string K0 + */ + NdisZeroMemory(K0, MD5_BLOCK_SIZE); + if (KeyLen <= MD5_BLOCK_SIZE) { + NdisMoveMemory(K0, Key, KeyLen); + } else { + RT_MD5(Key, KeyLen, K0); + } + + /* Exclusive-Or K0 with ipad */ + /* ipad: Inner pad; the byte x¡¦36¡¦ repeated B times. */ + for (index = 0; index < MD5_BLOCK_SIZE; index++) + K0[index] ^= 0x36; + /* End of for */ + + RT_MD5_Init(&md5_ctx1); + /* H(K0^ipad) */ + RT_MD5_Append(&md5_ctx1, K0, sizeof(K0)); + /* H((K0^ipad)||text) */ + RT_MD5_Append(&md5_ctx1, Message, MessageLen); + RT_MD5_End(&md5_ctx1, Digest); + + /* Exclusive-Or K0 with opad and remove ipad */ + /* opad: Outer pad; the byte x¡¦5c¡¦ repeated B times. */ + for (index = 0; index < MD5_BLOCK_SIZE; index++) + K0[index] ^= 0x36^0x5c; + /* End of for */ + + RT_MD5_Init(&md5_ctx2); + /* H(K0^opad) */ + RT_MD5_Append(&md5_ctx2, K0, sizeof(K0)); + /* H( (K0^opad) || H((K0^ipad)||text) ) */ + RT_MD5_Append(&md5_ctx2, Digest, MD5_DIGEST_SIZE); + RT_MD5_End(&md5_ctx2, Digest); + + if (MACLen > MD5_DIGEST_SIZE) + NdisMoveMemory(MAC, Digest, MD5_DIGEST_SIZE); + else + NdisMoveMemory(MAC, Digest, MACLen); +} /* End of RT_HMAC_SHA256 */ +#endif /* HMAC_MD5_SUPPORT */ + + +/* End of crypt_hmac.c */ + diff --git a/mt7620/src/common/crypt_md5.c b/mt7620/src/common/crypt_md5.c new file mode 100644 index 0000000..a49c111 --- /dev/null +++ b/mt7620/src/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/mt7620/src/common/crypt_sha2.c b/mt7620/src/common/crypt_sha2.c new file mode 100644 index 0000000..75de87c --- /dev/null +++ b/mt7620/src/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/mt7620/src/common/ee_flash.c b/mt7620/src/common/ee_flash.c new file mode 100644 index 0000000..b99fb95 --- /dev/null +++ b/mt7620/src/common/ee_flash.c @@ -0,0 +1,365 @@ +/* + *************************************************************************** + * 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 + -------- ---------- ---------------------------------------------- +*/ + + +#include "rt_config.h" + +static NDIS_STATUS rtmp_ee_flash_init(PRTMP_ADAPTER pAd, PUCHAR start); + + +static USHORT EE_FLASH_ID_LIST[]={ +#ifdef RT2860 + 0x2860, +#endif /* RT2860 */ +#ifdef RT2880 + 0x2880, +#endif /* RT2880 */ +#ifdef RT2883 + 0x2883, + 0x2880, +#endif /* RT2883 */ +#ifdef RT3883 + 0x3662, + 0x3883, +#endif /* RT3883 */ +#ifdef RT305x + 0x3052, + 0x3051, + 0x3050, + 0x3350, +#endif /* RT305x */ +#ifdef RT3352 + 0x3352, +#endif /* RT3352 */ +#ifdef RT5350 + 0x5350, +#endif /* RT5350 */ + + +#ifdef RT6352 + 0x6352, + 0x7620, +#endif /* RT6352 */ + +}; + +#define EE_FLASH_ID_NUM (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, RF_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, RF_OFFSET, EEPROM_SIZE); +#endif /* MULTIPLE_CARD_SUPPORT */ +} + + +static NDIS_STATUS rtmp_ee_flash_reset( + IN RTMP_ADAPTER *pAd, + IN PUCHAR start) +{ + PUCHAR src; + RTMP_OS_FS_INFO osFsInfo; + RTMP_OS_FD srcf; + INT retval; + + 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_ERROR, ("--> 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; + + rtmp_ee_flash_read(pAd, 0, &eeFlashId); + + for(listIdx =0 ; listIdx < EE_FLASH_ID_NUM; listIdx++) + { + if (eeFlashId == EE_FLASH_ID_LIST[listIdx]) + return TRUE; + } + return FALSE; +} + + +static NDIS_STATUS rtmp_ee_flash_init(PRTMP_ADAPTER pAd, PUCHAR start) +{ + 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; + + 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(PRTMP_ADAPTER pAd) +{ +#ifdef MULTIPLE_CARD_SUPPORT + UCHAR *eepromBuf; +#endif /* MULTIPLE_CARD_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("--> rtmp_nv_init\n")); + if (pAd->chipCap.eebuf == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("pAd->chipCap.eebuf == NULL!!!\n")); + return NDIS_STATUS_FAILURE; + } + +/* ASSERT((pAd->eebuf == NULL)); */ + pAd->eebuf = pAd->chipCap.eebuf; + + +#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.eebuf, 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, RF_OFFSET, EEPROM_SIZE); +#endif /* MULTIPLE_CARD_SUPPORT */ + + return rtmp_ee_flash_init(pAd, pAd->eebuf); +} diff --git a/mt7620/src/common/ee_prom.c b/mt7620/src/common/ee_prom.c new file mode 100644 index 0000000..3c4b8f2 --- /dev/null +++ b/mt7620/src/common/ee_prom.c @@ -0,0 +1,265 @@ +/* + *************************************************************************** + * 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 PRTMP_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 PRTMP_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; + +} + + diff --git a/mt7620/src/common/eeprom.c b/mt7620/src/common/eeprom.c new file mode 100644 index 0000000..ee41b3c --- /dev/null +++ b/mt7620/src/common/eeprom.c @@ -0,0 +1,82 @@ +/* + *************************************************************************** + * 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" + + +INT RtmpChipOpsEepromHook( + IN RTMP_ADAPTER *pAd, + IN INT infType) +{ + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + +#ifdef RTMP_FLASH_SUPPORT + pChipOps->eeinit = rtmp_nv_init; + pChipOps->eeread = rtmp_ee_flash_read; + pChipOps->eewrite = rtmp_ee_flash_write; + return 0; +#endif /* RTMP_FLASH_SUPPORT */ + + + switch(infType) + { +#ifdef RTMP_PCI_SUPPORT + case RTMP_DEV_INF_PCI: + case RTMP_DEV_INF_PCIE: + { + UINT32 val; + RTMP_IO_READ32(pAd, E2PROM_CSR, &val); + if ((val & 0x30) == 0) + pAd->EEPROMAddressNum = 6; /* 93C46*/ + else if ((val & 0x30) == 0x10) + pAd->EEPROMAddressNum = 8; /* 93C66*/ + else + pAd->EEPROMAddressNum = 8; /* 93C86*/ + } + pChipOps->eeinit = NULL; + pChipOps->eeread = rtmp_ee_prom_read16; + pChipOps->eewrite = rtmp_ee_prom_write16; + break; +#endif /* RTMP_PCI_SUPPORT */ + +#ifdef RTMP_RBUS_SUPPORT + case RTMP_DEV_INF_RBUS: + pChipOps->eeinit = rtmp_nv_init; + pChipOps->eeread = rtmp_ee_flash_read; + pChipOps->eewrite = rtmp_ee_flash_write; + pChipOps->loadFirmware = NULL; + break; +#endif /* RTMP_RBUS_SUPPORT */ + + default: + DBGPRINT(RT_DEBUG_ERROR, ("RtmpChipOpsEepromHook() failed!\n")); + break; + } + + return 0; +} + diff --git a/mt7620/src/common/frq_cal.c b/mt7620/src/common/frq_cal.c new file mode 100644 index 0000000..ac05d39 --- /dev/null +++ b/mt7620/src/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/mt7620/src/common/igmp_snoop.c b/mt7620/src/common/igmp_snoop.c new file mode 100644 index 0000000..47e4582 --- /dev/null +++ b/mt7620/src/common/igmp_snoop.c @@ -0,0 +1,1511 @@ +#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 PMULTICAST_FILTER_TABLE pMulticastFilterTable, + IN PLIST_HEADER pList, + IN PUCHAR pMemberAddr); + +static VOID DeleteIgmpMember( + IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, + IN PLIST_HEADER pList, + IN PUCHAR pMemberAddr); + +static VOID DeleteIgmpMemberList( + IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, + IN PLIST_HEADER pList); + + +/* + ========================================================================== + 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 */ +/* *ppMulticastFilterTable = kmalloc(sizeof(MULTICAST_FILTER_TABLE), MEM_ALLOC_FLAG); */ + 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 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)); +/* kfree(*ppMulticastFilterTable); */ + os_free_mem(NULL, *ppMulticastFilterTable); + *ppMulticastFilterTable = NULL; +} + +/* + ========================================================================== + 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; + + if (pMulticastFilterTable == NULL) + { + DBGPRINT(RT_DEBUG_OFF, ("%s Multicase filter table is not ready.\n", __FUNCTION__)); + return; + } + + /* if FULL, return */ + if (pMulticastFilterTable->Size == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("Table empty.\n")); + return; + } + + /* 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]; + + DBGPRINT(RT_DEBUG_OFF, ("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) + { + DBGPRINT(RT_DEBUG_OFF, ("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(pMulticastFilterTable, pGrpId, dev))) + { + /* 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_ERROR, ("%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(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(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(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) +{ + 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)) + { + /*USHORT Aid = MCAST_WCID; */ + /*SST Sst = SST_ASSOC; */ + /*UCHAR PsMode = PWR_ACTIVE, Rate; */ + /*if(APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate)) */ + DeleteIgmpMember(pMulticastFilterTable, &pEntry->MemberList, pMemberAddr); + if (IgmpMemberCnt(&pEntry->MemberList) > 0) + break; + } + + if (pEntry) + { + if (pEntry == pMulticastFilterTable->Hash[HashIdx]) + { + pMulticastFilterTable->Hash[HashIdx] = pEntry->pNext; + DeleteIgmpMemberList(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(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_ERROR, ("%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 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(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(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; +} + +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); + 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); + 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 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; +} + +static VOID InsertIgmpMember( + 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); + + 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 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); + FreeGrpMemberEntry(pMulticastFilterTable, pCurEntry); + break; + } + pCurEntry = pCurEntryNext; + } + + return; +} + +static VOID DeleteIgmpMemberList( + 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); + 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(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); + } + } +} + +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[ETH_LENGTH_OF_ADDRESS]; + UCHAR GroupId[ETH_LENGTH_OF_ADDRESS]; + 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].MSSIDDev); + + 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].MSSIDDev); + + 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); + + bGroupId = 0; + } + + if(memberCnt == 0) + MulticastFilterTableDeleteEntry(pAd, (PUCHAR)GroupId, NULL, pDev); + + 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 UCHAR FromWhichBSSID, + OUT INT *pInIgmpGroup, + OUT PMULTICAST_FILTER_TABLE_ENTRY *ppGroupEntry) +{ + if(IS_MULTICAST_MAC_ADDR(pSrcBufVA)) + { + BOOLEAN IgmpMldPkt = FALSE; + PUCHAR pIpHeader = pSrcBufVA + 12; + + if(ntohs(*((UINT16 *)(pIpHeader))) == ETH_P_IPV6) + IgmpMldPkt = IPv6MulticastFilterExcluded(pSrcBufVA, pIpHeader); + else + IgmpMldPkt = isIgmpPkt(pSrcBufVA, pIpHeader); + + if (IgmpMldPkt) + { + *ppGroupEntry = NULL; + *pInIgmpGroup = IGMP_PKT; + } + else if ((*ppGroupEntry = MulticastFilterTableLookup(pAd->pMulticastFilterTable, pSrcBufVA, + get_netdev_from_bssid(pAd, FromWhichBSSID))) == 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->pMulticastFilterTable, pGroupMacAddr, + get_netdev_from_bssid(pAd, FromWhichBSSID))) != 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, + IN PNET_DEV pNetDev) +{ + 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; + + bContinue = FALSE; + + if ((IgmpPktInGroup == IGMP_IN_GROUP) + && (pGroupEntry == NULL)) + return NDIS_STATUS_FAILURE; + + if (IgmpPktInGroup == IGMP_IN_GROUP) + { + pMemberEntry = (PMEMBER_ENTRY)pGroupEntry->MemberList.pHead; + if (pMemberEntry != NULL) + { + pMemberAddr = pMemberEntry->Addr; + pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate); + bContinue = TRUE; + } + } + else if (IgmpPktInGroup == IGMP_PKT) + { + PUCHAR src_addr = GET_OS_PKT_DATAPTR(pPacket); + src_addr += 6; + + for(MacEntryIdx=1; MacEntryIdxMacTab.Content[MacEntryIdx].Addr; + pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate); + 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)) + { + OS_PKT_CLONE(pAd, pPacket, pSkbClone, MEM_ALLOC_FLAG); + if ((pSkbClone) + ) + { + RTMP_SET_PACKET_WCID(pSkbClone, (UCHAR)pMacEntry->Aid); + /* Pkt type must set to PKTSRC_NDIS. */ + /* It cause of the deason that APHardTransmit() */ + /* doesn't handle PKTSRC_DRIVER pkt type in version 1.3.0.0. */ + RTMP_SET_PACKET_SOURCE(pSkbClone, PKTSRC_NDIS); + } + else + { + if (IgmpPktInGroup == IGMP_IN_GROUP) + { + pMemberEntry = pMemberEntry->pNext; + if (pMemberEntry != NULL) + { + pMemberAddr = pMemberEntry->Addr; + pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate); + bContinue = TRUE; + } + else + bContinue = FALSE; + } + else if (IgmpPktInGroup == IGMP_PKT) + { + PUCHAR src_addr = GET_OS_PKT_DATAPTR(pPacket); + src_addr += 6; + for(MacEntryIdx=pMacEntry->Aid + 1; MacEntryIdxMacTab.Content[MacEntryIdx].Addr; + pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate); + 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; + } + } + if (MacEntryIdx == MAX_NUMBER_OF_MAC) + bContinue = FALSE; + } + else + bContinue = FALSE; + + continue; + } + + if (PsMode == PWR_SAVE) + { + APInsertPsQueue(pAd, pSkbClone, pMacEntry, QueIdx); + } + else + { + /* insert the pkt to TxSwQueue. */ + if (pAd->TxSwQueue[QueIdx].Number >= pAd->TxSwQMaxLen) + { +#ifdef BLOCK_NET_IF + StopNetIfQueue(pAd, QueIdx, pSkbClone); +#endif /* BLOCK_NET_IF */ + 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 DOT11_N_SUPPORT + RTMP_BASetup(pAd, pMacEntry, UserPriority); +#endif /* DOT11_N_SUPPORT */ + } + + if (IgmpPktInGroup == IGMP_IN_GROUP) + { + pMemberEntry = pMemberEntry->pNext; + if (pMemberEntry != NULL) + { + pMemberAddr = pMemberEntry->Addr; + pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate); + bContinue = TRUE; + } + else + bContinue = FALSE; + } + else if (IgmpPktInGroup == IGMP_PKT) + { + for(MacEntryIdx=pMacEntry->Aid + 1; MacEntryIdxMacTab.Content[MacEntryIdx].Addr; + pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate); + if (pMacEntry && IS_ENTRY_CLIENT(pMacEntry) + && get_netdev_from_bssid(pAd, pMacEntry->apidx) == pNetDev) + { + pMemberAddr = pMacEntry->Addr; + bContinue = TRUE; + break; + } + } + if (MacEntryIdx == MAX_NUMBER_OF_MAC) + bContinue = FALSE; + } + else + bContinue = FALSE; + } + + 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; +} + +BOOLEAN IPv6MulticastFilterExcluded( + IN PUCHAR pDstMacAddr, + IN PUCHAR pIpHeader) +{ + BOOLEAN result = FALSE; + UINT16 IpProtocol = ntohs(*((UINT16 *)(pIpHeader))); + INT idx; + UINT8 nextProtocol; + + if(!IS_IPV6_MULTICAST_MAC_ADDR(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); + UINT32 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; + } + } while(FALSE); + + for (idx = 0; idx < IPV6_MULTICAST_FILTER_EXCLUED_SIZE; idx++) + { + if (nextProtocol == IPv6MulticastFilterExclued[idx]) + { + result = TRUE; + break; + } + } + + return result; +} + +/* 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); + 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); + 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; +} + + +#endif /* IGMP_SNOOP_SUPPORT */ diff --git a/mt7620/src/common/mesh.c b/mt7620/src/common/mesh.c new file mode 100644 index 0000000..b74a764 --- /dev/null +++ b/mt7620/src/common/mesh.c @@ -0,0 +1,3543 @@ +/* + *************************************************************************** + * 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: + mesh.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi 2007-06-25 For mesh (802.11s) support. +*/ + +#ifdef MESH_SUPPORT + + +#include "rt_config.h" +#include "mesh_sanity.h" + +extern UCHAR OUI_WPA_NONE_AKM[4]; +extern UCHAR OUI_WPA_TKIP[4]; +extern UCHAR OUI_WPA_CCMP[4]; +extern UCHAR OUI_WPA2_TKIP[4]; +extern UCHAR OUI_WPA2_CCMP[4]; +extern UCHAR OUI_MSA_8021X_AKM[4]; /* Not yet final - IEEE 802.11s-D1.06 */ +extern UCHAR OUI_MSA_PSK_AKM[4]; /* Not yet final - IEEE 802.11s-D1.06 */ + + +typedef VOID (*MESH_ACT_FRAME_HANDLER_FUNC)(IN PRTMP_ADAPTER pAd, IN RX_BLK *pRxBlk); + +typedef struct _MESH_ACTION_HANDLER +{ + UINT8 Category; + UINT8 ActionCode; + MESH_ACT_FRAME_HANDLER_FUNC pHandle; +} MESH_ACTION_HANDLER, *PMESH_ACTION_HANDLER; + +static MESH_ACTION_HANDLER MeshActHandler[] = +{ + /* Peer Link Management. */ + {CATEGORY_MESH_PEER_LINK, ACT_CODE_PEER_LINK_OPEN, (MESH_ACT_FRAME_HANDLER_FUNC)MeshPeerLinkOpenProcess}, + {CATEGORY_MESH_PEER_LINK, ACT_CODE_PEER_LINK_CONFIRM, (MESH_ACT_FRAME_HANDLER_FUNC)MeshPeerLinkConfirmProcess}, + {CATEGORY_MESH_PEER_LINK, ACT_CODE_PEER_LINK_CLOSE, (MESH_ACT_FRAME_HANDLER_FUNC)MeshPeerLinkCloseProcess}, + + /* Peer Link Metric. */ + {CATEGORY_MESH_LINK_METRIC, ACT_CODE_LINK_METRIC_REP, (MESH_ACT_FRAME_HANDLER_FUNC)MeshPeerLinkMetricReportProcess}, + + /* HWMP. */ + {CATEGORY_MESH_PATH_SELECTION, ACT_CODE_PATH_REQUEST, (MESH_ACT_FRAME_HANDLER_FUNC)MeshPreqRcvProcess}, + {CATEGORY_MESH_PATH_SELECTION, ACT_CODE_PATH_REPLY, (MESH_ACT_FRAME_HANDLER_FUNC)MeshPrepRcvProcess}, + {CATEGORY_MESH_PATH_SELECTION, ACT_CODE_PATH_ERROR, (MESH_ACT_FRAME_HANDLER_FUNC)MeshPerrRcvProcess}, + {CATEGORY_MESH_PATH_SELECTION, ACT_CODE_MULTIPATH_NOTICE, + (MESH_ACT_FRAME_HANDLER_FUNC)MeshMultipathNoticeRcvProcess}, + + {CATEGORY_MESH_RES_COORDINATION, RESOURCE_CHANNEL_SWITCH_ANNOUNCEMENT, + (MESH_ACT_FRAME_HANDLER_FUNC)MeshChSwAnnounceProcess} +}; +#define MESH_ACT_HANDLER_TAB_SIZE (sizeof(MeshActHandler) / sizeof(MESH_ACTION_HANDLER)) + + + + +INT Set_MeshId_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT success = FALSE; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if(!IS_MESH_IF(pObj)) + return FALSE; + + if(strlen(arg) <= MAX_MESH_ID_LEN) + { + NdisZeroMemory(pAd->MeshTab.MeshId, MAX_MESH_ID_LEN); + NdisMoveMemory(pAd->MeshTab.MeshId, arg, strlen(arg)); + pAd->MeshTab.MeshIdLen = (UCHAR)strlen(arg); + success = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(mesh0) Set_MeshId_Proc::(Len=%d,MeshId=%s)\n", + pAd->MeshTab.MeshIdLen, pAd->MeshTab.MeshId)); + + MeshDown(pAd, TRUE); + MeshUp(pAd); + } + else + success = FALSE; + + return success; +} + +INT Set_MeshHostName_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT success = FALSE; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if(!IS_MESH_IF(pObj)) + return FALSE; + + if(strlen(arg) <= MAX_HOST_NAME_LEN) + { + NdisZeroMemory(pAd->MeshTab.HostName, MAX_HOST_NAME_LEN); + NdisMoveMemory(pAd->MeshTab.HostName, arg, strlen(arg)); + success = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(mesh0) Set_MeshHostName_Proc::(HostName=%s)\n", + pAd->MeshTab.HostName)); + } + else + success = FALSE; + + return success; +} + +INT Set_MeshAutoLink_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT Enable; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if(!IS_MESH_IF(pObj)) + return FALSE; + + Enable = simple_strtol(arg, 0, 16); + + pAd->MeshTab.MeshAutoLink = (Enable > 0) ? TRUE : FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s::(enable = %d)\n", __FUNCTION__, pAd->MeshTab.MeshAutoLink)); + + return TRUE; +} + + +INT Set_MeshForward_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT Enable; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if(!IS_MESH_IF(pObj)) + return FALSE; + + Enable = simple_strtol(arg, 0, 16); + + pAd->MeshTab.MeshCapability.field.Forwarding = (Enable > 0) ? (1) : (0); + + DBGPRINT(RT_DEBUG_TRACE, ("%s::(enable = %d)\n", __FUNCTION__, pAd->MeshTab.MeshCapability.field.Forwarding)); + + return TRUE; +} + + +INT Set_MeshPortal_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT Enable; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if(!IS_MESH_IF(pObj)) + return FALSE; + + Enable = simple_strtol(arg, 0, 16); + + if (Enable) + pAd->MeshTab.OpMode |= MESH_POTAL; + else + pAd->MeshTab.OpMode ^= MESH_POTAL; + + + DBGPRINT(RT_DEBUG_TRACE, ("%s::(enable = %d)\n", __FUNCTION__, pAd->MeshTab.OpMode)); + + return TRUE; +} + +INT Set_MeshAddLink_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i; + PSTRING value; + UCHAR PeerMac[ETH_LENGTH_OF_ADDRESS]; + ULONG LinkIdx; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if(!IS_MESH_IF(pObj)) + return FALSE; + + 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, &PeerMac[i], 1); + } + + if(i != 6) + return FALSE; /*Invalid */ + } + + LinkIdx = GetMeshLinkId(pAd, (PCHAR)PeerMac); + if (LinkIdx == BSS_NOT_FOUND) + { + LinkIdx = MeshLinkAlloc(pAd, PeerMac, MESH_LINK_STATIC); + if (LinkIdx == BSS_NOT_FOUND) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() All Mesh-Links been occupied.\n", __FUNCTION__)); + return FALSE; + } + } + + if (!VALID_MESH_LINK_ID(LinkIdx)) + return FALSE; + + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_ACTOPN, 0, NULL, LinkIdx); + + DBGPRINT(RT_DEBUG_TRACE, ("%s::(LinkIdx = %ld)\n", __FUNCTION__, LinkIdx)); + + return TRUE; +} + +INT Set_MeshDelLink_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i; + PSTRING value; + UCHAR PeerMac[ETH_LENGTH_OF_ADDRESS]; + ULONG LinkIdx; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if(!IS_MESH_IF(pObj)) + return FALSE; + + 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, &PeerMac[i], 1); + } + + if(i != 6) + return FALSE; /*Invalid */ + } + + LinkIdx = GetMeshLinkId(pAd, (PCHAR)PeerMac); + if (!VALID_MESH_LINK_ID(LinkIdx)) + return FALSE; + + pAd->MeshTab.MeshLink[LinkIdx].Entry.LinkType = MESH_LINK_DYNAMIC; + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_CNCL, 0, NULL, LinkIdx); + + DBGPRINT(RT_DEBUG_TRACE, ("%s::(LinkIdx = %ld)\n", __FUNCTION__, LinkIdx)); + + return TRUE; +} + +INT Set_MeshMaxTxRate_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT Rate; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if(!IS_MESH_IF(pObj)) + return FALSE; + + Rate = simple_strtol(arg, 0, 10); + + if (Rate <= 12) + pAd->MeshTab.MeshMaxTxRate = Rate; + else + DBGPRINT(RT_DEBUG_ERROR, ("%s::Wrong Tx Rate setting(%d), (0 ~ 12))\n", __FUNCTION__, Rate)); + + DBGPRINT(RT_DEBUG_TRACE, ("%s::(Max Tx Rate = %ld)\n", __FUNCTION__, pAd->MeshTab.MeshMaxTxRate)); + + return TRUE; +} + +INT Set_MeshRouteAdd_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT success = TRUE; + return success; +} + +INT Set_MeshRouteDelete_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT success = TRUE; + return success; +} + +INT Set_MeshRouteUpdate_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT success = TRUE; + return success; +} + +INT Set_MeshMultiCastAgeOut_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT AgeTime; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if(!IS_MESH_IF(pObj)) + return FALSE; + + AgeTime = simple_strtol(arg, 0, 10); + + if ((AgeTime <= 65535) && (AgeTime >= 1)) + pAd->MeshTab.MeshMultiCastAgeOut = AgeTime; + else + DBGPRINT(RT_DEBUG_ERROR, ("%s::Wrong MeshMultiCastAgeOut setting(%d), (1 ~ 65535))\n", __FUNCTION__, AgeTime)); + + DBGPRINT(RT_DEBUG_TRACE, ("%s::(MeshMultiCastAgeOut = %ld)\n", __FUNCTION__, pAd->MeshTab.MeshMultiCastAgeOut)); + + pAd->MeshTab.MeshMultiCastAgeOut = (AgeTime * 1000); + + return TRUE; +} + +INT Set_MeshAuthMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR i; + INT success = TRUE; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if(!IS_MESH_IF(pObj)) + return FALSE; + + if ((strncmp(arg, "WPANONE", 7) == 0) || (strncmp(arg, "wpanone", 7) == 0)) + pAd->MeshTab.AuthMode = Ndis802_11AuthModeWPANone; + else + pAd->MeshTab.AuthMode = Ndis802_11AuthModeOpen; + + /* Set all mesh link as Port_Not_Secure */ + for (i=0; iMacTab.Content[i])) + { + pAd->MacTab.Content[i].PortSecured = WPA_802_1X_PORT_NOT_SECURED; + } + } + + RTMPMakeRSNIE(pAd, pAd->MeshTab.AuthMode, pAd->MeshTab.WepStatus, MIN_NET_DEVICE_FOR_MESH); + + if(pAd->MeshTab.AuthMode >= Ndis802_11AuthModeWPA) + { + if (pAd->MeshTab.AuthMode == Ndis802_11AuthModeWPANone) + pAd->MeshTab.DefaultKeyId = 0; + else + pAd->MeshTab.DefaultKeyId = 1; + } + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(mesh0) Set_MeshAuthMode_Proc::(MeshAuthMode(%d)=%s)\n", + pAd->MeshTab.AuthMode, GetAuthMode(pAd->MeshTab.AuthMode))); + + return success; +} + +INT Set_MeshEncrypType_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT success = TRUE; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if(!IS_MESH_IF(pObj)) + return FALSE; + + if ((strncmp(arg, "WEP", 3) == 0) || (strncmp(arg, "wep", 3) == 0)) + { + if (pAd->MeshTab.AuthMode < Ndis802_11AuthModeWPA) + pAd->MeshTab.WepStatus = Ndis802_11WEPEnabled; + } + else if ((strncmp(arg, "TKIP", 4) == 0) || (strncmp(arg, "tkip", 4) == 0)) + { + if (pAd->MeshTab.AuthMode >= Ndis802_11AuthModeWPA) + pAd->MeshTab.WepStatus = Ndis802_11Encryption2Enabled; + } + else if ((strncmp(arg, "AES", 3) == 0) || (strncmp(arg, "aes", 3) == 0)) + { + if (pAd->MeshTab.AuthMode >= Ndis802_11AuthModeWPA) + pAd->MeshTab.WepStatus = Ndis802_11Encryption3Enabled; + } + else + { + pAd->MeshTab.WepStatus = Ndis802_11WEPDisabled; + } + + if(pAd->MeshTab.WepStatus >= Ndis802_11Encryption2Enabled) + { + if (pAd->MeshTab.AuthMode == Ndis802_11AuthModeWPANone) + pAd->MeshTab.DefaultKeyId = 0; + else + pAd->MeshTab.DefaultKeyId = 1; + } + + RTMPMakeRSNIE(pAd, pAd->MeshTab.AuthMode, pAd->MeshTab.WepStatus, MIN_NET_DEVICE_FOR_MESH); + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(mesh0) Set_MeshEncrypType_Proc::(MeshEncrypType(%d)=%s)\n", + pAd->MeshTab.WepStatus, GetEncryptType(pAd->MeshTab.WepStatus))); + + return success; +} + +INT Set_MeshDefaultkey_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG KeyIdx; + INT success = TRUE; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if(!IS_MESH_IF(pObj)) + return FALSE; + + KeyIdx = simple_strtol(arg, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + pAd->MeshTab.DefaultKeyId = (UCHAR) (KeyIdx - 1); + else + pAd->MeshTab.DefaultKeyId = 0; /* Default value */ + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(mesh0) Set_MeshDefaultkey_Proc::(MeshDefaultkey=%d)\n", + pAd->MeshTab.DefaultKeyId)); + + return success; +} + +INT Set_MeshWEPKEY_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR i; + UCHAR KeyLen; + UCHAR CipherAlg = CIPHER_NONE; + INT success = TRUE; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if(!IS_MESH_IF(pObj)) + return FALSE; + + KeyLen = strlen(arg); + + switch (KeyLen) + { + case 5: /*wep 40 Ascii type */ + case 13: /*wep 104 Ascii type */ + pAd->MeshTab.SharedKey.KeyLen = KeyLen; + NdisMoveMemory(pAd->MeshTab.SharedKey.Key, arg, KeyLen); + if (KeyLen == 5) + CipherAlg = CIPHER_WEP64; + else + CipherAlg = CIPHER_WEP128; + + NdisMoveMemory(pAd->MeshTab.DesiredWepKey, arg, KeyLen); + pAd->MeshTab.DesiredWepKeyLen= KeyLen; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(mesh0) Set_MeshWEPKRY_Proc::(WepKey=%s ,type=%s, Alg=%s)\n", arg, "Ascii", CipherName[CipherAlg])); + break; + case 10: /*wep 40 Hex type */ + case 26: /*wep 104 Hex type */ + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; /*Not Hex value; */ + } + pAd->MeshTab.SharedKey.KeyLen = KeyLen/2 ; + AtoH(arg, pAd->MeshTab.SharedKey.Key, KeyLen/2); + if (KeyLen == 10) + CipherAlg = CIPHER_WEP64; + else + CipherAlg = CIPHER_WEP128; + + NdisMoveMemory(pAd->MeshTab.DesiredWepKey, arg, KeyLen); + pAd->MeshTab.DesiredWepKeyLen = KeyLen; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(mesh0) Set_MeshWEPKRY_Proc::(WepKey=%s, type=%s, Alg=%s)\n", arg, "Hex", CipherName[CipherAlg])); + break; + default: /*Invalid argument */ + pAd->MeshTab.SharedKey.KeyLen = 0; + pAd->MeshTab.DesiredWepKeyLen = KeyLen; + DBGPRINT(RT_DEBUG_ERROR, ("IF(mesh0) Set_MeshWEPKRY_Proc::Invalid argument (=%s)\n", arg)); + return FALSE; + } + + pAd->MeshTab.SharedKey.CipherAlg = CipherAlg; + + + return success; +} + + +INT Set_MeshWPAKEY_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + /*UCHAR keyMaterial[40]; */ + INT success = TRUE; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if(!IS_MESH_IF(pObj)) + return FALSE; + + success = RT_CfgSetWPAPSKKey(pAd, arg, pAd->MeshTab.MeshId, pAd->MeshTab.MeshIdLen, pAd->MeshTab.PMK); + if (success == FALSE) + return FALSE; + + NdisMoveMemory(pAd->MeshTab.WPAPassPhraseKey, arg, strlen(arg)); + pAd->MeshTab.WPAPassPhraseKeyLen = strlen(arg); + + DBGPRINT(RT_DEBUG_TRACE, ("IF(mesh0) Set_MeshWPAKEY_Proc::PassPhrasKey (=%s)\n", arg)); + + return success; +} + +INT Set_MeshRouteInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + PMESH_ROUTING_TABLE pRouteTab = pAd->MeshTab.pMeshRouteTab; + + if (pRouteTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Route Table doesn't exist.\n", __FUNCTION__)); + return FALSE; + } + + if(!IS_MESH_IF(pObj)) + return FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("\n\n")); + + DBGPRINT(RT_DEBUG_OFF, ("\n%-19s%-6s%-19s%-16s%-12s%-9s\n", + "MESH DA", "DSN", "NEXTHOP", "NEXTHOPLINKID", "METRICS", "ROUTE_IDX")); + + for (i=0; iContent[i]; + if (pEntry->Valid) + { + DBGPRINT(RT_DEBUG_OFF, ("%02X:%02X:%02X:%02X:%02X:%02X ", PRINT_MAC(pEntry->MeshDA))); + DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->Dsn)); + DBGPRINT(RT_DEBUG_OFF, ("%02X:%02X:%02X:%02X:%02X:%02X ", PRINT_MAC(pEntry->NextHop))); + DBGPRINT(RT_DEBUG_OFF, ("%-16d", (int)pEntry->NextHopLinkID)); + DBGPRINT(RT_DEBUG_OFF, ("%-12d", pEntry->PathMetric)); + DBGPRINT(RT_DEBUG_OFF, ("%-9d\n", (int)pEntry->Idx)); + } + } + + return TRUE; +} + + +INT Set_MeshProxyInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + + PMESH_PROXY_ENTRY pEntry = NULL; + SHORT EntryIndex; + PMESH_PROXY_ENTRY_TABLE pProxyTab = pAd->MeshTab.pMeshProxyTab; + int i=0; + + DBGPRINT(RT_DEBUG_OFF, ("pProxyTab size:%d free:%d\n",pProxyTab->AgeList.Number,pProxyTab->FreeEntryList.Number)); + + EntryIndex=pProxyTab->AgeList.Head; + if (EntryIndex >= 0) + pEntry=&pProxyTab->Content[EntryIndex]; + + DBGPRINT(RT_DEBUG_OFF, ("Mesh Proxy Age Out List\n")); + DBGPRINT(RT_DEBUG_OFF, ("Index,DLNext,DLPrev,HashNext,Mac\n")); + while(EntryIndex!=-1) + { + DBGPRINT(RT_DEBUG_OFF, ("%02d %02d %02d %02d MAC:%02x:%02x:%02x:%02x:%02x:%02x \n", + + EntryIndex,pEntry->DLNext,pEntry->DLPrev,pEntry->Next, + pEntry->MacAddr[0],pEntry->MacAddr[1],pEntry->MacAddr[2], + pEntry->MacAddr[3],pEntry->MacAddr[4],pEntry->MacAddr[5])); + + EntryIndex=pEntry->DLNext; + pEntry=&pProxyTab->Content[EntryIndex]; + + } + + DBGPRINT(RT_DEBUG_TRACE, ("Mesh Proxy Mac Hash Table \n")); + for(i=0;iHash[i]!=-1) + DBGPRINT(RT_DEBUG_TRACE, ("%03d : %d \n",i,pProxyTab->Hash[i])); + + } + + + DBGPRINT(RT_DEBUG_OFF, ("Mesh Content Table \n")); + DBGPRINT(RT_DEBUG_OFF, ("No,HashNext,DLNext,DLPrev\n")); + for(i=0;iContent[i].Next,pProxyTab->Content[i].DLNext,pProxyTab->Content[i].DLPrev)); + } + + return TRUE; +} + +INT Set_MeshEntryInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if(!IS_MESH_IF(pObj)) + return FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("\n%-19s%-10s\n", "DESTMAC", "ROUTE_IDX")); + + MeshEntryTableGet(pAd); + return TRUE; +} + +INT Set_MeshInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if(!IS_MESH_IF(pObj)) + return FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("HostName = %s, Len=%d\n", pAd->MeshTab.HostName, strlen((PSTRING)pAd->MeshTab.HostName))); + DBGPRINT(RT_DEBUG_OFF, ("Mesh Id = %s, Len=%d\n", pAd->MeshTab.MeshId, pAd->MeshTab.MeshIdLen)); + DBGPRINT(RT_DEBUG_OFF, ("Mesh AutoLink = %s\n", pAd->MeshTab.MeshAutoLink == TRUE ? "Enable" : "Disable")); + DBGPRINT(RT_DEBUG_OFF, ("Channel Precedence (CPI) = %d\n", pAd->MeshTab.CPI)); + DBGPRINT(RT_DEBUG_OFF, ("mesh ctrl current state =%d\n", pAd->MeshTab.CtrlCurrentState)); + DBGPRINT(RT_DEBUG_OFF, ("Mesh AuthMode(%d)=%s, EncrypType(%d)=%s \n", + pAd->MeshTab.AuthMode, GetAuthMode(pAd->MeshTab.AuthMode), + pAd->MeshTab.WepStatus, GetEncryptType(pAd->MeshTab.WepStatus))); + + + for (i = 0; i < MAX_MESH_LINKS; i++) + { + DBGPRINT(RT_DEBUG_OFF, ("mesh link (%d) current state =%d,", i, pAd->MeshTab.MeshLink[i].CurrentState)); + DBGPRINT(RT_DEBUG_OFF, (" Valid =%d,", pAd->MeshTab.MeshLink[i].Entry.Valid)); + DBGPRINT(RT_DEBUG_OFF, (" MatchWcid =%d,", pAd->MeshTab.MeshLink[i].Entry.MacTabMatchWCID)); + DBGPRINT(RT_DEBUG_OFF, (" LocalId =%x,", pAd->MeshTab.MeshLink[i].Entry.LocalLinkId)); + DBGPRINT(RT_DEBUG_OFF, (" PeerId =%x,", pAd->MeshTab.MeshLink[i].Entry.PeerLinkId)); + DBGPRINT(RT_DEBUG_OFF, (" ExtChOffset =%d,", pAd->MeshTab.MeshLink[i].Entry.ExtChOffset)); + DBGPRINT(RT_DEBUG_OFF, (" PeerMacAddr =%02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr[0], pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr[1], + pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr[2], pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr[3], + pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr[4], pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr[5])); + } + DBGPRINT(RT_DEBUG_OFF, ("\n\n")); + + 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_MESH(pEntry)) + { + DBGPRINT(RT_DEBUG_OFF, ("%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->MatchWDSTabIdx)); + 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)); +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("%-10s", GetPhyMode(pEntry->HTPhyMode.field.MODE))); + DBGPRINT(RT_DEBUG_OFF, ("%-6s", GetBW(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\n", pEntry->HTPhyMode.field.STBC)); +#endif /* DOT11_N_SUPPORT */ + } + } + + return TRUE; +} + +INT Set_NeighborInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int i; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if(!IS_MESH_IF(pObj)) + return FALSE; + + if (pAd->MeshTab.pMeshNeighborTab == NULL) + { + DBGPRINT(RT_DEBUG_OFF, ("Mesh Neighbor Tab not ready.\n")); + return TRUE; + } + + + if (pAd->MeshTab.pMeshNeighborTab->NeighborNr == 0) + { + DBGPRINT(RT_DEBUG_OFF, ("Mesh Neighbor Tab empty.\n")); + return TRUE; + } + + DBGPRINT(RT_DEBUG_OFF, ("Neighbor MP Num = %d\n", pAd->MeshTab.pMeshNeighborTab->NeighborNr)); + DBGPRINT(RT_DEBUG_OFF, ("\n%-4s%-19s%-6s%-4s%-4s%-6s%-8s%-6s%-8s%-14s%-16s%-6s\n", + "IDX", "MAC", "MRSI", "CH", "BW", "CHOF", "CPI", "STATE", "LINKID", "ECRP", "MESHID", "HSTN")); + + for (i=0; iMeshTab.pMeshNeighborTab->NeighborMP[i]; + if (pEntry->Valid) + { + DBGPRINT(RT_DEBUG_OFF, ("%-4d", i)); + DBGPRINT(RT_DEBUG_OFF, ("%02X:%02X:%02X:%02X:%02X:%02X ", + pEntry->PeerMac[0], pEntry->PeerMac[1], pEntry->PeerMac[2], + pEntry->PeerMac[3], pEntry->PeerMac[4], pEntry->PeerMac[5])); + DBGPRINT(RT_DEBUG_OFF, ("%-6d", (int)pEntry->RealRssi)); + DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->Channel)); + DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->ChBW)); + DBGPRINT(RT_DEBUG_OFF, ("%-6d", (int)pEntry->ExtChOffset)); + DBGPRINT(RT_DEBUG_OFF, ("%-8d", (int)pEntry->CPI)); + DBGPRINT(RT_DEBUG_OFF, ("%-6d", (int)pEntry->State)); + DBGPRINT(RT_DEBUG_OFF, ("%-8x", (int)pEntry->MeshLinkIdx)); + MeshEncrypType = MeshCheckPeerMpCipher(pEntry->CapabilityInfo, pEntry->RSNIE, pEntry->RSNIE_Len); + if (MeshEncrypType == ENCRYPT_OPEN_WEP) + { + DBGPRINT(RT_DEBUG_OFF, ("%-14s", "OPEN-WEP")); + } + else if (MeshEncrypType == ENCRYPT_WPANONE_TKIP) + { + DBGPRINT(RT_DEBUG_OFF, ("%-14s", "WPANONE-TKIP")); + } + else if (MeshEncrypType == ENCRYPT_WPANONE_AES) + { + DBGPRINT(RT_DEBUG_OFF, ("%-14s", "WPANONE-AES")); + } + else + { + DBGPRINT(RT_DEBUG_OFF, ("%-14s", "OPEN-NONE")); + } + DBGPRINT(RT_DEBUG_OFF, ("%-16s", pEntry->MeshId)); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", pEntry->HostName)); + } + } + + return TRUE; +} + +INT Set_MultipathInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i; + LONG HashId; + PMESH_MULTIPATH_ENTRY pEntry; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if(!IS_MESH_IF(pObj)) + return FALSE; + + for (i = 0; i < MAX_MESH_LINKS; i++) + { + if (!PeerLinkValidCheck(pAd, i)) + continue; + DBGPRINT(RT_DEBUG_OFF, ("Link(%d) ", i)); + for (HashId = 0; HashId < MULTIPATH_HASH_TAB_SIZE; HashId++) + { + pEntry = (PMESH_MULTIPATH_ENTRY)(pAd->MeshTab.MeshLink[i].Entry.MultiPathHash[HashId].pHead); + if (pEntry == NULL) + continue; + + DBGPRINT(RT_DEBUG_OFF, (" HashId(%ld):", HashId)); + while (pEntry) + { + DBGPRINT(RT_DEBUG_OFF, ("SA=%02x:%02x:%02x:%02x:%02x:%02x ", + pEntry->MeshSA[0], pEntry->MeshSA[1], pEntry->MeshSA[2], + pEntry->MeshSA[3], pEntry->MeshSA[4], pEntry->MeshSA[5])); + pEntry = pEntry->pNext; + } + } + DBGPRINT(RT_DEBUG_OFF, ("\n")); + } + + return TRUE; +} + +INT Set_MultiCastAgeOut_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if(!IS_MESH_IF(pObj)) + return FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("Multi Cast Age Timeout = %ld sec\n", (pAd->MeshTab.MeshMultiCastAgeOut) / 1000)); + + return TRUE; +} + +INT Set_MeshOnly_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT Enable; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if(!IS_MESH_IF(pObj)) + return FALSE; + + Enable = (UINT) simple_strtol(arg, 0, 16); + + pAd->MeshTab.MeshOnly= (Enable > 0) ? TRUE : FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s::(enable = %d)\n", __FUNCTION__, pAd->MeshTab.MeshOnly)); + + return TRUE; +} + +INT Set_PktSig_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + PMESH_BMPKTSIG_TAB pTab = pAd->MeshTab.pBMPktSigTab; + + if(!IS_MESH_IF(pObj)) + return FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("\n%-4s%-19s%-4s\n", "IDX", "MAC", "SEQ")); + for (i=0; iContent[i]); + if (pTab->Content[i].Valid == FALSE) + continue; + + DBGPRINT(RT_DEBUG_OFF, ("%-4d", i)); + DBGPRINT(RT_DEBUG_OFF, ("%02x:%02x:%02x:%02x:%02x:%02x ", + pEntry->MeshSA[0], pEntry->MeshSA[1], pEntry->MeshSA[2], + pEntry->MeshSA[3], pEntry->MeshSA[4], pEntry->MeshSA[5])); + DBGPRINT(RT_DEBUG_OFF, ("%-8x:%-9x%-9x%-9x%-9x", + pEntry->MeshSeqBased, pEntry->Offset[0], pEntry->Offset[1], + pEntry->Offset[2], pEntry->Offset[3])); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + } + + return TRUE; +} + +/* --------------------------------- Public -------------------------------- */ +/* +======================================================================== +Routine Description: + Close Mesh network interface. + +Arguments: + ad_p points to our adapter + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RTMP_Mesh_Close( + IN PRTMP_ADAPTER pAd) +{ + + /* free Mesh Tables and allocate spin locks */ + NdisFreeSpinLock(&pAd->MeshTabLock); + + /* close virtual interface. */ + if (pAd->MeshTab.dev) + RtmpOSNetDevClose(pAd->MeshTab.dev); + +} /* End of RTMP_Mesh_Close */ + + +/* +======================================================================== +Routine Description: + Remove Mesh network interface. + +Arguments: + ad_p points to our adapter + +Return Value: + None + +Note: +======================================================================== +*/ +VOID MESH_Remove( + IN PRTMP_ADAPTER pAd) +{ + + +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + + /* remove virtual interface. */ + if (pAd->MeshTab.dev) + { + RtmpOSNetDevDetach(pAd->MeshTab.dev); + RtmpOSNetDevFree(pAd->MeshTab.dev); + } + + NeighborTableDestroy(pAd); + BMPktSigTabExit(pAd); + MultipathPoolExit(pAd); + + MeshRoutingTable_Exit(pAd); + MeshEntryTable_Exit(pAd); + MeshProxyEntryTable_Exit(pAd); + +} /* End of MESH_Remove */ + + +/* --------------------------------- Private -------------------------------- */ + +VOID MeshUp( + IN PRTMP_ADAPTER pAd) +{ + BOOLEAN TxPreamble; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: ===> \n", __FUNCTION__)); + 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; + + pAd->MeshTab.MeshChannel = pAd->CommonCfg.Channel; + + /* Make regular Beacon frame */ + MeshMakeBeacon(pAd, MESH_BEACON_IDX(pAd)); + + /* Check if the security is supported */ + if (pAd->MeshTab.EasyMeshSecurity) + { + if (pAd->MeshTab.AuthMode != Ndis802_11AuthModeOpen && + pAd->MeshTab.AuthMode != Ndis802_11AuthModeWPANone) + { + pAd->MeshTab.AuthMode = Ndis802_11AuthModeOpen; + pAd->MeshTab.WepStatus = Ndis802_11WEPDisabled; + } + pAd->MeshTab.OpMode &= ~(MESH_MKD); + + DBGPRINT(RT_DEBUG_TRACE, ("MeshUp: the Easy MSA is enabled. \n")); + } + else + { + if (pAd->MeshTab.AuthMode != Ndis802_11AuthModeWPA2 && + pAd->MeshTab.AuthMode != Ndis802_11AuthModeWPA2PSK) + { + pAd->MeshTab.AuthMode = Ndis802_11AuthModeWPA2; + pAd->MeshTab.WepStatus = Ndis802_11Encryption3Enabled; + } + + DBGPRINT(RT_DEBUG_TRACE, ("MeshUp: the Easy MSA is disabled. \n")); + } + + if (pAd->MeshTab.OpMode & MESH_MKD) + { + NdisMoveMemory(pAd->MeshTab.LocalMSCIE.MKDDID, pAd->MeshTab.CurrentAddress, MAC_ADDR_LEN); + pAd->MeshTab.bInitialMsaDone = TRUE; + pAd->MeshTab.bKeyholderDone = TRUE; + pAd->MeshTab.bConnectedToMKD = TRUE; + } + else + { + NdisZeroMemory(&pAd->MeshTab.LocalMSCIE, sizeof(MESH_SECURITY_CAPABILITY_IE)); + pAd->MeshTab.bInitialMsaDone = FALSE; + pAd->MeshTab.bKeyholderDone = FALSE; + pAd->MeshTab.bConnectedToMKD = FALSE; + } + +#ifdef CONFIG_STA_SUPPORT + /* set my current address as my BSSID */ + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + AsicSetBssid(pAd, pAd->CurrentAddress); +#endif /* CONFIG_STA_SUPPORT */ + + /* Init PMKID */ + pAd->MeshTab.PMKID_Len = 0; + NdisZeroMemory(pAd->MeshTab.PMKID, LEN_PMKID); + + TxPreamble = (pAd->CommonCfg.TxPreamble == Rt802_11PreambleLong ? 0 : 1); + + pAd->MeshTab.CapabilityInfo = + CAP_GENERATE(0, 0, (pAd->MeshTab.WepStatus != Ndis802_11EncryptionDisabled), TxPreamble, pAd->CommonCfg.bUseShortSlotTime, 0); + + if (pAd->MeshTab.AuthMode == Ndis802_11AuthModeWPANone) + { + pAd->MeshTab.DefaultKeyId = 0; /* always be zero */ + + NdisZeroMemory(&pAd->MeshTab.SharedKey, sizeof(CIPHER_KEY)); + pAd->MeshTab.SharedKey.KeyLen = LEN_TK; + + NdisMoveMemory(pAd->MeshTab.SharedKey.Key, pAd->MeshTab.PMK, LEN_TK); + + if (pAd->MeshTab.WepStatus == Ndis802_11Encryption2Enabled) + { + NdisMoveMemory(pAd->MeshTab.SharedKey.RxMic, &pAd->MeshTab.PMK[16], LEN_TKIP_MIC); + NdisMoveMemory(pAd->MeshTab.SharedKey.TxMic, &pAd->MeshTab.PMK[16], LEN_TKIP_MIC); + } + + /* Decide its ChiperAlg */ + if (pAd->MeshTab.WepStatus == Ndis802_11Encryption2Enabled) + pAd->MeshTab.SharedKey.CipherAlg = CIPHER_TKIP; + else if (pAd->MeshTab.WepStatus == Ndis802_11Encryption3Enabled) + pAd->MeshTab.SharedKey.CipherAlg = CIPHER_AES; + else + { + DBGPRINT(RT_DEBUG_WARN, ("Unknow Cipher (=%d), set Cipher to AES\n", pAd->MeshTab.WepStatus)); + pAd->MeshTab.SharedKey.CipherAlg = CIPHER_AES; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("!!! %s - AuthMode(%d)=%s, WepStatus(%d)=%s !!!\n", + __FUNCTION__, + pAd->MeshTab.AuthMode, GetAuthMode(pAd->MeshTab.AuthMode), + pAd->MeshTab.WepStatus, GetEncryptType(pAd->MeshTab.WepStatus))); + + MlmeEnqueue(pAd, MESH_CTRL_STATE_MACHINE, MESH_CTRL_JOIN, 0, NULL, 0); + DBGPRINT(RT_DEBUG_TRACE, ("%s: <=== \n", __FUNCTION__)); +} + +BOOLEAN MeshLinkCheck( + IN VOID *pAdSrc) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + BOOLEAN WaitMeshClose = FALSE; + INT idx; + + + for (idx = 0; idx < MAX_MESH_LINKS; idx++) + { + if (PeerLinkMngRuning(pAd, idx) || PeerLinkValidCheck(pAd, idx)) + WaitMeshClose = TRUE; + } + return WaitMeshClose; +} + +VOID MeshDown( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN WaitFlag) +{ + INT idx; + + /* clear PMKID */ + pAd->MeshTab.PMKID_Len = 0; + NdisZeroMemory(pAd->MeshTab.PMKID, LEN_PMKID); + + /* clear these flag */ + pAd->MeshTab.bInitialMsaDone = FALSE; + pAd->MeshTab.bKeyholderDone = FALSE; + pAd->MeshTab.bConnectedToMKD = FALSE; + +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + + MlmeEnqueue(pAd, MESH_CTRL_STATE_MACHINE, MESH_CTRL_DISCONNECT, 0, NULL, 0); + MeshMlmeHandler(pAd); + + + RtmpMeshDown(pAd, WaitFlag, MeshLinkCheck); + + /* delete all mesh links. */ + for (idx = 0; idx < MAX_MESH_LINKS; idx++) + { + if (pAd->MeshTab.MeshLink[idx].Entry.Valid) + MeshLinkDelete(pAd, pAd->MeshTab.MeshLink[idx].Entry.PeerMacAddr, idx); + } + + /* when the ra interface is down, do not send its beacon frame */ + MeshCleanBeaconFrame(pAd, MESH_BEACON_IDX(pAd)); + +#ifdef CONFIG_STA_SUPPORT + /* resume BSSID for infra mode */ + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + AsicSetBssid(pAd, pAd->CommonCfg.Bssid); +#endif /* CONFIG_STA_SUPPORT */ +} + +VOID MeshHalt( + IN PRTMP_ADAPTER pAd) +{ + int idx; + BOOLEAN Cancelled; + + RTMPCancelTimer(&pAd->MeshTab.PldTimer, &Cancelled); + RTMPCancelTimer(&pAd->MeshTab.McsTimer, &Cancelled); + for (idx = 0; idx < MAX_MESH_LINKS; idx++) + { + RTMPCancelTimer(&pAd->MeshTab.MeshLink[idx].TOR, &Cancelled); + RTMPCancelTimer(&pAd->MeshTab.MeshLink[idx].TOC, &Cancelled); + RTMPCancelTimer(&pAd->MeshTab.MeshLink[idx].TOH, &Cancelled); + } +} + +VOID TearDownAllMeshLink( + IN PRTMP_ADAPTER pAd) +{ + INT i; + PMESH_NEIGHBOR_ENTRY pNeighbor = NULL; + DBGPRINT(RT_DEBUG_TRACE, ("%s: tear down all Mesh Link.\n", __FUNCTION__)); + + for (i = 0; i < MAX_MESH_LINKS; i++) + { + if(PeerLinkValidCheck(pAd, i)) + { + /* + SendMeshPeerLinkClose(pAd, pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr, + pAd->MeshTab.MeshLink[i].Entry.LocalLinkId, + pAd->MeshTab.MeshLink[i].Entry.PeerLinkId, + MESH_LINK_CANCELLED); + */ + /*send link close message */ + { + PUCHAR pPeerMac=pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr; + UINT32 LocalLinkId=pAd->MeshTab.MeshLink[i].Entry.LocalLinkId; + UINT32 PeerLinkId=pAd->MeshTab.MeshLink[i].Entry.PeerLinkId; + HEADER_802_11 MeshHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + MESH_FLAG MeshFlag; + UINT32 MeshSeq = INC_MESH_SEQ(pAd->MeshTab.MeshSeq); + + 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; + } + + MeshHeaderInit(pAd, &MeshHdr, + pPeerMac, /* addr1 */ + pAd->MeshTab.CurrentAddress, /* addr2 */ + ZERO_MAC_ADDR); /* addr3 */ + NdisMoveMemory(pOutBuffer, (PCHAR)&MeshHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + /* Mesh Header */ + MeshFlag.word = 0; + MeshFlag.field.AE = 0; /* Peer-Link manager frame never carry 6 addresses. */ + InsertMeshHeader(pAd, (pOutBuffer + FrameLen), &FrameLen, MeshFlag.word, + pAd->MeshTab.TTL, MeshSeq, NULL, NULL, NULL); + + /* Action field */ + InsertMeshActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_MESH_PEER_LINK, ACT_CODE_PEER_LINK_CLOSE); + + /* Reason code */ + InsertReasonCode(pAd, (pOutBuffer + FrameLen), &FrameLen, MESH_LINK_CANCELLED); + + /* Mesh Peer Link Management IE */ + InsertMeshPeerLinkMngIE(pAd, (pOutBuffer + FrameLen), &FrameLen, SUBTYPE_PEER_LINK_CLOSE, + LocalLinkId, PeerLinkId, MESH_LINK_CANCELLED); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: LocalLinkId=%x, PeerLinkId=%x, Reason=%d\n", + __FUNCTION__, LocalLinkId, PeerLinkId, MESH_LINK_CANCELLED)); + + } + + + pNeighbor = NeighborSearch(pAd, pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr); + if (pNeighbor) + { + pNeighbor->State = NEIGHBOR_MP; + pNeighbor->MeshLinkIdx = 0; + } + + if (pAd->MeshTab.LinkSize == 0) + { + pAd->MeshTab.bInitialMsaDone = FALSE; + } + + MultipathListDelete(pAd, i); + + + if(MeshTableLookup(pAd, pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr, TRUE)) + MacTableDeleteMeshEntry(pAd, pAd->MeshTab.MeshLink[i].Entry.MacTabMatchWCID, + pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr); + + + if (pAd->MeshTab.MeshLink[i].Entry.Valid) + { + MeshLinkDelete(pAd, pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr, i); + } + } + } +} + +BOOLEAN MeshAcceptPeerLink( + IN PRTMP_ADAPTER pAd) +{ + return (pAd->MeshTab.LinkSize < MAX_MESH_LINKS) ? 1 : 0; +} + +MAC_TABLE_ENTRY *MacTableInsertMeshEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UINT MeshLinkIdx) +{ + PMAC_TABLE_ENTRY pEntry = NULL; + + /* if FULL, return */ + if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE) + return NULL; + + do + { + if((pEntry = MeshTableLookup(pAd, pAddr, TRUE)) != NULL) + break; + + /* allocate one MAC entry */ + pEntry = MacTableInsertEntry(pAd, pAddr, MeshLinkIdx + MIN_NET_DEVICE_FOR_MESH, OPMODE_AP, TRUE); + if (pEntry) + { + pAd->MeshTab.MeshLink[MeshLinkIdx].Entry.MacTabMatchWCID = pEntry->Aid; + pEntry->MatchMeshTabIdx = MeshLinkIdx; + + pEntry->MaxHTPhyMode.word = pAd->MeshTab.MaxHTPhyMode.word; + pEntry->MinHTPhyMode.word = pAd->MeshTab.MinHTPhyMode.word; + pEntry->HTPhyMode.word = pAd->MeshTab.HTPhyMode.word; + +#ifdef DOT11_N_SUPPORT + if (pAd->MeshTab.HTPhyMode.field.MODE >= MODE_HTMIX) + { + if (pAd->MeshTab.DesiredTransmitSetting.field.MCS != MCS_AUTO) + { + DBGPRINT(RT_DEBUG_TRACE, ("IF-mesh0 : Desired MCS = %d\n", + pAd->MeshTab.DesiredTransmitSetting.field.MCS)); + + if (pAd->MeshTab.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->MeshTab.HTPhyMode.field.MCS) + { + /* STA supports fixed MCS */ + pEntry->MaxHTPhyMode.field.MCS = pAd->MeshTab.HTPhyMode.field.MCS; + } + } + } +#endif /* DOT11_N_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertMeshEntry - allocate entry #%d, Total= %d\n",pEntry->Aid, pAd->MacTab.Size)); + break; + } + } while(FALSE); + + return pEntry; +} + + +/* + ========================================================================== + Description: + Delete all Mesh Entry in pAd->MacTab + ========================================================================== + */ +BOOLEAN MacTableDeleteMeshEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT wcid, + IN PUCHAR pAddr) +{ + if (!VALID_WCID(wcid)) + return FALSE; + + MacTableDeleteEntry(pAd, wcid, pAddr); + MeshCreatePerrAction(pAd, pAddr); + + return TRUE; +} + +MAC_TABLE_ENTRY *MeshTableLookup( + 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_MESH(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 *MeshTableLookupByWcid( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount) +{ + ULONG MeshIndex; + PMAC_TABLE_ENTRY pCurEntry = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + + if (!VALID_WCID(wcid)) + return NULL; + + RTMP_SEM_LOCK(&pAd->MeshTabLock); + RTMP_SEM_LOCK(&pAd->MacTabLock); + + do + { + pCurEntry = &pAd->MacTab.Content[wcid]; + + MeshIndex = 0xff; + if ((pCurEntry) && IS_ENTRY_MESH(pCurEntry)) + { + MeshIndex = pCurEntry->MatchMeshTabIdx; + } + + if (MeshIndex == 0xff) + break; + + if (pAd->MeshTab.MeshLink[MeshIndex].Entry.Valid != TRUE) + break; + + if (MAC_ADDR_EQUAL(pCurEntry->Addr, pAddr)) + { + if(bResetIdelCount) + pCurEntry->NoDataIdleCount = 0; + pEntry = pCurEntry; + break; + } + } while(FALSE); + + RTMP_SEM_UNLOCK(&pAd->MacTabLock); + RTMP_SEM_UNLOCK(&pAd->MeshTabLock); + + return pEntry; +} + +MAC_TABLE_ENTRY *FindMeshEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN PUCHAR pAddr) +{ + MAC_TABLE_ENTRY *pEntry; + + /* lookup the match wds entry for the incoming packet. */ + pEntry = MeshTableLookupByWcid(pAd, Wcid, pAddr, TRUE); + + return pEntry; +} + +VOID MlmeHandleRxMeshFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + int i; + PHEADER_802_11 pHeader = pRxBlk->pHeader; +/* PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; */ + UCHAR Category; + UCHAR ActionField; + UCHAR MeshHdrLen; + + if (!MESH_ON(pAd)) + return; + + + +#ifdef WDS_SUPPORT + if (WdsTableLookup(pAd, pHeader->Addr2, FALSE) != NULL) + { + + return; + } +#endif /* WDS_SUPPORT */ + + + pRxBlk->pData = (UCHAR *)pHeader; + pRxBlk->pData += LENGTH_802_11; + pRxBlk->DataSize -= LENGTH_802_11; + + MeshHdrLen = GetMeshHederLen(pRxBlk->pData); + /* get Category */ + NdisMoveMemory(&Category, pRxBlk->pData + MeshHdrLen, 1); + /* get ActionField */ + NdisMoveMemory(&ActionField, pRxBlk->pData + MeshHdrLen + 1, 1); + + for (i = 0; i < MESH_ACT_HANDLER_TAB_SIZE; i++) + { + if ((Category == MeshActHandler[i].Category) + && (ActionField == MeshActHandler[i].ActionCode) + && (MeshActHandler[i].pHandle)) + { + (*(MeshActHandler[i].pHandle))(pAd, pRxBlk); + break; + } + } + +} + +LONG +PathRouteIDSearch( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr) +{ + MESH_ENTRY *pEntry = NULL; + UCHAR DestAddr[MAC_ADDR_LEN]; + + + if (*pAddr & 0x01) /* B/Mcast packet. */ + return BMCAST_ROUTE_ID; + + COPY_MAC_ADDR(DestAddr, pAddr); + pEntry = MeshEntryTableLookUp(pAd, DestAddr); + + if (pEntry) + { + if (pEntry->PathReqTimerRunning) + { + + return -1; + } + else + return (ULONG)pEntry->Idx; + } + + + return -1; +} + +PUCHAR +PathRouteAddrSearch( + IN PRTMP_ADAPTER pAd, + IN UCHAR RouteIdx) +{ + MESH_ROUTING_ENTRY *pEntry = NULL; + PMESH_ROUTING_TABLE pRouteTab = pAd->MeshTab.pMeshRouteTab; + + if (pRouteTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Route Table doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + if (RouteIdx >= MAX_ROUTE_TAB_SIZE) + return NULL; + + if (pRouteTab->Content[RouteIdx].Valid == TRUE) + { + pEntry = &pRouteTab->Content[RouteIdx]; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Can't find the Route Index = (%d)\n", (int)RouteIdx)); + return NULL; + } + + return pEntry->MeshDA; +} + +INT +PathMeshLinkIDSearch( + IN PRTMP_ADAPTER pAd, + IN UCHAR RouteIdx) +{ + MESH_ROUTING_ENTRY *pEntry = NULL; + PMESH_ROUTING_TABLE pRouteTab = pAd->MeshTab.pMeshRouteTab; + + if (pRouteTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Route Table doesn't exist.\n", __FUNCTION__)); + return -1; + } + + if (RouteIdx >= MAX_ROUTE_TAB_SIZE) + return -1; + + if (pRouteTab->Content[RouteIdx].Valid == TRUE) + { + pEntry = &pRouteTab->Content[RouteIdx]; + return pEntry->NextHopLinkID; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Can't find the Route Index = (%d)\n", (int)RouteIdx)); + } + + return -1; +} + +UINT GetMeshHederLen( + IN PUCHAR pSrcBufVA) +{ + UINT MeshHdrLen = 0; + + switch(GetMeshFlagAE(pSrcBufVA)) + { + case 0: + MeshHdrLen = 6; + break; + case 1: + MeshHdrLen = 12; + break; + case 2: + MeshHdrLen = 18; + break; + case 3: + MeshHdrLen = 24; + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s: Undown Mesh AE type=%x\n", __FUNCTION__, GetMeshFlagAE(pSrcBufVA))); + break; + } + + + return MeshHdrLen; +} + +UINT8 GetMeshFlag( + IN PUCHAR pSrcBufVA) +{ + PMESH_HEADER pMeshHead; + + pMeshHead = (PMESH_HEADER)(pSrcBufVA); + + return pMeshHead->MeshFlag; +} + +UINT8 GetMeshFlagAE( + IN PUCHAR pSrcBufVA) +{ + PMESH_HEADER pMeshHead; + + pMeshHead = (PMESH_HEADER)(pSrcBufVA); + + return (UINT8)((PMESH_FLAG)&pMeshHead->MeshFlag)->field.AE; +} + +UINT8 GetMeshTTL( + IN PUCHAR pSrcBufVA) +{ + PMESH_HEADER pMeshHead; + + pMeshHead = (PMESH_HEADER)(pSrcBufVA); + + return pMeshHead->MeshTTL; +} + +UINT32 GetMeshSeq( + IN PUCHAR pSrcBufVA) +{ + PMESH_HEADER pMeshHead; + UINT32 MeshSeq; + + pMeshHead = (PMESH_HEADER)(pSrcBufVA); + MeshSeq = le2cpu32(pMeshHead->MeshSeq); + + return MeshSeq; +} + +PUCHAR GetMeshAddr4( + IN PUCHAR pSrcBufVA) +{ + PMESH_HEADER pMeshHead; + + pMeshHead = (PMESH_HEADER)(pSrcBufVA); + if (((PMESH_FLAG)&pMeshHead->MeshFlag)->field.AE == 1 + || ((PMESH_FLAG)&pMeshHead->MeshFlag)->field.AE == 3) + return (PUCHAR)(pSrcBufVA + 6); + else + return NULL; +} + +PUCHAR GetMeshAddr5( + IN PUCHAR pSrcBufVA) +{ + PMESH_HEADER pMeshHead; + + pMeshHead = (PMESH_HEADER)(pSrcBufVA); + if (((PMESH_FLAG)&pMeshHead->MeshFlag)->field.AE == 2) + return (PUCHAR)(pSrcBufVA + 6); + else if (((PMESH_FLAG)&pMeshHead->MeshFlag)->field.AE == 3) + return (PUCHAR)(pSrcBufVA + 6 + MAC_ADDR_LEN); + else + return NULL; +} + +PUCHAR GetMeshAddr6( + IN PUCHAR pSrcBufVA) +{ + PMESH_HEADER pMeshHead; + + pMeshHead = (PMESH_HEADER)(pSrcBufVA); + if (((PMESH_FLAG)&pMeshHead->MeshFlag)->field.AE == 2) + return (PUCHAR)(pSrcBufVA + 6 + MAC_ADDR_LEN); + else if (((PMESH_FLAG)&pMeshHead->MeshFlag)->field.AE == 3) + return (PUCHAR)(pSrcBufVA + 6 + MAC_ADDR_LEN + MAC_ADDR_LEN); + else + return NULL; +} + +ULONG GetMeshLinkId( + IN PRTMP_ADAPTER pAd, + IN PCHAR PeerMacAddr) +{ + ULONG i; + + for (i = 0; i < MAX_MESH_LINKS; i++) + { + if (MAC_ADDR_EQUAL(PeerMacAddr, pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr)) + break; + } + + if (i == MAX_MESH_LINKS) + return BSS_NOT_FOUND; + + return (ULONG)i; +} + +VOID MeshDataPktProcess( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN USHORT MeshLinkIdx, + OUT PNDIS_PACKET *pMeshForwardPacket, + OUT BOOLEAN *pbDirectForward, + OUT BOOLEAN *pbAnnounce) + +{ + PUCHAR pHeader802_3 = GET_OS_PKT_DATAPTR(pPacket); + PUCHAR pMeshHdr = pHeader802_3 + LENGTH_802_3; + UINT MeshHdrLen = GetMeshHederLen(pMeshHdr); + UINT8 MeshTTL = GetMeshTTL(pMeshHdr); + UINT8 MeshFlagAE = GetMeshFlagAE(pMeshHdr); + INT PktLen; + + do + { + *pbAnnounce = FALSE; + *pbDirectForward = FALSE; + + if (!MESH_ON(pAd)) + break; + + if (*pHeader802_3 & 0x01) + { + if (--MeshTTL > 0) + *pbDirectForward = TRUE; + else + *pbDirectForward = FALSE; + *pbAnnounce = TRUE; + } + else + { + + if (MAC_ADDR_EQUAL(pHeader802_3, pAd->MeshTab.CurrentAddress)) + { + *pbAnnounce = TRUE; + *pbDirectForward = FALSE; + + if ((!(pAd->MeshTab.OpMode & MESH_AP) && !(pAd->MeshTab.OpMode & MESH_POTAL)) && + (MeshFlagAE == 2 && !MAC_ADDR_EQUAL(GetMeshAddr5(pMeshHdr),pAd->MeshTab.CurrentAddress))) + *pbAnnounce = FALSE; + } + else + { + if (--MeshTTL > 0) + *pbDirectForward = TRUE; + else + *pbDirectForward = FALSE; + *pbAnnounce = FALSE; + } + } + + if (pAd->MeshTab.MeshCapability.field.Forwarding == 0) + *pbDirectForward = FALSE; + + if (*pbDirectForward == TRUE) + { + PUCHAR pFwdPktHeader = NULL; + if (*pbAnnounce == TRUE) + { + *pMeshForwardPacket = (PNDIS_PACKET)OS_PKT_COPY(RTPKT_TO_OSPKT(pPacket)); + if (*pMeshForwardPacket == NULL) + { + /*ASSERT(*pMeshForwardPacket); */ + *pbAnnounce = FALSE; + *pbDirectForward = FALSE; + break; + } + pFwdPktHeader = GET_OS_PKT_DATAPTR(*pMeshForwardPacket); + } + else + pFwdPktHeader = pHeader802_3; + + + if (NdisEqualMemory(SNAP_802_1H, pFwdPktHeader + LENGTH_802_3 + MeshHdrLen, 6) || + NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pFwdPktHeader + LENGTH_802_3 + MeshHdrLen, 6)) + { + NdisMoveMemory(pFwdPktHeader + 12, pFwdPktHeader + LENGTH_802_3 + MeshHdrLen + 6, 2); + } + else + { + PktLen=GET_OS_PKT_LEN(pPacket)-LENGTH_802_3; + *(pFwdPktHeader+12)=(UCHAR)(PktLen / 256); + *(pFwdPktHeader+13)=(UCHAR)(PktLen % 256); + } + } + + if (*pbAnnounce == TRUE) + { + PUCHAR pSrcBuf,pData=pMeshHdr + MeshHdrLen; + UINT Offset; + BOOLEAN WithLLC=TRUE; + UCHAR Header802_3[14]; + + + if (NdisEqualMemory(SNAP_802_1H, pData, 6) || NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6)) + { + pSrcBuf = pMeshHdr + MeshHdrLen + 6 - LENGTH_802_3_NO_TYPE; + } + else + { + pSrcBuf = pMeshHdr + MeshHdrLen - LENGTH_802_3; + WithLLC=FALSE; + } + + + if (MeshFlagAE == 2) + { /* the lenght of hdr shall be 16 bytes here. */ + COPY_MAC_ADDR(Header802_3,GetMeshAddr5(pMeshHdr)); + COPY_MAC_ADDR(Header802_3+MAC_ADDR_LEN,GetMeshAddr6(pMeshHdr)); + } + else if(MeshFlagAE == 1) + { + /* Mesh Data frame never AE=1. */ + /* drop the frame. */ + DBGPRINT(RT_DEBUG_ERROR, ("%s: Receive Mesh-Data frame carry AE=1. Drop the frame.\n", __FUNCTION__)); + *pbAnnounce = FALSE; + *pbDirectForward = FALSE; + if (*pMeshForwardPacket != NULL) + RELEASE_NDIS_PACKET(pAd, *pMeshForwardPacket, NDIS_STATUS_FAILURE); + *pMeshForwardPacket = NULL; + break; + } + else + { + COPY_MAC_ADDR(Header802_3,pHeader802_3); + COPY_MAC_ADDR(Header802_3+MAC_ADDR_LEN,pHeader802_3 + MAC_ADDR_LEN); + } + + Offset = pSrcBuf - pHeader802_3; +/* GET_OS_PKT_DATAPTR(pPacket) = pSrcBuf; */ +/* GET_OS_PKT_LEN(pPacket) -= Offset; */ + SET_OS_PKT_DATAPTR(pPacket, pSrcBuf); + SET_OS_PKT_LEN(pPacket, (GET_OS_PKT_LEN(pPacket) - Offset)); + + if (WithLLC==FALSE) + { + PktLen=GET_OS_PKT_LEN(pPacket)-14; + Header802_3[12]=(UCHAR)(PktLen / 256); + Header802_3[13]=(UCHAR)(PktLen % 256); + memcpy(pSrcBuf,Header802_3,14); + } + else + { + memcpy(pSrcBuf,Header802_3,12); + } + + + } + } while (FALSE); + + return; +} + +ULONG InsertPktMeshHeader( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN PUCHAR *pHeaderBufPtr) +{ + ULONG TempLen = 0; + MESH_FLAG MeshFlag; + UINT16 MeshTTL; + UINT32 MeshSeq; + PUCHAR pMeshAddr5 = NULL; + PUCHAR pMeshAddr6 = NULL; + + PerpareMeshHeader(pAd, pTxBlk, &MeshFlag, &MeshTTL, &MeshSeq, &pMeshAddr5, &pMeshAddr6); + InsertMeshHeader(pAd, *pHeaderBufPtr, &TempLen, MeshFlag.word, MeshTTL, MeshSeq, + NULL, pMeshAddr5, pMeshAddr6); + + *pHeaderBufPtr += TempLen; + pTxBlk->MpduHeaderLen += TempLen; + + return TempLen; +} + +UINT32 RandomMeshCPI( + IN PRTMP_ADAPTER pAd) +{ + return (UINT32)((RandomByte(pAd) << 8) + (RandomByte(pAd))); +} + +UINT16 RandomLinkId( + IN PRTMP_ADAPTER pAd) +{ + return (UINT16)((RandomByte(pAd) << 8) + (RandomByte(pAd))); +} + +UINT8 RandomChSwWaitTime( + IN PRTMP_ADAPTER pAd) +{ + UINT8 ChSwCnt = RandomByte(pAd); + + ChSwCnt = (ChSwCnt >= 50) ? ChSwCnt : (UINT8)(50 + RandomByte(pAd)); + return ChSwCnt; +} + +void rtmp_read_mesh_from_file( + IN PRTMP_ADAPTER pAd, + PSTRING tmpbuf, + PSTRING buffer) +{ + /*UCHAR keyMaterial[40]; */ + ULONG KeyIdx; + ULONG KeyLen; + + /*MeshId */ + if(RTMPGetKeyParameter("MeshId", tmpbuf, 255, buffer, FALSE)) + { + /*MeshId acceptable strlen must be less than 32 and bigger than 0. */ + if((strlen(tmpbuf) < 0) || (strlen(tmpbuf) > 32)) + pAd->MeshTab.MeshIdLen = 0; + else + pAd->MeshTab.MeshIdLen = strlen(tmpbuf); + + if(pAd->MeshTab.MeshIdLen > 0) + { + NdisMoveMemory(&pAd->MeshTab.MeshId, tmpbuf, pAd->MeshTab.MeshIdLen); + } + else + { + NdisZeroMemory(&pAd->MeshTab.MeshId, MAX_MESH_ID_LEN); + } + DBGPRINT(RT_DEBUG_TRACE, ("MeshIdLen=%d, MeshId=%s\n", pAd->MeshTab.MeshIdLen, pAd->MeshTab.MeshId)); + } + + /*MeshAutoLink */ + if (RTMPGetKeyParameter("MeshAutoLink", tmpbuf, 255, buffer, TRUE)) + { + LONG Enable; + Enable = simple_strtol(tmpbuf, 0, 10); + pAd->MeshTab.MeshAutoLink = (Enable > 0) ? TRUE : FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("%s::(MeshAutoLink=%d)\n", __FUNCTION__, pAd->MeshTab.MeshAutoLink)); + } + else + pAd->MeshTab.MeshAutoLink = TRUE; + + /*MeshForward */ + if (RTMPGetKeyParameter("MeshForward", tmpbuf, 255, buffer, TRUE)) + { + LONG Enable; + Enable = simple_strtol(tmpbuf, 0, 10); + pAd->MeshTab.MeshCapability.field.Forwarding = (Enable > 0) ? (1) : (0); + DBGPRINT(RT_DEBUG_TRACE, ("%s::(MeshForward=%d)\n", __FUNCTION__, pAd->MeshTab.MeshCapability.field.Forwarding)); + } + + /*MeshAuthMode */ + if (RTMPGetKeyParameter("MeshAuthMode", tmpbuf, 255, buffer, TRUE)) + { + if ((strncmp(tmpbuf, "WPANONE", 7) == 0) || (strncmp(tmpbuf, "wpanone", 7) == 0)) + pAd->MeshTab.AuthMode = Ndis802_11AuthModeWPANone; + else + pAd->MeshTab.AuthMode = Ndis802_11AuthModeOpen; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(mesh0) MeshAuthMode(%d)=%s \n", pAd->MeshTab.AuthMode, GetAuthMode(pAd->MeshTab.AuthMode))); + RTMPMakeRSNIE(pAd, pAd->MeshTab.AuthMode, pAd->MeshTab.WepStatus, MIN_NET_DEVICE_FOR_MESH); + + if(pAd->MeshTab.AuthMode >= Ndis802_11AuthModeWPA) + { + if (pAd->MeshTab.AuthMode == Ndis802_11AuthModeWPANone) + pAd->MeshTab.DefaultKeyId = 0; + else + pAd->MeshTab.DefaultKeyId = 1; + } + + } + + /*MeshEncrypType */ + if (RTMPGetKeyParameter("MeshEncrypType", tmpbuf, 255, buffer, TRUE)) + { + if ((strncmp(tmpbuf, "WEP", 3) == 0) || (strncmp(tmpbuf, "wep", 3) == 0)) + { + if (pAd->MeshTab.AuthMode < Ndis802_11AuthModeWPA) + pAd->MeshTab.WepStatus = Ndis802_11WEPEnabled; + } + else if ((strncmp(tmpbuf, "TKIP", 4) == 0) || (strncmp(tmpbuf, "tkip", 4) == 0)) + { + if (pAd->MeshTab.AuthMode >= Ndis802_11AuthModeWPA) + pAd->MeshTab.WepStatus = Ndis802_11Encryption2Enabled; + } + else if ((strncmp(tmpbuf, "AES", 3) == 0) || (strncmp(tmpbuf, "aes", 3) == 0)) + { + if (pAd->MeshTab.AuthMode >= Ndis802_11AuthModeWPA) + pAd->MeshTab.WepStatus = Ndis802_11Encryption3Enabled; + } + else + { + pAd->MeshTab.WepStatus = Ndis802_11WEPDisabled; + } + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(mesh0) MeshEncrypType(%d)=%s \n", pAd->MeshTab.WepStatus, GetEncryptType(pAd->MeshTab.WepStatus))); + RTMPMakeRSNIE(pAd, pAd->MeshTab.AuthMode, pAd->MeshTab.WepStatus, MIN_NET_DEVICE_FOR_MESH); + + } + + /*MeshWPAKEY */ + if (RTMPGetKeyParameter("MeshWPAKEY", tmpbuf, 255, buffer, TRUE)) + { + /* The WPA KEY must be 8~64 characters */ + int success; + + success = RT_CfgSetWPAPSKKey(pAd, tmpbuf, pAd->MeshTab.MeshId, pAd->MeshTab.MeshIdLen, pAd->MeshTab.PMK); + if (success == TRUE) + { + NdisMoveMemory(pAd->MeshTab.WPAPassPhraseKey, tmpbuf, strlen(tmpbuf)); + pAd->MeshTab.WPAPassPhraseKeyLen = strlen(tmpbuf); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("I/F(mesh0) set MeshWPAKEY fail, key string required 8 ~ 64 characters!!!\n")); + } + + } + + /*MeshDefaultkey */ + if (RTMPGetKeyParameter("MeshDefaultkey", tmpbuf, 255, buffer, TRUE)) + { + KeyIdx = simple_strtol(tmpbuf, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + pAd->MeshTab.DefaultKeyId = (UCHAR) (KeyIdx - 1); + else + pAd->MeshTab.DefaultKeyId = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(mesh0) DefaultKeyID(0~3)=%d\n", pAd->MeshTab.DefaultKeyId)); + } + + /*MeshWEPKEY */ + if (RTMPGetKeyParameter("MeshWEPKEY", tmpbuf, 255, buffer, TRUE)) + { + KeyLen = strlen(tmpbuf); + + /* Hex type */ + if((KeyLen == 10) || (KeyLen == 26)) + { + pAd->MeshTab.SharedKey.KeyLen = KeyLen / 2; + AtoH(tmpbuf, pAd->MeshTab.SharedKey.Key, KeyLen / 2); + if (KeyLen == 10) + pAd->MeshTab.SharedKey.CipherAlg = CIPHER_WEP64; + else + pAd->MeshTab.SharedKey.CipherAlg = CIPHER_WEP128; + + NdisMoveMemory(pAd->MeshTab.DesiredWepKey, tmpbuf, KeyLen); + pAd->MeshTab.DesiredWepKeyLen = KeyLen; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(mesh0) MeshWEPKEY=%s, it's HEX type and %s\n", tmpbuf, (KeyLen == 10) ? "wep64":"wep128")); + } + /* ASCII type */ + else if ((KeyLen == 5) || (KeyLen == 13)) + { + pAd->MeshTab.SharedKey.KeyLen = KeyLen; + NdisMoveMemory(pAd->MeshTab.SharedKey.Key, tmpbuf, KeyLen); + if (KeyLen == 5) + pAd->MeshTab.SharedKey.CipherAlg = CIPHER_WEP64; + else + pAd->MeshTab.SharedKey.CipherAlg = CIPHER_WEP128; + + NdisMoveMemory(pAd->MeshTab.DesiredWepKey, tmpbuf, KeyLen); + pAd->MeshTab.DesiredWepKeyLen = KeyLen; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(mesh0) MeshWEPKEY=%s, it's ASCII type and %s\n", tmpbuf, (KeyLen == 5) ? "wep64":"wep128")); + } + /*Invalid key length */ + else + { + pAd->MeshTab.DesiredWepKeyLen = 0; + DBGPRINT(RT_DEBUG_ERROR, ("I/F(mesh0) MeshWEPKEY is Invalid key length(%d)!\n", (UCHAR)KeyLen)); + } + } + + return; +} + + +VOID LocalMsaIeInit( + IN PRTMP_ADAPTER pAd, + IN INT idx) +{ + PMSA_HANDSHAKE_IE pLocalMsaIe; + + /* clear the local MP's MSAIE field */ + NdisZeroMemory(pAd->MeshTab.MeshLink[idx].Entry.LocalMsaIe, MESH_MAX_MSAIE_LEN); + pAd->MeshTab.MeshLink[idx].Entry.LocalMsaIeLen = 0; + + pLocalMsaIe = (PMSA_HANDSHAKE_IE)pAd->MeshTab.MeshLink[idx].Entry.LocalMsaIe; + + + pLocalMsaIe->MeshHSControl.word = 0; + if (pAd->MeshTab.bInitialMsaDone == FALSE || pAd->MeshTab.PMKID_Len == 0) + pLocalMsaIe->MeshHSControl.field.RequestAuth = 1; + + if (pAd->MeshTab.MeshLink[idx].Entry.bValidLocalMpAsSelector) + { + UCHAR AuthMode = pAd->MeshTab.AuthMode; + UCHAR EncrypType = pAd->MeshTab.WepStatus; + + switch (AuthMode) + { + case Ndis802_11AuthModeWPA2: + NdisMoveMemory(pLocalMsaIe->SelectedAKM, OUI_MSA_8021X_AKM, LEN_OUI_SUITE); + break; + + case Ndis802_11AuthModeWPA2PSK: + NdisMoveMemory(pLocalMsaIe->SelectedAKM, OUI_MSA_PSK_AKM, LEN_OUI_SUITE); + break; + + /*default: */ + case Ndis802_11AuthModeWPANone: + NdisMoveMemory(pLocalMsaIe->SelectedAKM, OUI_WPA_NONE_AKM, LEN_OUI_SUITE); + break; + } + + switch (EncrypType) + { + case Ndis802_11Encryption2Enabled: + if (pAd->MeshTab.AuthMode == Ndis802_11AuthModeWPANone) + NdisMoveMemory(pLocalMsaIe->SelectedPairwiseCipher, OUI_WPA_TKIP, LEN_OUI_SUITE); + else + NdisMoveMemory(pLocalMsaIe->SelectedPairwiseCipher, OUI_WPA2_TKIP, LEN_OUI_SUITE); + break; + + case Ndis802_11Encryption3Enabled: + if (pAd->MeshTab.AuthMode == Ndis802_11AuthModeWPANone) + NdisMoveMemory(pLocalMsaIe->SelectedPairwiseCipher, OUI_WPA_CCMP, LEN_OUI_SUITE); + else + NdisMoveMemory(pLocalMsaIe->SelectedPairwiseCipher, OUI_WPA2_CCMP, LEN_OUI_SUITE); + break; + } + } + + pAd->MeshTab.MeshLink[idx].Entry.LocalMsaIeLen = sizeof(MSA_HANDSHAKE_IE); + +} + +/* + ========================================================================== + Description: + It shall be queried about mesh security information through IOCTL + Arguments: + pAd Pointer to our adapter + wrq Pointer to the ioctl argument + ========================================================================== +*/ +VOID RTMPIoctlQueryMeshSecurityInfo( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + UCHAR key_len = 0; + MESH_SECURITY_INFO meshInfo; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlQueryMeshSecurityInfo==>\n")); + + NdisZeroMemory((PUCHAR)&meshInfo, sizeof(MESH_SECURITY_INFO)); + + if (pAd->MeshTab.AuthMode == Ndis802_11AuthModeOpen && pAd->MeshTab.WepStatus == Ndis802_11Encryption1Enabled) + meshInfo.EncrypType = ENCRYPT_OPEN_WEP; /* 1 - OPEN-WEP */ + else if (pAd->MeshTab.AuthMode == Ndis802_11AuthModeWPANone && pAd->MeshTab.WepStatus == Ndis802_11Encryption2Enabled) + meshInfo.EncrypType = ENCRYPT_WPANONE_TKIP; /* 2 - WPANONE-TKIP */ + else if (pAd->MeshTab.AuthMode == Ndis802_11AuthModeWPANone && pAd->MeshTab.WepStatus == Ndis802_11Encryption3Enabled) + meshInfo.EncrypType = ENCRYPT_WPANONE_AES; /* 3 - WPANONE-AES */ + else + meshInfo.EncrypType = ENCRYPT_OPEN_NONE; /* 0 - OPEN-NONE */ + + meshInfo.KeyIndex = pAd->MeshTab.DefaultKeyId + 1; + + if (meshInfo.EncrypType == ENCRYPT_OPEN_WEP) + { + key_len = pAd->MeshTab.DesiredWepKeyLen; + if (key_len > 0) + { + meshInfo.KeyLength = key_len; + NdisMoveMemory(meshInfo.KeyMaterial, pAd->MeshTab.DesiredWepKey, key_len); + } + } + else if (meshInfo.EncrypType == ENCRYPT_WPANONE_TKIP || meshInfo.EncrypType == ENCRYPT_WPANONE_AES) + { + key_len = pAd->MeshTab.WPAPassPhraseKeyLen; + if (key_len > 0) + { + meshInfo.KeyLength = key_len; + NdisMoveMemory(meshInfo.KeyMaterial, pAd->MeshTab.WPAPassPhraseKey, key_len); + } + } + + wrq->u.data.length = sizeof(MESH_SECURITY_INFO); + if (copy_to_user(wrq->u.data.pointer, &meshInfo, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + +} + + +/* + ========================================================================== + Description: + It shall be set mesh security through IOCTL + Arguments: + pAd Pointer to our adapter + wrq Pointer to the ioctl argument + ========================================================================== +*/ +INT RTMPIoctlSetMeshSecurityInfo( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + INT Status = NDIS_STATUS_SUCCESS; + MESH_SECURITY_INFO meshInfo; + UCHAR MeshKey[255]; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlSetMeshSecurityInfo==>\n")); + + if (wrq->u.data.length != sizeof(MESH_SECURITY_INFO)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: the length is too large \n", __FUNCTION__)); + return -EINVAL; + } + + if (copy_from_user(&meshInfo, wrq->u.data.pointer, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: copy_from_user() fail\n", __FUNCTION__)); + return -EFAULT; + } + + /* Default security mode is OPEN-NONE */ + pAd->MeshTab.AuthMode = Ndis802_11AuthModeOpen; + pAd->MeshTab.WepStatus = Ndis802_11EncryptionDisabled; + NdisZeroMemory((PUCHAR)&pAd->MeshTab.SharedKey, sizeof(CIPHER_KEY)); + + /* Set default key index */ + if((meshInfo.KeyIndex >= 1) && (meshInfo.KeyIndex <= 4)) + pAd->MeshTab.DefaultKeyId = meshInfo.KeyIndex - 1; + else + pAd->MeshTab.DefaultKeyId = 0; + + NdisZeroMemory(MeshKey, 255); + if (meshInfo.KeyLength > 0) + NdisMoveMemory(MeshKey, meshInfo.KeyMaterial, meshInfo.KeyLength); + MeshKey[sizeof(MeshKey)-1] = 0x00; + + /* OPEN-WEP */ + if (meshInfo.EncrypType == ENCRYPT_OPEN_WEP) + { + if (!Set_MeshWEPKEY_Proc(pAd, (PSTRING) MeshKey)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh WEP key isn't valid \n", __FUNCTION__)); + return -EFAULT; + } + + pAd->MeshTab.AuthMode = Ndis802_11AuthModeOpen; + pAd->MeshTab.WepStatus = Ndis802_11Encryption1Enabled; + } + else if (meshInfo.EncrypType == ENCRYPT_WPANONE_TKIP || meshInfo.EncrypType == ENCRYPT_WPANONE_AES) + { + if (!Set_MeshWPAKEY_Proc(pAd, (PSTRING) MeshKey)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh WPA key isn't valid \n", __FUNCTION__)); + return -EFAULT; + } + + pAd->MeshTab.AuthMode = Ndis802_11AuthModeWPANone; + if (meshInfo.EncrypType == ENCRYPT_WPANONE_TKIP) + pAd->MeshTab.WepStatus = Ndis802_11Encryption2Enabled; + else + pAd->MeshTab.WepStatus = Ndis802_11Encryption3Enabled; + + RTMPMakeRSNIE(pAd, pAd->MeshTab.AuthMode, pAd->MeshTab.WepStatus, MIN_NET_DEVICE_FOR_MESH); + } + + return Status; + +} + +UCHAR GetMeshSecurity( + IN PRTMP_ADAPTER pAd) +{ + + UCHAR EncrypType = ENCRYPT_OPEN_NONE; + + if (pAd->MeshTab.AuthMode==Ndis802_11AuthModeOpen + && pAd->MeshTab.WepStatus == Ndis802_11WEPDisabled) + { + + } + else if (pAd->MeshTab.AuthMode==Ndis802_11AuthModeOpen + && pAd->MeshTab.WepStatus == Ndis802_11WEPEnabled) + { + + EncrypType = ENCRYPT_OPEN_WEP; + } + else if (pAd->MeshTab.AuthMode==Ndis802_11AuthModeWPANone + && pAd->MeshTab.WepStatus == Ndis802_11Encryption2Enabled) + { + EncrypType = ENCRYPT_WPANONE_TKIP; + } + else if (pAd->MeshTab.AuthMode==Ndis802_11AuthModeWPANone + && pAd->MeshTab.WepStatus == Ndis802_11Encryption3Enabled) + { + EncrypType = ENCRYPT_WPANONE_AES; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Can not find correct mesh security ,return OPEN_NONE Auth:%d WepStatus:%d \n", __FUNCTION__ + ,pAd->MeshTab.AuthMode,pAd->MeshTab.WepStatus)); + } + + + return EncrypType; +} + +UCHAR MeshCheckPeerMpCipher( + IN USHORT CapabilityInfo, + IN PUCHAR pVIE, + IN USHORT LenVIE) +{ + UCHAR EncrypType = ENCRYPT_OPEN_NONE; + + if (CAP_IS_PRIVACY_ON(CapabilityInfo)) + { + PUCHAR pVarIEs; + USHORT VarIELen; + PEID_STRUCT pEid; + + EncrypType = ENCRYPT_OPEN_WEP; + + pVarIEs = pVIE; + VarIELen = LenVIE; + + while (VarIELen > 0) + { + pEid = (PEID_STRUCT) pVarIEs; + + if ((pEid->Eid == IE_WPA) && (VarIELen > (sizeof(RSNIE) + 2)) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))) + { + RSNIE *pRsnie; + + pRsnie = (RSNIE*)pEid->Octet; + + if(RTMPEqualMemory(OUI_WPA_TKIP, pRsnie->ucast[0].oui, 4)) + EncrypType = ENCRYPT_WPANONE_TKIP; + else if (RTMPEqualMemory(OUI_WPA_CCMP, pRsnie->ucast[0].oui, 4)) + EncrypType = ENCRYPT_WPANONE_AES; + + break; + } + /* For WPA2/WPA2PSK */ + + pVarIEs += (pEid->Len + 2); + VarIELen -= (pEid->Len + 2); + } + + } + + return EncrypType; +} + +BOOLEAN MeshAllowToSendPacket( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + OUT UCHAR *pWcid) +{ + BOOLEAN allowed = FALSE; + PMESH_PROXY_ENTRY pMeshProxyEntry = NULL; + PUCHAR pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket); + + if (MESH_ON(pAd)) + { + LONG RouteId = PathRouteIDSearch(pAd, pSrcBufVA); + + if (!MAC_ADDR_EQUAL(pAd->MeshTab.CurrentAddress, pSrcBufVA + MAC_ADDR_LEN)) + { + if ((pAd->MeshTab.OpMode & MESH_AP) || (pAd->MeshTab.OpMode & MESH_POTAL)) + { + pMeshProxyEntry = MeshProxyEntryTableLookUp(pAd, pSrcBufVA + MAC_ADDR_LEN); + + if (!pMeshProxyEntry) + { + pMeshProxyEntry = MeshProxyEntryTableInsert(pAd, pAd->MeshTab.CurrentAddress, pSrcBufVA + MAC_ADDR_LEN); + } + } + else + { + return FALSE; + } + } + + if (RouteId == BMCAST_ROUTE_ID) + { + MeshClonePacket(pAd, pPacket, MESH_PROXY, 0); + } + else if (RouteId >= 0) + { + INT LinkId; + + LinkId = PathMeshLinkIDSearch(pAd, RouteId); + if ((LinkId >= 0) && VALID_MESH_LINK_ID(LinkId)) + { + *pWcid = pAd->MeshTab.MeshLink[LinkId].Entry.MacTabMatchWCID; + RTMP_SET_MESH_ROUTE_ID(pPacket, (UINT8)RouteId); + + /* MESH_PROXY indicate the packet come from os layer to mesh0 virtual interface. */ + RTMP_SET_MESH_SOURCE(pPacket, MESH_PROXY); + allowed = TRUE; + } + } + else + { + /* entity is not exist. */ + /* start path discovery. */ + if (MAC_ADDR_EQUAL(pSrcBufVA + MAC_ADDR_LEN, pAd->MeshTab.CurrentAddress)) + MeshCreatePreqAction(pAd, NULL, pSrcBufVA); + else + MeshCreatePreqAction(pAd, pSrcBufVA + MAC_ADDR_LEN, pSrcBufVA); + } + } + + return allowed; +} + +VOID PerpareMeshHeader( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + OUT PMESH_FLAG pMeshFlag, + OUT UINT16 *pMeshTTL, + OUT UINT32 *pMeshSeq, + OUT PUCHAR *ppMeshAddr5, + OUT PUCHAR *ppMeshAddr6) +{ + UINT MeshHdrLen = 0; + PNDIS_PACKET pPacket = pTxBlk->pPacket; + PUCHAR pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket); + UINT8 TXWISize = pAd->chipCap.TXWISize; + PHEADER_802_11 pHeader_802_11 = (PHEADER_802_11)&pTxBlk->HeaderBuf[TXINFO_SIZE + pAd->chipCap.TXWISize]; + + if (RTMP_GET_MESH_SOURCE(pPacket) == MESH_PROXY) + { + pMeshFlag->word = 0; + *pMeshTTL = pAd->MeshTab.TTL; + *pMeshSeq = INC_MESH_SEQ(pAd->MeshTab.MeshSeq); + if (( (*pSrcBufVA & 0x01) /* B/Mcast packet. */ + || MAC_ADDR_EQUAL(pSrcBufVA, pHeader_802_11->Addr3)) /* or DA is a MP. */ + && MAC_ADDR_EQUAL(pSrcBufVA + MAC_ADDR_LEN, pAd->MeshTab.CurrentAddress)) + { + pMeshFlag->field.AE = 0; + *ppMeshAddr5 = NULL; + *ppMeshAddr6 = NULL; + } + else + { + pMeshFlag->field.AE = 2; + *ppMeshAddr5 = pSrcBufVA; + *ppMeshAddr6 = pSrcBufVA + MAC_ADDR_LEN; + } + } + else + { + pSrcBufVA += LENGTH_802_3; + MeshHdrLen = GetMeshHederLen(pSrcBufVA); + pMeshFlag->word = GetMeshFlag(pSrcBufVA); + *pMeshTTL = GetMeshTTL(pSrcBufVA) - 1; + *pMeshSeq = GetMeshSeq(pSrcBufVA); + *ppMeshAddr5 = GetMeshAddr5(pSrcBufVA); + *ppMeshAddr6 = GetMeshAddr6(pSrcBufVA); + + if (NdisEqualMemory(SNAP_802_1H, pTxBlk->pSrcBufData + MeshHdrLen, 6) || NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pTxBlk->pSrcBufData + MeshHdrLen, 6)) + { + /* skip Mesh header and LLC Header (8 Bytes). */ + pTxBlk->pSrcBufData = pTxBlk->pSrcBufData + MeshHdrLen + 8; + pTxBlk->SrcBufLen -= (MeshHdrLen + 8); + } + else + { + pTxBlk->pSrcBufData = pTxBlk->pSrcBufData + MeshHdrLen; + pTxBlk->SrcBufLen -= (MeshHdrLen); + } + } + + return; +} + +BOOLEAN MeshChCheck( + IN RTMP_ADAPTER *pAd, + IN PMESH_NEIGHBOR_ENTRY pNeighborEntry) +{ + BOOLEAN result = FALSE; + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + && (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + && (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == BW_40) + && (pNeighborEntry->ChBW == BW_40) + ) + { + result = ((pNeighborEntry->Channel == pAd->CommonCfg.Channel) + && (pNeighborEntry->ChBW == pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth) + && (pNeighborEntry->ExtChOffset == pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset)) ? TRUE : FALSE; + } + else +#endif /* DOT11_N_SUPPORT */ + { + result = (pNeighborEntry->Channel == pAd->CommonCfg.Channel) ? TRUE : FALSE; + } + + + return result; +} + +/* + ========================================================================== + Description: + Pre-build a BEACON frame in the shared memory + ========================================================================== +*/ +VOID MeshMakeBeacon( + IN PRTMP_ADAPTER pAd, + IN UCHAR idx) +{ + UCHAR DsLen = 1, SsidLen; + UCHAR RSNIe=IE_WPA; + HEADER_802_11 BcnHdr; + LARGE_INTEGER FakeTimestamp; + ULONG FrameLen = 0; + PTXWI_STRUC pTxWI = &pAd->BeaconTxWI; + PUCHAR pBeaconFrame = (PUCHAR)pAd->MeshTab.BeaconBuf; + UCHAR *ptr; + UINT i; + UINT32 longValue; + UCHAR ASupRate[] = {0x8C, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6C}; + UCHAR ASupRateLen = sizeof(ASupRate)/sizeof(UCHAR); + ULONG TmpLen; + HTTRANSMIT_SETTING BeaconTransmit; /* MGMT frame PHY rate setting when operatin at Ht rate. */ + UINT8 TXWISize = pAd->chipCap.TXWISize; + + /* ignore SSID for MP. Refer to IEEE 802.11s-D1.06 */ + SsidLen = 0; + + if (pAd->MeshTab.bBcnSntReq == FALSE) + return; + + + DBGPRINT(RT_DEBUG_TRACE, ("MeshMakeBeacon - %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pAd->MeshTab.CurrentAddress))); + MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, +#ifdef P2P_SUPPORT + pAd->MeshTab.CurrentAddress, +#endif /* P2P_SUPPORT */ + pAd->MeshTab.CurrentAddress); + + if (pAd->MeshTab.AuthMode == Ndis802_11AuthModeWPANone) + RSNIe = IE_WPA; + else if ((pAd->MeshTab.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->MeshTab.AuthMode == Ndis802_11AuthModeWPA2PSK)) + RSNIe = IE_WPA2; + + /* for update framelen to TxWI later. */ + MakeOutgoingFrame(pBeaconFrame, &FrameLen, + sizeof(HEADER_802_11), &BcnHdr, + TIMESTAMP_LEN, &FakeTimestamp, + 2, &pAd->CommonCfg.BeaconPeriod, + 2, &pAd->MeshTab.CapabilityInfo, + 1, &SsidIe, + 1, &SsidLen, + END_OF_ARGS); + + if (pAd->CommonCfg.Channel <= 14) + { + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &SupRateIe, + 1, &pAd->CommonCfg.SupRateLen, + pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRate, + END_OF_ARGS); + FrameLen += TmpLen; + } + else + { + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &SupRateIe, + 1, &ASupRateLen, + pAd->CommonCfg.SupRateLen, ASupRate, + END_OF_ARGS); + FrameLen += TmpLen; + } + + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &DsIe, + 1, &DsLen, + 1, &pAd->MeshTab.MeshChannel, + END_OF_ARGS); + FrameLen += TmpLen; + + if ((pAd->CommonCfg.Channel <= 14) + && (pAd->CommonCfg.ExtRateLen)) + { + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &ExtRateIe, + 1, &pAd->CommonCfg.ExtRateLen, + pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, + END_OF_ARGS); + FrameLen += TmpLen; + } + + /* Append RSN_IE when WPA OR WPAPSK, */ + if (pAd->MeshTab.AuthMode >= Ndis802_11AuthModeWPA) + { + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &RSNIe, + 1, &pAd->MeshTab.RSNIE_Len, + pAd->MeshTab.RSNIE_Len, pAd->MeshTab.RSN_IE, + END_OF_ARGS); + FrameLen += TmpLen; + } + +#ifdef DOT11_N_SUPPORT + /* AP Channel Report */ + if (pAd->CommonCfg.PhyMode == PHY_11BGN_MIXED + && ((pAd->CommonCfg.HT_DisallowTKIP == FALSE) + || (pAd->CommonCfg.HT_DisallowTKIP + && !IS_INVALID_HT_SECURITY(pAd->MeshTab.WepStatus))) + ) /*wayne_note */ + { + UCHAR APChannelReportIe = IE_AP_CHANNEL_REPORT; + ULONG TmpLen; + + /* 802.11n D2.0 Annex J */ + /* USA */ + /* regulatory class 32, channel set 1~7 */ + /* regulatory 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); */ + + + MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, + 1, &APChannelReportIe, + 1, &rclasslen, + rclasslen, rclass32, + 1, &APChannelReportIe, + 1, &rclasslen, + rclasslen, rclass33, + END_OF_ARGS); + FrameLen += TmpLen; + } +#endif /* DOT11_N_SUPPORT */ + + BeaconTransmit.word = 0; + RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, BSS0Mcast_WCID, + FrameLen, PID_MGMT, 0, 0,IFS_HTTXOP, FALSE, &BeaconTransmit); + /* */ + /* step 6. move BEACON TXD and frame content to on-chip memory */ + /* */ + ptr = (PUCHAR)&pAd->BeaconTxWI; +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, ptr, TYPE_TXWI); +#endif + + + for (i=0; iBeaconOffset[idx] + i, longValue, 4); + ptr +=4; + } + + + /* update BEACON frame content. start right after the 24-byte TXINFO field */ + ptr = (PUCHAR)pAd->MeshTab.BeaconBuf; +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); +#endif + + + for (i= 0; i< FrameLen; i+=4) + { + longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); + RTMP_CHIP_UPDATE_BEACON(pAd, pAd->BeaconOffset[idx] + TXWISize + i, longValue, 4); + ptr += 4; + } + + + pAd->MeshTab.TimIELocationInBeacon = (UCHAR)FrameLen; + pAd->MeshTab.CapabilityInfoLocationInBeacon = sizeof(HEADER_802_11) + TIMESTAMP_LEN + 2; + + +#ifdef CONFIG_STA_SUPPORT + RTMP_IO_READ32(pAd, MAC_BSSID_DW1, &longValue); + longValue &= 0x0000FFFF; + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, longValue); +#endif /* CONFIG_STA_SUPPORT */ + +} + +/* + ========================================================================== + 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 MeshUpdateBeaconFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR idx) +{ + /*PTXWI_STRUC pTxWI = &pAd->BeaconTxWI; */ + PUCHAR pBeaconFrame = (PUCHAR)pAd->MeshTab.BeaconBuf; + UCHAR *ptr; + ULONG FrameLen = pAd->MeshTab.TimIELocationInBeacon; + ULONG UpdatePos = pAd->MeshTab.TimIELocationInBeacon; + /*UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; */ + /*UCHAR ID_1B, TimFirst, TimLast, *pTim; */ + HTTRANSMIT_SETTING BeaconTransmit; /* MGMT frame PHY rate setting when operatin at Ht rate. */ + + if (pAd->MeshTab.bBcnSntReq == FALSE) + return; + + /* The beacon of mesh isn't be initialized */ + if (FrameLen == 0) + return; + + /* */ + /* step 1 - update BEACON's Capability */ + /* */ + ptr = pBeaconFrame + pAd->MeshTab.CapabilityInfoLocationInBeacon; + *ptr = (UCHAR)(pAd->MeshTab.CapabilityInfo & 0x00ff); + *(ptr+1) = (UCHAR)((pAd->MeshTab.CapabilityInfo & 0xff00) >> 8); + +#ifdef DOT11_N_SUPPORT + /* */ + /* step 5. Update HT. Since some fields might change in the same BSS. */ + /* */ + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + && ((pAd->CommonCfg.HT_DisallowTKIP == FALSE) + || (pAd->CommonCfg.HT_DisallowTKIP + && !IS_INVALID_HT_SECURITY(pAd->MeshTab.WepStatus))) + ) /*wayne_note */ + { + ULONG TmpLen; + UCHAR HtLen, HtLen1; + /*UCHAR i; */ + +#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 */ + + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + && ((pAd->CommonCfg.HT_DisallowTKIP == FALSE) + || (pAd->CommonCfg.HT_DisallowTKIP + && !IS_INVALID_HT_SECURITY(pAd->MeshTab.WepStatus))) + )/*wayne_note */ + { + ULONG TmpLen; + UCHAR HtLen, HtLen1; + /*UCHAR i; */ +#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); + + 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, &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(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, &pAd->CommonCfg.AddHTInfo, + END_OF_ARGS); +#else + 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, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_AHTINFO[0], + HtLen1, &addHTInfoTmp, + END_OF_ARGS); +#endif + FrameLen += TmpLen; + } + + } + + /* P802.11n_D1.10 */ + /* 7.3.2.27 Extended Capabilities IE */ + /* HT Information Exchange Support */ + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + && ((pAd->CommonCfg.HT_DisallowTKIP == FALSE) + || (pAd->CommonCfg.HT_DisallowTKIP + && !IS_INVALID_HT_SECURITY(pAd->MeshTab.WepStatus))) + ) /*wayne_note */ + { + ULONG TmpLen; + UCHAR ExtCapIe[3] = {IE_EXT_CAPABILITY, 1, 0x01}; + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 3, ExtCapIe, + END_OF_ARGS); + FrameLen += TmpLen; + + } +#endif /* DOT11_N_SUPPORT */ + + /* add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back */ + if ((pAd->CommonCfg.HT_DisallowTKIP == FALSE) || (pAd->CommonCfg.HT_DisallowTKIP && !IS_INVALID_HT_SECURITY(pAd->MeshTab.WepStatus))) + {/*wayne_note */ + 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 */ + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 9, RalinkSpecificIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + + /* Insert MeshIDIE and MeshConfigurationIE in Beacon frame */ + /*if (MeshValid(&pAd->MeshTab)) */ + { + pAd->MeshTab.MeshCapability.field.AcceptPeerLinks = MeshAcceptPeerLink(pAd); + InsertMeshIdIE(pAd, pBeaconFrame+FrameLen, &FrameLen); + InsertMeshConfigurationIE(pAd, pBeaconFrame+FrameLen, &FrameLen, FALSE); + InsertMeshHostNameIE(pAd, pBeaconFrame+FrameLen, &FrameLen); + } + + /* Insert MSCIE */ + InsertMSCIE(pAd, pBeaconFrame+FrameLen, &FrameLen); + + /* */ + /* step 6. Since FrameLen may change, update TXWI. */ + /* */ + /* Update in real buffer */ + /* Update sw copy. */ + if (pAd->CommonCfg.Channel <= 14) + BeaconTransmit.word = 0; + else + BeaconTransmit.word = 0x4000; + + RTMPWriteTxWI(pAd, &pAd->BeaconTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, 0xff, + FrameLen, PID_MGMT, QID_MGMT, 0, IFS_HTTXOP, FALSE, &BeaconTransmit); + /* */ + /* step 7. move BEACON TXWI and frame content to on-chip memory */ + /* */ + RT28xx_UpdateBeaconToAsic(pAd, idx + MIN_NET_DEVICE_FOR_MESH, FrameLen, UpdatePos); +} + +VOID MeshCleanBeaconFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR idx) +{ + INT i; + UINT8 TXWISize = pAd->chipCap.TXWISize; + + + /* 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[idx] + i, 0, 4); + + + +} + +/* + ========================================================================== + 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. + + ========================================================================== + */ +VOID AsicEnableMESHSync( + IN PRTMP_ADAPTER pAd) +{ + BCN_TIME_CFG_STRUC csr; + + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); + + + /* start sending BEACON */ + 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 in IBSS mode */ + csr.field.bTBTTEnable = 1; + csr.field.bBeaconGen = 1; + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); +} + +#ifdef CONFIG_STA_SUPPORT +BOOLEAN MeshWirelessForward( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN ULONG FromWhichBSSID) +{ + BOOLEAN bAnnounce, bDirectForward; + UCHAR *pHeader802_3; + PNDIS_PACKET pForwardPacket = NULL; + PNDIS_PACKET pMeshForwardPacket = NULL; + + if (FromWhichBSSID < MIN_NET_DEVICE_FOR_MESH) + return TRUE; + + pHeader802_3 = GET_OS_PKT_DATAPTR(pPacket); + + MeshDataPktProcess(pAd, pPacket, (FromWhichBSSID - MIN_NET_DEVICE_FOR_MESH), + &pMeshForwardPacket, &bDirectForward, &bAnnounce); + + if (bDirectForward) + { + LONG RouteId; + + /* build an NDIS packet */ + if ((bDirectForward == TRUE) && (bAnnounce == TRUE)) + pForwardPacket = pMeshForwardPacket; + else + pForwardPacket = DuplicatePacket(get_netdev_from_bssid(pAd, FromWhichBSSID), + pPacket, FromWhichBSSID); + + if (pForwardPacket == NULL) + return bAnnounce; + + RouteId = PathRouteIDSearch(pAd, pHeader802_3); + if (RouteId == BMCAST_ROUTE_ID) + { + MeshClonePacket(pAd, pForwardPacket, MESH_FORWARD, (FromWhichBSSID - MIN_NET_DEVICE_FOR_MESH)); + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pForwardPacket, NDIS_STATUS_SUCCESS); + } + else if (RouteId >= 0) + { + INT LinkId; + + LinkId = PathMeshLinkIDSearch(pAd, RouteId); + if ((LinkId >= 0) && VALID_MESH_LINK_ID(LinkId)) + { + RTMP_SET_PACKET_NET_DEVICE_MESH(pForwardPacket, 0); + RTMP_SET_PACKET_SOURCE(pForwardPacket, PKTSRC_NDIS); + RTMP_SET_PACKET_MOREDATA(pForwardPacket, FALSE); + RTMP_SET_PACKET_WCID(pForwardPacket, + pAd->MeshTab.MeshLink[LinkId].Entry.MacTabMatchWCID); + RTMP_SET_MESH_ROUTE_ID(pForwardPacket, RouteId); + RTMP_SET_MESH_SOURCE(pForwardPacket, MESH_FORWARD); + STASendPacket(pAd, pForwardPacket); + } + else + { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pForwardPacket, NDIS_STATUS_FAILURE); + } + } + else + { + /* entity is not exist. */ + /* start path discovery. */ + MeshCreatePreqAction(pAd, NULL, pHeader802_3); + + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pForwardPacket, NDIS_STATUS_FAILURE); + } + + /* Dequeue outgoing frames from TxSwQueue[] and process it */ + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } + + return bAnnounce; +} +#endif /* CONFIG_STA_SUPPORT */ + +UINT32 MeshAirLinkTime( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pMacEntry, + IN HTTRANSMIT_SETTING HTTxMode) +{ + +typedef struct __TX_RATE +{ + UINT8 PhyMode; + UINT8 MCS; + UINT8 RateIdx; + ULONG DataRate; +} _TX_RATE; + +_TX_RATE TxRate[] = +{ + {MODE_CCK, 0, 0, 10}, /* 1 Mbps */ + {MODE_CCK, 1, 1, 20}, /* 2 Mbps */ + {MODE_CCK, 2, 2, 55}, /* 5.5 Mbps */ + {MODE_CCK, 3, 3, 110}, /* 11 Mbps */ + + {MODE_OFDM, 0, 4, 60}, /* 6 Mbps */ + {MODE_OFDM, 1, 5, 90}, /* 9 Mbps */ + {MODE_OFDM, 2, 6, 120}, /* 12 Mbps */ + {MODE_OFDM, 3, 7, 180}, /* 18 Mbps */ + {MODE_OFDM, 4, 8, 240}, /* 24 Mbps */ + {MODE_OFDM, 5, 9, 360}, /* 36 Mbps */ + {MODE_OFDM, 6, 10, 480}, /* 48 Mbps */ + {MODE_OFDM, 7, 11, 540}, /* 54 Mbps */ + +#ifdef DOT11_N_SUPPORT + {MODE_HTMIX, 0, 12, 65}, /* 6.5 Mbps */ + {MODE_HTMIX, 1, 13, 130}, /* 13 Mbps */ + {MODE_HTMIX, 2, 14, 195}, /* 19.5 Mbps */ + {MODE_HTMIX, 3, 15, 260}, /* 26 Mbps */ + {MODE_HTMIX, 4, 16, 390}, /* 39 Mbps */ + {MODE_HTMIX, 5, 17, 520}, /* 52 Mbps */ + {MODE_HTMIX, 6, 18, 585}, /* 58.5 Mbps */ + {MODE_HTMIX, 7, 19, 650}, /* 65 Mbps */ + {MODE_HTMIX, 8, 20, 130}, /* 13 Mbps */ + {MODE_HTMIX, 9, 21, 260}, /* 26 Mbps */ + {MODE_HTMIX, 10, 22, 390}, /* 39 Mbps */ + {MODE_HTMIX, 11, 23, 520}, /* 52 Mbps */ + {MODE_HTMIX, 12, 24, 780}, /* 78 Mbps */ + {MODE_HTMIX, 13, 25, 1040}, /* 104 Mbps */ + {MODE_HTMIX, 14, 26, 1170}, /* 117 Mbps */ + {MODE_HTMIX, 15, 27, 1300}, /* 130 Mbps */ +#endif /* DOT11_N_SUPPORT */ +}; +#define _TX_RATE_TAB_SIZE (sizeof(TxRate) / sizeof(_TX_RATE)) + + INT loopIdx; + ULONG Rate = 10; + ULONG ErrRate = 0; + UINT PhyMode; + ULONG Metric; + ULONG PhyOverHead; + + PhyMode = HTTxMode.field.MODE; +#ifdef DOT11_N_SUPPORT + PhyMode = (HTTxMode.field.MODE > MODE_HTMIX) ? + MODE_HTMIX : HTTxMode.field.MODE; +#endif /* DOT11_N_SUPPORT */ + + for (loopIdx = 0; loopIdx < _TX_RATE_TAB_SIZE; loopIdx++) + { + if ((TxRate[loopIdx].PhyMode == HTTxMode.field.MODE) + && (TxRate[loopIdx].MCS == HTTxMode.field.MCS)) + { + Rate = TxRate[loopIdx].DataRate; + if (pMacEntry != NULL) + ErrRate = pMacEntry->PER[TxRate[loopIdx].RateIdx] >= 100 + ? 99 : pMacEntry->PER[TxRate[loopIdx].RateIdx]; + else + ErrRate = 0; + break; + } + } + +#ifdef DOT11_N_SUPPORT + if ((PhyMode > MODE_OFDM) + && (HTTxMode.field.BW == 1)) + { + Rate *= 2; + } +#endif /* DOT11_N_SUPPORT */ + + if (PhyMode == MODE_CCK) + PhyOverHead = 335 + 346; + else + PhyOverHead = 75 + 110; + + Metric = (PhyOverHead + (8192 * 10 / Rate)) * (100 /(100 - ErrRate)); + + return Metric; +} + +UINT32 MESH_LinkMetricUpdate( + IN PRTMP_ADAPTER pAd, + IN PCHAR pDestAddr) +{ + PMAC_TABLE_ENTRY pEntry; + HTTRANSMIT_SETTING HTTxMode; + ULONG Idx = GetMeshLinkId(pAd, pDestAddr); + + pEntry = MacTableLookup(pAd, (PUCHAR)pDestAddr); + if (pEntry == NULL) + HTTxMode.word = pAd->CommonCfg.MlmeTransmit.word; + else + HTTxMode.word = pEntry->HTPhyMode.word; + + if (Idx < MAX_MESH_LINKS) + pAd->MeshTab.MeshLink[Idx].Entry.Metrics = + MeshAirLinkTime(pAd, pEntry, HTTxMode); + + return pAd->MeshTab.MeshLink[Idx].Entry.Metrics; +} + +VOID EnqueuePeerLinkMetricReport( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDestAddr, + IN UINT32 Metric) +{ + HEADER_802_11 MeshHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + MESH_FLAG MeshFlag; + UINT32 MeshSeq = INC_MESH_SEQ(pAd->MeshTab.MeshSeq); + + 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; + } + + MeshHeaderInit(pAd, &MeshHdr, + pDestAddr, /* addr1 */ + pAd->MeshTab.CurrentAddress, /* addr2 */ + ZERO_MAC_ADDR); /* addr3 */ + NdisMoveMemory(pOutBuffer, (PCHAR)&MeshHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + /* Mesh Header */ + MeshFlag.word = 0; + MeshFlag.field.AE = 0; /* Peer-Link manager frame never carry 6 addresses. */ + InsertMeshHeader(pAd, (pOutBuffer + FrameLen), &FrameLen, MeshFlag.word, + pAd->MeshTab.TTL, MeshSeq, NULL, NULL, NULL); + + /* Action field */ + InsertMeshActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_MESH_LINK_METRIC, ACT_CODE_LINK_METRIC_REP); + + /* Insert Link Metric Report IE */ + InsertLinkMetricReportIE(pAd, (pOutBuffer+FrameLen), &FrameLen, Metric); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Dest address(%02x:%02x:%02x:%02x:%02x:%02x)\n", + __FUNCTION__, pDestAddr[0], pDestAddr[1], pDestAddr[2], + pDestAddr[4], pDestAddr[4], pDestAddr[5])); + + return; +} + +VOID MeshPeerLinkMetricReportProcess( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PHEADER_802_11 pHeader = (PHEADER_802_11)pRxBlk->pHeader; + PUCHAR pFrame; + ULONG FrameLen; + UINT MeshLinkId = 0; + UINT32 LinkMetric; + + do + { + ULONG Idx; + UCHAR MeshHdrLen; + + Idx = GetMeshLinkId(pAd, (PCHAR)pHeader->Addr2); + if (Idx == BSS_NOT_FOUND) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() Link Metric Report Ignore, PeerLink Not found.\n", __FUNCTION__)); + return; + } + MeshLinkId = (UINT)Idx; + + MeshHdrLen = GetMeshHederLen(pRxBlk->pData); + /* skip Mesh Header */ + pRxBlk->pData += MeshHdrLen; + pRxBlk->DataSize -= MeshHdrLen; + + /* skip Category and ActionCode */ + pFrame = (PUCHAR)(pRxBlk->pData + 2); + FrameLen = pRxBlk->DataSize - 2; + + MeshLinkMetricReportSanity( pAd, + pFrame, + FrameLen, + &LinkMetric); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: LinkMetric=%d, PeerMac=%02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, LinkMetric, pHeader->Addr2[0], pHeader->Addr2[1], + pHeader->Addr2[2], pHeader->Addr2[3], pHeader->Addr2[4], pHeader->Addr2[5])); + + pAd->MeshTab.MeshLink[Idx].Entry.Metrics = LinkMetric; + } while (FALSE); + + return; +} + + +VOID MeshCfgInit( + IN PRTMP_ADAPTER pAd, + IN PSTRING pHostName) +{ + INT i; + + /* default configuration of Mesh. */ + pAd->MeshTab.OpMode = MESH_MP; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + pAd->MeshTab.OpMode |= MESH_AP; +#endif /* CONFIG_AP_SUPPORT */ + + pAd->MeshTab.PathProtocolId = MESH_HWMP; + pAd->MeshTab.PathMetricId = MESH_AIRTIME; + pAd->MeshTab.ContgesionCtrlId = NULL_PROTOCOL; + pAd->MeshTab.TTL = MESH_TTL; + pAd->MeshTab.MeshMaxTxRate = 0; + pAd->MeshTab.MeshMultiCastAgeOut = MULTIPATH_AGEOUT; + pAd->MeshTab.UCGEnable = FALSE; + pAd->MeshTab.MeshCapability.field.Forwarding = 1; + if (pAd->MeshTab.MeshIdLen == 0) + { + pAd->MeshTab.MeshIdLen = strlen(DEFAULT_MESH_ID); + NdisMoveMemory(pAd->MeshTab.MeshId, DEFAULT_MESH_ID, pAd->MeshTab.MeshIdLen); + } + + /* initialize state */ + pAd->MeshTab.EasyMeshSecurity = TRUE; /* Default is TRUE for CMPC */ + pAd->MeshTab.bInitialMsaDone = FALSE; + pAd->MeshTab.bKeyholderDone = FALSE; + pAd->MeshTab.bConnectedToMKD = FALSE; + pAd->MeshTab.MeshOnly = FALSE; + + pAd->MeshTab.bAutoTxRateSwitch = TRUE; + pAd->MeshTab.DesiredTransmitSetting.field.MCS = MCS_AUTO; + + for (i = 0; i < MAX_MESH_LINKS; i++) + NdisZeroMemory(&pAd->MeshTab.MeshLink[i].Entry, sizeof(MESH_LINK_ENTRY)); + + if (strlen(pHostName) > 0) + { + if (strlen(pHostName) < MAX_HOST_NAME_LEN) + strcpy((PSTRING) pAd->MeshTab.HostName, pHostName); + else + strncpy((PSTRING) pAd->MeshTab.HostName, pHostName, MAX_HOST_NAME_LEN-1); + } + else + strcpy((PSTRING) pAd->MeshTab.HostName, DEFAULT_MESH_HOST_NAME); + +} + + +VOID MeshInit( + IN PRTMP_ADAPTER pAd, + IN RTMP_OS_NETDEV_OP_HOOK *pNetDevOps) +{ +#define MESH_MAX_DEV_NUM 32 + PNET_DEV new_dev_p; +/* RTMP_OS_NETDEV_OP_HOOK netDevOpHook; */ + + /* sanity check to avoid redundant virtual interfaces are created */ + if (pAd->flg_mesh_init != FALSE) + return; + + + /* init */ + pAd->MeshTab.dev = NULL; + + /* create virtual network interface */ + do { + UINT32 MC_RowID = 0, IoctlIF = 0; +#ifdef MULTIPLE_CARD_SUPPORT + MC_RowID = pAd->MC_RowID; +#endif /* MULTIPLE_CARD_SUPPORT */ +#ifdef HOSTAPD_SUPPORT + IoctlIF = pAd->IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + new_dev_p = RtmpOSNetDevCreate(MC_RowID, &IoctlIF, INT_MESH, 0, sizeof(PRTMP_ADAPTER), INF_MESH_DEV_NAME); +#ifdef HOSTAPD_SUPPORT + pAd->IoctlIF = IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + if (new_dev_p == NULL) + { + /* allocation fail, exit */ + DBGPRINT(RT_DEBUG_ERROR, ("Allocate network device fail (MESH)...\n")); + break; + } + + RTMP_OS_NETDEV_SET_PRIV(new_dev_p, pAd); + + /* init MAC address of virtual network interface */ + COPY_MAC_ADDR(pAd->MeshTab.CurrentAddress, pAd->CurrentAddress); +#ifdef CONFIG_AP_SUPPORT + if (pAd->chipCap.MBSSIDMode == MBSSID_MODE1) + { + if (pAd->ApCfg.BssidNum > 0) + { + /* + 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. + */ + pAd->MeshTab.CurrentAddress[0] += 2; + pAd->MeshTab.CurrentAddress[0] += ((pAd->ApCfg.BssidNum - 1) << 2); + } + } + else + { + pAd->MeshTab.CurrentAddress[ETH_LENGTH_OF_ADDRESS - 1] = + (pAd->MeshTab.CurrentAddress[ETH_LENGTH_OF_ADDRESS - 1] + pAd->ApCfg.BssidNum) & 0xFF; + } +#endif /* CONFIG_AP_SUPPORT */ + + + pNetDevOps->priv_flags = INT_MESH; /* we are virtual interface */ + pNetDevOps->needProtcted = TRUE; + NdisMoveMemory(&pNetDevOps->devAddr[0], &pAd->MeshTab.CurrentAddress[0], MAC_ADDR_LEN); + + /* register this device to OS */ + RtmpOSNetDevAttach(pAd->OpMode, new_dev_p, pNetDevOps); + + /* backup our virtual network interface */ + pAd->MeshTab.dev = new_dev_p; + } while(FALSE); + + /* Initialize Mesh configuration */ + /*MeshCfgInit(pAd, pHostName); */ + + /* initialize Mesh Tables and allocate spin locks */ + NdisAllocateSpinLock(pAd, &pAd->MeshTabLock); + + NeighborTableInit(pAd); + BMPktSigTabInit(pAd); + MultipathPoolInit(pAd); + + MeshRoutingTable_Init(pAd); + MeshEntryTable_Init(pAd); + MeshProxyEntryTable_Init(pAd); + +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + + pAd->flg_mesh_init = TRUE; +} + + +INT MESH_OpenPre( + IN PNET_DEV pDev) +{ + PRTMP_ADAPTER pAd; + + + pAd = RTMP_OS_NETDEV_GET_PRIV(pDev); + if (ADHOC_ON(pAd)) + return -1; + + pAd->MeshTab.bBcnSntReq = TRUE; + return 0; +} + + +INT MESH_OpenPost( + IN PNET_DEV pDev) +{ + PRTMP_ADAPTER pAd; + + + pAd = RTMP_OS_NETDEV_GET_PRIV(pDev); + + /* Statup Mesh Protocol Stack. */ + MeshUp(pAd); + +#ifdef CONFIG_STA_SUPPORT + { + UINT32 Value; + /* Pre-tbtt interrupt setting. */ + RTMP_IO_READ32(pAd, INT_TIMER_CFG, &Value); + Value &= 0xffff0000; + Value |= 6 << 4; /* Pre-TBTT is 6ms before TBTT interrupt. 1~10 ms is reasonable. */ + RTMP_IO_WRITE32(pAd, INT_TIMER_CFG, Value); + + /* Enable pre-tbtt interrupt */ + RTMP_IO_READ32(pAd, INT_TIMER_EN, &Value); + Value |=0x1; + RTMP_IO_WRITE32(pAd, INT_TIMER_EN, Value); + } + AsicEnableMESHSync(pAd); +#endif /* CONFIG_STA_SUPPORT */ + return 0; +} + + +INT MESH_Close( + IN PNET_DEV pDev) +{ + PRTMP_ADAPTER pAd; + + + pAd = RTMP_OS_NETDEV_GET_PRIV(pDev); + MeshDown(pAd, TRUE); + + pAd->MeshTab.bBcnSntReq = FALSE; + +#ifdef CONFIG_STA_SUPPORT + { + UINT32 Value; + /* Disable pre-tbtt interrupt */ + RTMP_IO_READ32(pAd, INT_TIMER_EN, &Value); + Value &=0xe; + RTMP_IO_WRITE32(pAd, INT_TIMER_EN, Value); + } + + /*update beacon Sync */ + /*if rausb0 is up => stop beacon */ + /*if rausb0 is down => we will call AsicDisableSync() in usb_rtusb_close_device() */ + if (INFRA_ON(pAd)) + AsicEnableBssSync(pAd); + else if (ADHOC_ON(pAd)) + AsicEnableIbssSync(pAd); + else + AsicDisableSync(pAd); +#endif /* CONFIG_STA_SUPPORT */ + + pAd->MeshTab.bBcnSntReq = FALSE; + +#ifdef CONFIG_AP_SUPPORT + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); +#endif /* CONFIG_AP_SUPPORT */ + return 0; +} + + +int MESH_PacketSend( + IN PNDIS_PACKET pPktSrc, + IN PNET_DEV pDev, + IN RTMP_NET_PACKET_TRANSMIT Func) +{ + PRTMP_ADAPTER pAd; + PMESH_STRUCT pMesh; + + + + pAd = RTMP_OS_NETDEV_GET_PRIV(pDev); + ASSERT(pAd); + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + RELEASE_NDIS_PACKET(pAd, pPktSrc, NDIS_STATUS_FAILURE); + return 0; + } +#endif /* RALINK_ATE */ + if ((RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))) + { + /* wlan is scanning/disabled/reset */ + RELEASE_NDIS_PACKET(pAd, pPktSrc, NDIS_STATUS_FAILURE); + return 0; + } + + pMesh = (PMESH_STRUCT)&pAd->MeshTab; + do + { + if (MeshValid(pMesh) != TRUE) + break; + /* find the device in our Mesh list */ + if (pMesh->dev == pDev) + { + /* ya! find it */ + pAd->RalinkCounters.PendingNdisPacketCount ++; + RTMP_SET_PACKET_SOURCE(pPktSrc, PKTSRC_NDIS); + RTMP_SET_PACKET_MOREDATA(pPktSrc, FALSE); + RTMP_SET_PACKET_NET_DEVICE_MESH(pPktSrc, 0); + SET_OS_PKT_NETDEV(pPktSrc, pAd->net_dev); + + + /* transmit the packet */ + return Func(RTPKT_TO_OSPKT(pPktSrc)); + } + } while(FALSE); + + + /* can not find the BSS so discard the packet */ + + RELEASE_NDIS_PACKET(pAd, pPktSrc, NDIS_STATUS_FAILURE); + + return 0; +} + +#endif /* MESH_SUPPORT */ + diff --git a/mt7620/src/common/mesh_bmpkt.c b/mt7620/src/common/mesh_bmpkt.c new file mode 100644 index 0000000..eb118b6 --- /dev/null +++ b/mt7620/src/common/mesh_bmpkt.c @@ -0,0 +1,593 @@ +/* + *************************************************************************** + * 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: + mesh.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi 2007-08-06 For mesh (802.11s) support. +*/ + +#ifdef MESH_SUPPORT + + +#include "rt_config.h" + +VOID BMPktSigTabInit( + IN PRTMP_ADAPTER pAd) +{ + NdisAllocateSpinLock(pAd, &pAd->MeshTab.MeshBMPktTabLock); + +/* pAd->MeshTab.pBMPktSigTab = kmalloc(sizeof(MESH_BMPKTSIG_TAB), GFP_ATOMIC); */ + os_alloc_mem(pAd, (UCHAR **)&(pAd->MeshTab.pBMPktSigTab), sizeof(MESH_BMPKTSIG_TAB)); + if (pAd->MeshTab.pBMPktSigTab) + NdisZeroMemory(pAd->MeshTab.pBMPktSigTab, sizeof(MESH_BMPKTSIG_TAB)); + else + DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->MeshTab.pBMPktSigTab", __FUNCTION__)); + + return; +} + +VOID BMPktSigTabExit( + IN PRTMP_ADAPTER pAd) +{ + NdisFreeSpinLock(&pAd->MeshTab.MeshBMPktTabLock); + + if (pAd->MeshTab.pBMPktSigTab) +/* kfree(pAd->MeshTab.pBMPktSigTab); */ + os_free_mem(NULL, pAd->MeshTab.pBMPktSigTab); + pAd->MeshTab.pBMPktSigTab = NULL; + + return; +} + +PMESH_BMPKTSIG_ENTRY BMPktSigTabLookUp( + IN PRTMP_ADAPTER pAd, + IN PUCHAR MeshSA) +{ + UINT HashIdx; + ULONG Now; + PMESH_BMPKTSIG_TAB pTab = pAd->MeshTab.pBMPktSigTab; + PMESH_BMPKTSIG_ENTRY pEntry = NULL; + PMESH_BMPKTSIG_ENTRY pPrevEntry = NULL; + + if (pTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pBMPktSigTab doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + RTMP_SEM_LOCK(&pAd->MeshTab.MeshBMPktTabLock); + + HashIdx = BMPKT_MAC_ADDR_HASH_INDEX(MeshSA); + pEntry = pTab->Hash[HashIdx]; + + while (pEntry) + { + if (MAC_ADDR_EQUAL(pEntry->MeshSA, MeshSA)) + break; + else + { + pPrevEntry = pEntry; + pEntry = pEntry->pNext; + } + } + + if (pEntry) + { + NdisGetSystemUpTime(&Now); + if (RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->LastRefTime + MESH_BMPKT_RECORD_TIME))) + { /* remove ageout entry. */ + if (pPrevEntry == NULL) + pTab->Hash[HashIdx] = pEntry->pNext; + else + pPrevEntry->pNext = pEntry->pNext; + + NdisZeroMemory(pEntry, sizeof(MESH_BMPKTSIG_ENTRY)); + pEntry = NULL; + pTab->Size--; + } + else + pEntry->LastRefTime = Now; + } + + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshBMPktTabLock); + + return pEntry; +} + +PMESH_BMPKTSIG_ENTRY BMPktSigTabInsert( + IN PRTMP_ADAPTER pAd, + IN PUCHAR MeshSA) +{ + INT i; + ULONG HashIdx; + PMESH_BMPKTSIG_TAB pTab = pAd->MeshTab.pBMPktSigTab; + PMESH_BMPKTSIG_ENTRY pEntry = NULL, pCurrEntry; + ULONG Now; + + if(pTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pBMPktSigTab doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + pEntry = BMPktSigTabLookUp(pAd, MeshSA); + if (pEntry == NULL) + { + /* if FULL, return */ + if (pTab->Size >= MAX_BMPKTSIG_TAB_SIZE) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pBMPktSigTab FULL.\n", __FUNCTION__)); + return NULL; + } + + RTMP_SEM_LOCK(&pAd->MeshTab.MeshBMPktTabLock); + for (i = 0; i < MAX_BMPKTSIG_TAB_SIZE; i++) + { + NdisGetSystemUpTime(&Now); + pEntry = &pTab->Content[i]; + + if ((pEntry->Valid == TRUE) + && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->LastRefTime + MESH_BMPKT_RECORD_TIME))) + { + PMESH_BMPKTSIG_ENTRY pPrevEntry = NULL; + ULONG HashIdx = BMPKT_MAC_ADDR_HASH_INDEX(pEntry->MeshSA); + PMESH_BMPKTSIG_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(MESH_BMPKTSIG_ENTRY)); + pTab->Size--; + + continue; + } + + if (pEntry->Valid == FALSE) + break; + } + + if (i < MAX_BMPKTSIG_TAB_SIZE) + { + NdisGetSystemUpTime(&Now); + pEntry->LastRefTime = Now; + pEntry->Valid = TRUE; + COPY_MAC_ADDR(pEntry->MeshSA, MeshSA); + pTab->Size++; + } + else + { + pEntry = NULL; + DBGPRINT(RT_DEBUG_ERROR, ("%s: pBMPktSigTab tab full.\n", __FUNCTION__)); + } + + /* add this Neighbor entry into HASH table */ + if (pEntry) + { + HashIdx = BMPKT_MAC_ADDR_HASH_INDEX(MeshSA); + 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->MeshTab.MeshBMPktTabLock); + } + + return pEntry; +} + +VOID BMPktSigTabDelete( + IN PRTMP_ADAPTER pAd, + IN PUCHAR MeshSA) +{ + PMESH_BMPKTSIG_TAB pTab = pAd->MeshTab.pBMPktSigTab; + PMESH_BMPKTSIG_ENTRY pEntry = NULL; + + if(pTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pBMPktSigTab doesn't exist.\n", __FUNCTION__)); + return; + } + + /* if empty, return */ + if (pTab->Size == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("pBMPktSigTab empty.\n")); + return; + } + + pEntry = BMPktSigTabLookUp(pAd, MeshSA); + if (pEntry != NULL) + { + PMESH_BMPKTSIG_ENTRY pPrevEntry = NULL; + ULONG HashIdx = BMPKT_MAC_ADDR_HASH_INDEX(pEntry->MeshSA); + PMESH_BMPKTSIG_ENTRY pProbeEntry = pTab->Hash[HashIdx]; + + RTMP_SEM_LOCK(&pAd->MeshTab.MeshBMPktTabLock); + /* 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(MESH_BMPKTSIG_ENTRY)); + pTab->Size--; + + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshBMPktTabLock); + } + + return; +} + + +BOOLEAN PktSigCheck( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pTA, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN UINT32 MeshSeq, + IN ULONG FrameType) +{ + BOOLEAN result = FALSE; + PMESH_BMPKTSIG_ENTRY pBMPktSigEntry = NULL; + + do + { + if ((FrameType == BTYPE_MGMT) || (*pDA & 0x01)) + { + if ((pBMPktSigEntry = BMPktSigTabLookUp(pAd, pSA)) == NULL) + { + if ((pBMPktSigEntry = BMPktSigTabInsert(pAd, pSA)) == NULL) + break; + + pBMPktSigEntry->MeshSeqBased = MeshSeq; + COPY_MAC_ADDR(pBMPktSigEntry->Precursor, pTA); + NdisZeroMemory(pBMPktSigEntry->Offset, sizeof(UINT32) * 4); + } + else + { + UINT32 DevNum; + UINT32 RemainNum; + UINT32 SeqDiff; + + if (MESH_SEQ_AFTER(pBMPktSigEntry->MeshSeqBased, MeshSeq)) + break; + + SeqDiff = MESH_SEQ_SUB(MeshSeq, pBMPktSigEntry->MeshSeqBased); + if (SeqDiff == 0) + break; + + if (SeqDiff > 128) + { + pBMPktSigEntry->MeshSeqBased = MeshSeq; + NdisZeroMemory(pBMPktSigEntry->Offset, sizeof(UINT32) * 4); + } + else + { + DevNum = (SeqDiff - 1) / 32; + RemainNum = (SeqDiff - 1) % 32; + if (pBMPktSigEntry->Offset[DevNum] & (1 << RemainNum)) + break; + else + pBMPktSigEntry->Offset[DevNum] |= (1 << RemainNum); + } + } + } + + result = TRUE; + } while (FALSE); + + if ((result == FALSE) + && (FrameType == BTYPE_DATA) + && IS_MULTICAST_MAC_ADDR(pDA) + && (pBMPktSigEntry != NULL) + && !MAC_ADDR_EQUAL(pBMPktSigEntry->Precursor, pTA)) + { + MeshMultipathNotice(pAd, pTA, pSA, 1); + } + + return result; +} + +VOID MeshClonePacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UINT8 MeshSrc, + IN UINT8 MeshLinkIdx) +{ + INT idx; + PUCHAR pSA = NULL; + PUCHAR pDA = NULL; + + for (idx = 0; idx < MAX_MESH_LINKS; idx++) + { + if ((MeshSrc == MESH_FORWARD) + && (MeshLinkIdx == idx)) + continue; + + pSA = GET_OS_PKT_DATAPTR(pPacket) + MAC_ADDR_LEN; + if (MAC_ADDR_EQUAL(pAd->MeshTab.MeshLink[idx].Entry.PeerMacAddr, pSA)) + continue; + + pDA = GET_OS_PKT_DATAPTR(pPacket); + if (IS_MULTICAST_MAC_ADDR(pDA) + && (MultipathEntryLookUp(pAd, idx, pSA) != NULL)) + continue; + + if (PeerLinkValidCheck(pAd, idx) == TRUE) + { + PNDIS_PACKET pPacketClone; + +/* pPacketClone = skb_clone(RTPKT_TO_OSPKT(pPacket), GFP_ATOMIC); */ + OS_PKT_CLONE(pAd, pPacket, pPacketClone, GFP_ATOMIC); + if (pPacketClone == NULL) + continue; + + RTMP_SET_PACKET_NET_DEVICE_MESH(pPacketClone, 0); + RTMP_SET_PACKET_SOURCE(pPacketClone, PKTSRC_NDIS); + RTMP_SET_PACKET_MOREDATA(pPacketClone, FALSE); + RTMP_SET_PACKET_WCID(pPacketClone, pAd->MeshTab.MeshLink[idx].Entry.MacTabMatchWCID); + RTMP_SET_MESH_ROUTE_ID(pPacketClone, BMCAST_ROUTE_ID); + RTMP_SET_MESH_SOURCE(pPacketClone, MeshSrc); +#ifdef CONFIG_AP_SUPPORT + APSendPacket(pAd, pPacketClone); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + STASendPacket(pAd, pPacketClone); +#endif /* CONFIG_STA_SUPPORT */ + } + } + + return; +} + +VOID MultipathPoolInit( + IN PRTMP_ADAPTER pAd) +{ + ULONG i; + + NdisAllocateSpinLock(pAd, &pAd->MeshTab.MultipathTabLock); + +/* pAd->MeshTab.pMultipathEntryPool = kmalloc(sizeof(MESH_MULTIPATH_ENTRY) * MULTIPATH_POOL_SIZE, GFP_ATOMIC); */ + os_alloc_mem(pAd, (UCHAR **)&(pAd->MeshTab.pMultipathEntryPool), sizeof(MESH_MULTIPATH_ENTRY) * MULTIPATH_POOL_SIZE); + if (pAd->MeshTab.pMultipathEntryPool) + { + NdisZeroMemory(pAd->MeshTab.pMultipathEntryPool, sizeof(MESH_BMPKTSIG_TAB)); + initList(&pAd->MeshTab.MultipathEntryFreeList); + for (i = 0; i < MULTIPATH_POOL_SIZE; i++) + insertTailList(&pAd->MeshTab.MultipathEntryFreeList, (PLIST_ENTRY)(pAd->MeshTab.pMultipathEntryPool + (ULONG)i)); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->MeshTab.pMultipathEntryPool", __FUNCTION__)); + + return; +} + +VOID MultipathPoolExit( + IN PRTMP_ADAPTER pAd) +{ + NdisFreeSpinLock(&pAd->MeshTab.MultipathTabLock); + + if (pAd->MeshTab.pMultipathEntryPool) +/* kfree(pAd->MeshTab.pMultipathEntryPool); */ + os_free_mem(NULL, pAd->MeshTab.pMultipathEntryPool); + pAd->MeshTab.pMultipathEntryPool = NULL; + + return; +} + +PMESH_MULTIPATH_ENTRY MultipathEntyAlloc( + IN PRTMP_ADAPTER pAd) +{ + PMESH_MULTIPATH_ENTRY pEntry; + + RTMP_SEM_LOCK(&pAd->MeshTab.MultipathTabLock); + + pEntry = (PMESH_MULTIPATH_ENTRY)removeHeadList(&pAd->MeshTab.MultipathEntryFreeList); + + RTMP_SEM_UNLOCK(&pAd->MeshTab.MultipathTabLock); + + return pEntry; +} + +VOID MultipathEntyFree( + IN PRTMP_ADAPTER pAd, + IN PMESH_MULTIPATH_ENTRY pEntry) +{ + RTMP_SEM_LOCK(&pAd->MeshTab.MultipathTabLock); + + insertTailList(&pAd->MeshTab.MultipathEntryFreeList, (PLIST_ENTRY)pEntry); + + RTMP_SEM_UNLOCK(&pAd->MeshTab.MultipathTabLock); + + return; +} + +VOID MultipathEntryInsert( + IN PRTMP_ADAPTER pAd, + IN UCHAR LinkIdx, + IN PUCHAR pMac) +{ + PMESH_MULTIPATH_ENTRY pEntry; + UINT8 HashId = *(pMac + 5); + ULONG Now; + + if (!VALID_MESH_LINK_ID(LinkIdx)) + return; + + pEntry = MultipathEntryLookUp(pAd, LinkIdx, pMac); + if(pEntry == NULL) + { + if ((pEntry = MultipathEntyAlloc(pAd)) == NULL) + return; + insertTailList(&pAd->MeshTab.MeshLink[LinkIdx].Entry.MultiPathHash[HashId], (PLIST_ENTRY)pEntry); + } + + DBGPRINT(RT_DEBUG_TRACE, ("Block multipath pkt to link(%d) from SA=%02x:%02x:%02x:%02x:%02x:%02x\n", + LinkIdx, pMac[0], pMac[1], pMac[2], pMac[3], pMac[4], pMac[5])); + + NdisGetSystemUpTime(&Now); + COPY_MAC_ADDR(pEntry->MeshSA, pMac); + pEntry->ReferTime = Now; + + return; +} + +VOID MultipathEntryDelete( + IN PRTMP_ADAPTER pAd, + IN UCHAR LinkIdx, + IN PUCHAR pMac) +{ + UINT8 HashId = *(pMac + 5); + PMESH_MULTIPATH_ENTRY pEntry; + + if (!VALID_MESH_LINK_ID(LinkIdx)) + return; + + pEntry = MultipathEntryLookUp(pAd, LinkIdx, pMac); + + if (pEntry != NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("release multipath pkt to link(%d) from SA=%02x:%02x:%02x:%02x:%02x:%02x\n", + LinkIdx, pMac[0], pMac[1], pMac[2], pMac[3], pMac[4], pMac[5])); + + delEntryList(&pAd->MeshTab.MeshLink[LinkIdx].Entry.MultiPathHash[HashId], (PLIST_ENTRY)pEntry); + MultipathEntyFree(pAd, pEntry); + } +} + +VOID MultipathListDelete( + IN PRTMP_ADAPTER pAd, + IN UCHAR LinkIdx) +{ + ULONG i; + PMESH_MULTIPATH_ENTRY pEntry; + + if (!VALID_MESH_LINK_ID(LinkIdx)) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("release all multipath pkt of link(%d)\n", LinkIdx)); + + for (i = 0; i < MULTIPATH_HASH_TAB_SIZE; i++) + { + pEntry = (PMESH_MULTIPATH_ENTRY)removeHeadList(&pAd->MeshTab.MeshLink[LinkIdx].Entry.MultiPathHash[i]); + while (pEntry != NULL) + { + MultipathEntyFree(pAd, pEntry); + pEntry = (PMESH_MULTIPATH_ENTRY)removeHeadList(&pAd->MeshTab.MeshLink[LinkIdx].Entry.MultiPathHash[i]); + } + } + return; +} + +PMESH_MULTIPATH_ENTRY MultipathEntryLookUp( + IN PRTMP_ADAPTER pAd, + IN UCHAR LinkIdx, + IN PUCHAR pMac) +{ + UINT8 HashId = *(pMac + 5); + PMESH_MULTIPATH_ENTRY pEntry; + + if (!VALID_MESH_LINK_ID(LinkIdx)) + return NULL; + + pEntry = (PMESH_MULTIPATH_ENTRY)(pAd->MeshTab.MeshLink[LinkIdx].Entry.MultiPathHash[HashId].pHead); + while (pEntry != NULL) + { + if(MAC_ADDR_EQUAL(pEntry->MeshSA, pMac)) + break; + pEntry = pEntry->pNext; + } + + return pEntry; +} + +VOID MultipathEntryMaintain( + IN PRTMP_ADAPTER pAd, + IN UCHAR LinkIdx) +{ + ULONG i; + PMESH_MULTIPATH_ENTRY pEntry; + ULONG Now; + + if (!VALID_MESH_LINK_ID(LinkIdx)) + return; + + NdisGetSystemUpTime(&Now); + for (i = 0; i < MULTIPATH_HASH_TAB_SIZE; i++) + { + pEntry = (PMESH_MULTIPATH_ENTRY)(pAd->MeshTab.MeshLink[LinkIdx].Entry.MultiPathHash[i].pHead); + while (pEntry) + { + PMESH_MULTIPATH_ENTRY pEntryNext = pEntry->pNext; + if (RTMP_TIME_AFTER(Now, pEntry->ReferTime + (pAd->MeshTab.MeshMultiCastAgeOut * OS_HZ / 1000))) + { + delEntryList(&pAd->MeshTab.MeshLink[LinkIdx].Entry.MultiPathHash[i], (PLIST_ENTRY)pEntry); + MultipathEntyFree(pAd, pEntry); + } + pEntry = pEntryNext; + } + } + return; +} + +#endif /* MESH_SUPPORT */ + diff --git a/mt7620/src/common/mesh_ctrl.c b/mt7620/src/common/mesh_ctrl.c new file mode 100644 index 0000000..119aef1 --- /dev/null +++ b/mt7620/src/common/mesh_ctrl.c @@ -0,0 +1,1434 @@ +/* + *************************************************************************** + * 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: + mesh_ctrl.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi 2007-06-25 For mesh (802.11s) support. +*/ +#ifdef MESH_SUPPORT + + +#include "rt_config.h" +#include "mesh_sanity.h" + +static VOID MeshPldTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +static VOID MeshMcsTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +static VOID +MeshCtrlJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID +MeshCtrlDisconnectAtDicoveryAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID +MeshCtrlFinishDiscoveryAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID +MeshCtrlDiscoveryAbortAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID +MeshCtrlPeriodPLDAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID +MeshCtrlDisconnectAtActivatedAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID +MeshCtrlUcgWhenActivated( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID +MeshPeerUcgWhenActivated( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID +MeshPeerUcgWhenUcg( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID +MeshCtrlDisconnectAtUCGAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID +MeshCtrlMcsTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +DECLARE_TIMER_FUNCTION(MeshPldTimeout); +DECLARE_TIMER_FUNCTION(MeshMcsTimeout); + +BUILD_TIMER_FUNCTION(MeshPldTimeout); +BUILD_TIMER_FUNCTION(MeshMcsTimeout); + +static VOID +NeighborEntrySet( + OUT PMESH_NEIGHBOR_ENTRY pNeighbor, + IN CHAR RealRssi, + IN PUCHAR pPeerMacAddr, + IN PSTRING pHostName, + IN PCHAR pMeshId, + IN UCHAR MeshIdLen, + IN UCHAR Channel, + IN UINT8 ChBW, + IN UINT8 ExtChOffset, + IN USHORT CapabilityInfo, + IN PUCHAR pVIE, + IN USHORT LenVIE, + IN PMESH_CONFIGURAION_IE pMeshConfig); + +static PMESH_NEIGHBOR_ENTRY +NeighMPWithMaxCPI( + IN PRTMP_ADAPTER pAd, + IN PMESH_NEIGHBOR_TAB pNeighborTab); + +static VOID +EnqueChSwAnnouncement( + IN PRTMP_ADAPTER pAd, + IN PUCHAR PeerMac, + IN UINT8 MeshTTL, + IN UINT32 MeshSeq, + IN UINT8 ChSwMode, + IN UCHAR NewCh, + IN UINT32 NewCPI, + IN UINT8 ChSwCnt, + IN PUCHAR pMeshSa); + +BOOLEAN MeshValid(PMESH_STRUCT pMesh) +{ + return (pMesh->CtrlCurrentState == MESH_CTRL_ACTIVATED) ? TRUE : FALSE; +} + +/* + ========================================================================== + Description: + The mesh control state machine, + Parameters: + Sm - pointer to the state machine + Note: + the state machine looks like the following + ========================================================================== + */ +VOID MeshCtrlStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, (ULONG)MESH_CTRL_MAX_STATES, + (ULONG)MESH_CTRL_MAX_EVENTS, (STATE_MACHINE_FUNC)Drop, MESH_CTRL_IDLE, MESH_CTRL_IDLE); + + /* MESH_CTRL_IDLE state */ + StateMachineSetAction(Sm, MESH_CTRL_IDLE, MESH_CTRL_JOIN, (STATE_MACHINE_FUNC)MeshCtrlJoinAction); + + /* MESH_CTRL_DISCOVERY state */ + StateMachineSetAction(Sm, MESH_CTRL_DISCOVERY, MESH_CTRL_DISCONNECT, (STATE_MACHINE_FUNC)MeshCtrlDisconnectAtDicoveryAction); + StateMachineSetAction(Sm, MESH_CTRL_DISCOVERY, APMT2_MLME_SCAN_FINISH, (STATE_MACHINE_FUNC)MeshCtrlFinishDiscoveryAction); + StateMachineSetAction(Sm, MESH_CTRL_DISCOVERY, APMT2_MLME_SCAN_ABORT, (STATE_MACHINE_FUNC)MeshCtrlDiscoveryAbortAction); + + /* MESH_CTRL_ACTIVATED state */ + StateMachineSetAction(Sm, MESH_CTRL_ACTIVATED, MESH_CTRL_PLD, (STATE_MACHINE_FUNC)MeshCtrlPeriodPLDAction); + StateMachineSetAction(Sm, MESH_CTRL_ACTIVATED, MESH_CTRL_DISCONNECT, (STATE_MACHINE_FUNC)MeshCtrlDisconnectAtActivatedAction); + StateMachineSetAction(Sm, MESH_CTRL_ACTIVATED, MESH_CTRL_UCG_EVT, (STATE_MACHINE_FUNC)MeshCtrlUcgWhenActivated); + StateMachineSetAction(Sm, MESH_CTRL_ACTIVATED, MESH_PEER_UCG_EVT, (STATE_MACHINE_FUNC)MeshPeerUcgWhenActivated); + + /* MESH_CTRL_UCG state */ + StateMachineSetAction(Sm, MESH_CTRL_UCG, MESH_CTRL_DISCONNECT, (STATE_MACHINE_FUNC)MeshCtrlDisconnectAtUCGAction); + StateMachineSetAction(Sm, MESH_CTRL_UCG, MESH_PEER_UCG_EVT, (STATE_MACHINE_FUNC)MeshPeerUcgWhenUcg); + StateMachineSetAction(Sm, MESH_CTRL_UCG, MESH_CTRL_MCS_TIMEOUT, (STATE_MACHINE_FUNC)MeshCtrlMcsTimeoutAction); + + /* init all Mesh ctrl state. */ + pAd->MeshTab.CtrlCurrentState = MESH_CTRL_IDLE; + + /* init all timer relative to mesh ctrl sm. */ + RTMPInitTimer(pAd, &pAd->MeshTab.PldTimer, GET_TIMER_FUNCTION(MeshPldTimeout), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->MeshTab.McsTimer, GET_TIMER_FUNCTION(MeshMcsTimeout), pAd, FALSE); + + return; +} + +/* + ========================================================================== + Description: + Peer-Link-Discovery timeout procedure. + Parameters: + Standard timer parameters + ========================================================================== + */ +static VOID MeshPldTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + DBGPRINT(RT_DEBUG_TRACE, ("%s - enqueue MESH_CTRL_PLD to MESH_CTRL State-Machine.\n", __FUNCTION__)); + + MlmeEnqueue(pAd, MESH_CTRL_STATE_MACHINE, MESH_CTRL_PLD, 0, NULL, 0); + MeshMlmeHandler(pAd); + + return; +} + +/* + ========================================================================== + Description: + Mesh-Channel-Switch timeout procedure. + Parameters: + Standard timer parameters + ========================================================================== + */ +static VOID MeshMcsTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + DBGPRINT(RT_DEBUG_TRACE, ("%s - enqueue MESH_CTRL_MCS_TIMEOUT to MESH_CTRL State-Machine.\n", __FUNCTION__)); + + MlmeEnqueue(pAd, MESH_CTRL_STATE_MACHINE, MESH_CTRL_MCS_TIMEOUT, 0, NULL, 0); + MeshMlmeHandler(pAd); + + return; +} + +static VOID +MeshCtrlJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MESH_CTRL_STATE *pCurrState = &(pAd->MeshTab.CtrlCurrentState); + +#ifdef CONFIG_STA_SUPPORT + /* Initialize RF register to default value */ + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + MeshChannelInit(pAd); + } +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef INTEL_CMPC + /* Set PLD timer. */ + /* transit state to MESH_CTRL_ACTIVATED. */ + + RTMPSetTimer(&pAd->MeshTab.PldTimer, PLD_TIME); + *pCurrState = MESH_CTRL_ACTIVATED; +#else + + MLME_SCAN_REQ_STRUCT ScanReq; + UCHAR BroadSsid[MAX_LEN_OF_SSID]; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get Join evt when Idle.\n", __FUNCTION__)); + + AsicDisableSync(pAd); + + BssTableInit(&pAd->ScanTab); + BroadSsid[0] = '\0'; + + ScanReq.SsidLen = 0; + NdisMoveMemory(ScanReq.Ssid, BroadSsid, ScanReq.SsidLen); + ScanReq.BssType = BSS_ANY; + ScanReq.ScanType = SCAN_PASSIVE; + +#ifdef CONFIG_AP_SUPPORT + pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; + MlmeEnqueue(pAd, AP_SYNC_STATE_MACHINE, APMT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0); + MeshMlmeHandler(pAd); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + ScanParmFill(pAd, &ScanReq, "", 0, BSS_ANY, SCAN_ACTIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, + sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0); +#endif /* CONFIG_STA_SUPPORT */ + + *pCurrState = MESH_CTRL_DISCOVERY; +#endif +} + +static VOID +MeshCtrlDisconnectAtDicoveryAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + MESH_CTRL_STATE *pCurrState = &(pAd->MeshTab.CtrlCurrentState); + INT i; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get Disconnect evt when Discovery.\n", __FUNCTION__)); + + for (i = 0; i < MAX_MESH_LINKS; i++) + { + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_CNCL, 0, NULL, i); + } + +#ifdef AP_SCAN_SUPPORT + MlmeEnqueue(pAd, AP_SYNC_STATE_MACHINE, APMT2_MLME_SCAN_CNCL, 0, NULL, 0); +#endif + *pCurrState = MESH_CTRL_IDLE; +} + +static VOID +MeshCtrlFinishDiscoveryAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + MESH_CTRL_STATE *pCurrState = &(pAd->MeshTab.CtrlCurrentState); + INT i; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get Scan-Finish evt when Discovery.\n", __FUNCTION__)); + + NeighborTableUpdate(pAd); + CandidateMPSelect(pAd); + + for (i = 0; i < MAX_MESH_LINKS; i++) + { + if(pAd->MeshTab.MeshLink[i].Entry.Valid) + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_ACTOPN, 0, NULL, i); + } + + RTMPSetTimer(&pAd->MeshTab.PldTimer, PLD_TIME + RANDOM_TIME(pAd)); + *pCurrState = MESH_CTRL_ACTIVATED; +} + +static VOID +MeshCtrlDiscoveryAbortAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MESH_CTRL_STATE *pCurrState = &(pAd->MeshTab.CtrlCurrentState); + + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get Scan-Abort evt when Discovery.\n", __FUNCTION__)); + + RTMPSetTimer(&pAd->MeshTab.PldTimer, PLD_TIME + RANDOM_TIME(pAd)); + *pCurrState = MESH_CTRL_ACTIVATED; +} + +static VOID +MeshCtrlPeriodPLDAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ +#ifdef INTEL_CMPC + /* select candidate MPs from neighbor list. */ + /* set PLD timer. */ + + INT i; + + CandidateMPSelect(pAd); + for (i = 0; i < MAX_MESH_LINKS; i++) + { + BOOLEAN CnetFlag = FALSE; + + if (pAd->MeshTab.MeshAutoLink == TRUE) + CnetFlag = pAd->MeshTab.MeshLink[i].Entry.Valid && !PeerLinkValidCheck(pAd, i); + else + CnetFlag = pAd->MeshTab.MeshLink[i].Entry.Valid + && (pAd->MeshTab.MeshLink[i].Entry.LinkType == MESH_LINK_STATIC) + && !PeerLinkValidCheck(pAd, i); + + if (CnetFlag) + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_ACTOPN, 0, NULL, i); + } + + RTMPSetTimer(&pAd->MeshTab.PldTimer, PLD_TIME); +#else + + PULONG pCurrState = &(pAd->MeshTab.CtrlCurrentState); + INT i; + BOOLEAN Valid = TRUE; + MLME_SCAN_REQ_STRUCT ScanReq; + UCHAR BroadSsid[MAX_LEN_OF_SSID]; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get PLD evt when Activated.\n", __FUNCTION__)); + + AsicDisableSync(pAd); + + BssTableInit(&pAd->ScanTab); + BroadSsid[0] = '\0'; + + ScanReq.SsidLen = 0; + NdisMoveMemory(ScanReq.Ssid, BroadSsid, ScanReq.SsidLen); + ScanReq.BssType = BSS_ANY; + ScanReq.ScanType = SCAN_PASSIVE; + + for (i = 0; i < MAX_MESH_LINKS; i++) + { + if (PeerLinkMngRuning(pAd, i)) + { + Valid = FALSE; + break; + } + } + + if (Valid) + { +#ifdef CONFIG_AP_SUPPORT + pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; + MlmeEnqueue(pAd, AP_SYNC_STATE_MACHINE, APMT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0); + MeshMlmeHandler(pAd); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + ScanParmFill(pAd, &ScanReq, "", 0, BSS_ANY, SCAN_ACTIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, + sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0); +#endif /* CONFIG_STA_SUPPORT */ + *pCurrState = MESH_CTRL_DISCOVERY; + } + else + { + RTMPSetTimer(&pAd->MeshTab.PldTimer, PLD_TIME + RANDOM_TIME(pAd)); + } +#endif /* INTEL_CMPC */ +} + +static VOID +MeshCtrlDisconnectAtActivatedAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + MESH_CTRL_STATE *pCurrState = &(pAd->MeshTab.CtrlCurrentState); + INT i; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get Disconnect evt when Activated.\n", __FUNCTION__)); + + for (i = 0; i < MAX_MESH_LINKS; i++) + { + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_CNCL, 0, NULL, i); + } + RTMPCancelTimer(&pAd->MeshTab.PldTimer, &Cancelled); + + *pCurrState = MESH_CTRL_IDLE; +} + +static VOID +MeshCtrlUcgWhenActivated( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + MESH_CTRL_STATE *pCurrState = &(pAd->MeshTab.CtrlCurrentState); + INT i; + BOOLEAN Cancelled; + UINT8 ChSwCnt = RandomChSwWaitTime(pAd); + UINT32 NewCPI = pAd->MeshTab.CPI += RandomByte(pAd); + UINT32 ChSwMode = 1; + + RTMPCancelTimer(&pAd->MeshTab.PldTimer, &Cancelled); + RTMPSetTimer(&pAd->MeshTab.McsTimer, ChSwCnt * MESH_TU); + + /* propagate channel switch announcement to each peer link. */ + INC_MESH_SEQ(pAd->MeshTab.MeshSeq); + for (i = 0; i < MAX_MESH_LINKS; i++) + { + if (PeerLinkValidCheck(pAd, i) == TRUE) + EnqueChSwAnnouncement( + pAd, + pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr, + pAd->MeshTab.TTL, + pAd->MeshTab.MeshSeq, + ChSwMode, + pAd->MeshTab.MeshChannel, + NewCPI, + ChSwCnt, + pAd->MeshTab.CurrentAddress); + } + + pAd->MeshTab.NewCPI = NewCPI; + *pCurrState = MESH_CTRL_UCG; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get UCG evt when Activated.\n", __FUNCTION__)); +} + +static VOID +MeshPeerUcgWhenActivated( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + MESH_CTRL_STATE *pCurrState = &(pAd->MeshTab.CtrlCurrentState); + BOOLEAN Cancelled; + PMESH_CH_SW_ANN_MSG_STRUCT pInfo = (PMESH_CH_SW_ANN_MSG_STRUCT)(Elem->Msg); + UINT32 NewCPI = pInfo->NewCPI; + PUCHAR pMeshSA = pInfo->MeshSA; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get UCG evt when Activated.\n", __FUNCTION__)); + + if ((NewCPI < pAd->MeshTab.CPI) + || ((NewCPI == pAd->MeshTab.CPI) && (memcmp(pAd->MeshTab.CurrentAddress, pMeshSA, MAC_ADDR_LEN) >= 0)) + ) + { + return; + } + + RTMPCancelTimer(&pAd->MeshTab.PldTimer, &Cancelled); + MeshPeerUcgWhenUcg(pAd, Elem); + *pCurrState = MESH_CTRL_UCG; + + return; +} + +static VOID +MeshPeerUcgWhenUcg( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + MESH_CTRL_STATE *pCurrState = &(pAd->MeshTab.CtrlCurrentState); + INT i; + BOOLEAN Cancelled; + PMESH_CH_SW_ANN_MSG_STRUCT pInfo = (PMESH_CH_SW_ANN_MSG_STRUCT)(Elem->Msg); + UINT32 NewCPI = pInfo->NewCPI; + UINT32 MeshSeq = pInfo->MeshSeq; + UINT8 MeshTTL = pInfo->MeshTTL; + UINT8 ChSwCnt = pInfo->ChSwCnt; + UINT8 NewCh = pInfo->NewCh; + UINT8 ChSwMode = pInfo->ChSwMode; + UINT8 LinkId = pInfo->LinkId; + PUCHAR pMeshSA = pInfo->MeshSA; + + if ((NewCPI < pAd->MeshTab.CPI) + || ((NewCPI == pAd->MeshTab.CPI) && (memcmp(pAd->MeshTab.CurrentAddress, pMeshSA, MAC_ADDR_LEN) >= 0)) + ) + { + return; + } + + if (*pCurrState == MESH_CTRL_UCG) + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get UCG evt when Activated.\n", __FUNCTION__)); + + pAd->MeshTab.MeshChannel = NewCh; + RTMPCancelTimer(&pAd->MeshTab.McsTimer, &Cancelled); + RTMPSetTimer(&pAd->MeshTab.McsTimer, ChSwCnt * MESH_TU); + + /* foward ChSwAnnouncement to each peer link. */ + MeshTTL--; + do + { + if (MeshTTL == 0) + break; + + for (i = 0; i < MAX_MESH_LINKS; i++) + { + if (PeerLinkValidCheck(pAd, i) == FALSE) + continue; + + if (LinkId == i) + continue; + + if (MAC_ADDR_EQUAL(pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr, pMeshSA) == TRUE) + continue; + + EnqueChSwAnnouncement( + pAd, + pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr, + MeshTTL, + MeshSeq, + ChSwMode, + NewCh, + NewCPI, + ChSwCnt, + pMeshSA); + } + } while(FALSE); + + pAd->MeshTab.NewCPI = NewCPI; + + return; +} + +static VOID +MeshCtrlDisconnectAtUCGAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + MESH_CTRL_STATE *pCurrState = &(pAd->MeshTab.CtrlCurrentState); + INT i; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get Disconnect evt when UCG.\n", __FUNCTION__)); + + for (i = 0; i < MAX_MESH_LINKS; i++) + { + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_CNCL, 0, NULL, i); + } + RTMPCancelTimer(&pAd->MeshTab.McsTimer, &Cancelled); + + *pCurrState = MESH_CTRL_IDLE; +} + +static VOID +MeshCtrlMcsTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + MESH_CTRL_STATE *pCurrState = &(pAd->MeshTab.CtrlCurrentState); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get Mcs evt when UCG.\n", __FUNCTION__)); + + if (!INFRA_ON(pAd) && !ADHOC_ON(pAd)) + { + /*SET_MESH_CHANNEL(pAd); */ + pAd->CommonCfg.Channel = pAd->MeshTab.MeshChannel; +#ifdef DOT11_N_SUPPORT + N_ChannelCheck(pAd); +#endif /* DOT11_N_SUPPORT */ + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + + pAd->MeshTab.CPI = pAd->MeshTab.NewCPI; + } + else + pAd->MeshTab.MeshChannel = pAd->CommonCfg.Channel; + + RTMPSetTimer(&pAd->MeshTab.PldTimer, PLD_TIME); + + *pCurrState = MESH_CTRL_ACTIVATED; +} + +BOOLEAN NeighborMPCheck( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMeshId, + IN UINT8 PathSelProtocolId, + IN UINT8 PathSelMetricId) +{ + BOOLEAN result = FALSE; + + if ((NdisEqualMemory(pMeshId, pAd->MeshTab.MeshId, pAd->MeshTab.MeshIdLen)) + && (PathSelProtocolId == pAd->MeshTab.PathProtocolId) + && (PathSelMetricId == pAd->MeshTab.PathMetricId)) + result = TRUE; + + return result; +} + +PMESH_NEIGHBOR_ENTRY InsertNeighborMP( + IN PRTMP_ADAPTER pAd, + IN CHAR RealRssi, + IN PUCHAR pPeerMacAddr, + IN UCHAR Channel, + IN UINT8 ChBW, + IN UINT8 ExtChOffset, + IN PUCHAR pHostName, + IN PUCHAR pMeshId, + IN UCHAR MeshIdLen, + IN USHORT CapabilityInfo, + IN PUCHAR pVIE, + IN USHORT LenVIE, + IN PMESH_CONFIGURAION_IE pMeshConfig) +{ + INT i; + ULONG HashIdx; + PMESH_NEIGHBOR_TAB pNeighborTab = pAd->MeshTab.pMeshNeighborTab; + PMESH_NEIGHBOR_ENTRY pNeighborEntry = NULL, pNeighborCurrEntry; + + if(pNeighborTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("pAd->MeshTab.pMeshNeighborTab equal NULL.\n")); + return NULL; + } + + pNeighborEntry = NeighborSearch(pAd, pPeerMacAddr); + if (pNeighborEntry == NULL) + { + /* if FULL, return */ + if (pNeighborTab->NeighborNr >= MAX_NEIGHBOR_MP) + { + DBGPRINT(RT_DEBUG_ERROR, ("pAd->MeshTab.pMeshNeighborTab FULL.\n")); + return NULL; + } + + for (i = 0; i < MAX_NEIGHBOR_MP; i++) + { + pNeighborEntry = &pAd->MeshTab.pMeshNeighborTab->NeighborMP[i]; + if (pNeighborEntry->Valid == FALSE) + break; + } + + if (i < MAX_NEIGHBOR_MP) + { + ULONG Idx; + + NeighborEntrySet(pNeighborEntry, RealRssi, pPeerMacAddr, (PSTRING)pHostName, (PCHAR)pMeshId, MeshIdLen, + Channel, ChBW, ExtChOffset, CapabilityInfo, pVIE, LenVIE, pMeshConfig); + Idx = GetMeshLinkId(pAd, (PCHAR)pPeerMacAddr); + if (Idx != BSS_NOT_FOUND) + { + pNeighborEntry->State = CANDIDATE_MP; + pNeighborEntry->MeshLinkIdx = Idx; + } + else + pNeighborEntry->State = NEIGHBOR_MP; + + pNeighborTab->NeighborNr++; + } + else + { + pNeighborEntry = NULL; + DBGPRINT(RT_DEBUG_ERROR, ("%s: Neighbor tab full.\n", __FUNCTION__)); + } + + /* add this Neighbor entry into HASH table */ + if (pNeighborEntry) + { + HashIdx = MESH_MAC_ADDR_HASH_INDEX(pPeerMacAddr); + if (pNeighborTab->Hash[HashIdx] == NULL) + { + pNeighborTab->Hash[HashIdx] = pNeighborEntry; + } + else + { + pNeighborCurrEntry = pNeighborTab->Hash[HashIdx]; + while (pNeighborCurrEntry->pNext != NULL) + pNeighborCurrEntry = pNeighborCurrEntry->pNext; + pNeighborCurrEntry->pNext = pNeighborEntry; + } + } + } + else + { + NeighborEntrySet(pNeighborEntry, RealRssi, pPeerMacAddr, (PSTRING)pHostName, (PCHAR)pMeshId, MeshIdLen, + Channel, ChBW, ExtChOffset, CapabilityInfo, pVIE, LenVIE, pMeshConfig); + } + + return pNeighborEntry; +} + +VOID DeleteNeighborMP( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pPeerMacAddr) +{ + PMESH_NEIGHBOR_TAB pNeighborTab = pAd->MeshTab.pMeshNeighborTab; + PMESH_NEIGHBOR_ENTRY pNeighborEntry = NULL; + + if(pNeighborTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("pAd->MeshTab.pMeshNeighborTab equal NULL.\n")); + return; + } + + /* if empty, return */ + if (pNeighborTab->NeighborNr == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("pMeshNeighborTab empty.\n")); + return; + } + + pNeighborEntry = NeighborSearch(pAd, pPeerMacAddr); + if (pNeighborEntry != NULL) + { + PMESH_NEIGHBOR_ENTRY pPrevEntry = NULL; + ULONG HashIdx = MESH_MAC_ADDR_HASH_INDEX(pNeighborEntry->PeerMac); + PMESH_NEIGHBOR_ENTRY pProbeEntry = pNeighborTab->Hash[HashIdx]; + + /* update Hash list */ + do + { + if (pProbeEntry == pNeighborEntry) + { + if (pPrevEntry == NULL) + { + pNeighborTab->Hash[HashIdx] = pNeighborEntry->pNext; + } + else + { + pPrevEntry->pNext = pNeighborEntry->pNext; + } + break; + } + + pPrevEntry = pProbeEntry; + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + + NdisZeroMemory(pNeighborEntry, sizeof(MESH_NEIGHBOR_ENTRY)); + pNeighborTab->NeighborNr--; + } + + return; +} + +PMESH_NEIGHBOR_ENTRY NeighborSearch( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pPeerMacAddr) +{ + ULONG HashIdx; + PMESH_NEIGHBOR_ENTRY pNighborEntry = NULL; + + HashIdx = MESH_MAC_ADDR_HASH_INDEX(pPeerMacAddr); + pNighborEntry = pAd->MeshTab.pMeshNeighborTab->Hash[HashIdx]; + + while (pNighborEntry) + { + if (MAC_ADDR_EQUAL(pNighborEntry->PeerMac, pPeerMacAddr)) + { + break; + } + else + pNighborEntry = pNighborEntry->pNext; + } + + return pNighborEntry; +} + +static VOID NeighborEntrySet( + OUT PMESH_NEIGHBOR_ENTRY pNeighbor, + IN CHAR RealRssi, + IN PUCHAR pPeerMacAddr, + IN PSTRING pHostName, + IN PCHAR pMeshId, + IN UCHAR MeshIdLen, + IN UCHAR Channel, + IN UINT8 ChBW, + IN UINT8 ExtChOffset, + IN USHORT CapabilityInfo, + IN PUCHAR pVIE, + IN USHORT LenVIE, + IN PMESH_CONFIGURAION_IE pMeshConfig) +{ + ULONG Now; + + NdisGetSystemUpTime(&Now); + + pNeighbor->Valid = TRUE; + COPY_MAC_ADDR(pNeighbor->PeerMac, pPeerMacAddr); + + /* record host name. */ + if(strlen(pHostName) > 0 && strlen(pHostName) < MAX_HOST_NAME_LEN) + strcpy((PSTRING) pNeighbor->HostName, pHostName); + else + strcpy((PSTRING) pNeighbor->HostName, DEFAULT_MESH_HOST_NAME); + + /* record mesh id. */ + if (MeshIdLen > 0) + { + NdisMoveMemory(pNeighbor->MeshId, pMeshId, MAX_MESH_ID_LEN); + pNeighbor->MeshIdLen = MeshIdLen; + } + + pNeighbor->RealRssi = RealRssi; + pNeighbor->Channel = Channel; + pNeighbor->ChBW = ChBW; + pNeighbor->ExtChOffset = ExtChOffset; + pNeighbor->CPI = pMeshConfig->CPI; + pNeighbor->PathProtocolId = pMeshConfig->PathSelProtocolId; + pNeighbor->PathMetricId = pMeshConfig->PathSelMetricId; + pNeighbor->MeshCapability = pMeshConfig->MeshCapability; + pNeighbor->Version = pMeshConfig->Version; + + pNeighbor->IdleCnt = 0; + pNeighbor->LastBeaconTime = Now; + + /*pNeighbor->MeshEncrypType = MeshCipher; */ + pNeighbor->CapabilityInfo = CapabilityInfo; + + if (LenVIE > 0) + { + NdisMoveMemory(pNeighbor->RSNIE, pVIE, LenVIE); + pNeighbor->RSNIE_Len = LenVIE; + } + else + { + pNeighbor->RSNIE_Len = 0; + } + + return; +} + +static PMESH_NEIGHBOR_ENTRY NeighMPWithMaxCPI( + IN PRTMP_ADAPTER pAd, + IN PMESH_NEIGHBOR_TAB pNeighborTab) +{ + INT i; + UINT32 MaxCPI = 0; + PMESH_NEIGHBOR_ENTRY pMaxCpiEntry = NULL; + PMESH_NEIGHBOR_ENTRY pNeighborEntry = NULL; + + for (i = 0; i < MAX_NEIGHBOR_MP; i++) + { + pNeighborEntry = &pAd->MeshTab.pMeshNeighborTab->NeighborMP[i]; + if (pNeighborEntry->Valid == FALSE) + continue; + + if (!NeighborMPCheck(pAd, pNeighborEntry->MeshId, + (UINT8)pNeighborEntry->PathProtocolId, + (UINT8)pNeighborEntry->PathMetricId)) + continue; + + if (MaxCPI < pNeighborEntry->CPI) + { + MaxCPI = pNeighborEntry->CPI; + pMaxCpiEntry = pNeighborEntry; + } + } + + return pMaxCpiEntry; +} + +VOID NeighborTableUpdate( + IN PRTMP_ADAPTER pAd) +{ + + INT i; + PMESH_NEIGHBOR_TAB pNeighborTab = pAd->MeshTab.pMeshNeighborTab; + PMESH_NEIGHBOR_ENTRY pNeighborEntry = NULL; + ULONG Now; + + if(pNeighborTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("pAd->MeshTab.pMeshNeighborTab equal NULL.\n")); + return; + } + + for (i = 0; i < MAX_NEIGHBOR_MP; i++) + { + pNeighborEntry = &pAd->MeshTab.pMeshNeighborTab->NeighborMP[i]; + if (pNeighborEntry->Valid == FALSE) + continue; + + NdisGetSystemUpTime(&Now); + /*if ((++pNeighborEntry->IdleCnt > NEIGHBOR_MP_IDLE_CNT)) */ + if(RTMP_TIME_AFTER(Now, pNeighborEntry->LastBeaconTime + (MESH_NEIGHBOR_BEACON_IDLE_TIME * OS_HZ / 1000) )) + { + if (MeshValid(&pAd->MeshTab) + && (pNeighborEntry->State == CANDIDATE_MP) + && (PeerLinkValidCheck(pAd, pNeighborEntry->MeshLinkIdx) == TRUE)) + { + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_CNCL, 0, NULL, pNeighborEntry->MeshLinkIdx); + } + if ( (pAd->MeshTab.UCGEnable && pNeighborEntry->Channel == pAd->MeshTab.MeshChannel) + || !pAd->MeshTab.UCGEnable) + DeleteNeighborMP(pAd, pNeighborEntry->PeerMac); + } + else + { + if (VALID_MESH_LINK_ID(pNeighborEntry->MeshLinkIdx)) + { + if ((pNeighborEntry->State == LINK_AVAILABLE) + && (pNeighborEntry->ExtChOffset != pAd->MeshTab.MeshLink[pNeighborEntry->MeshLinkIdx].Entry.ExtChOffset)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Link%d:Neighbor ExtChOffset change from %d to %d , kill the link!\n" + ,pNeighborEntry->MeshLinkIdx + ,pNeighborEntry->ExtChOffset,pAd->MeshTab.MeshLink[pNeighborEntry->MeshLinkIdx].Entry.ExtChOffset)); + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_CNCL, 0, NULL, pNeighborEntry->MeshLinkIdx); + RTMP_MLME_HANDLER(pAd); + } + } + } + + } + + return; +} + +VOID CandidateMPSelect( + IN PRTMP_ADAPTER pAd) +{ + + INT i; + PMESH_NEIGHBOR_TAB pNeighborTab = pAd->MeshTab.pMeshNeighborTab; + PMESH_NEIGHBOR_ENTRY pNeighborEntry = NULL; + + if(pNeighborTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("pAd->MeshTab.pMeshNeighborTab equal NULL.\n")); + return; + } + + if ((pAd->MeshTab.CPI == 0) + && (pNeighborTab->NeighborNr == 0)) + { + pAd->MeshTab.CPI = RandomMeshCPI(pAd); + } + else + { + + pNeighborEntry = NeighMPWithMaxCPI(pAd, pNeighborTab); + if ((pNeighborEntry != NULL) + && (pAd->MeshTab.CPI < pNeighborEntry->CPI)) + { + if (pAd->CommonCfg.Channel != pNeighborEntry->Channel) + { + pAd->MeshTab.CPI = pNeighborEntry->CPI; + /* start UCG Procedural. */ + } + } + + if (pAd->MeshTab.MeshAutoLink == FALSE) + return; + + for (i = 0; i < pNeighborTab->NeighborNr; i++) + { + pNeighborEntry = &pNeighborTab->NeighborMP[i]; + + if (!NeighborMPCheck(pAd, pNeighborEntry->MeshId, + (UINT8)pNeighborEntry->PathProtocolId, + (UINT8)pNeighborEntry->PathMetricId)) + continue; + + DBGPRINT(RT_DEBUG_TRACE, ("(%d) CPI=%d Apl=%d channel=%d state=%d\n", i, pNeighborEntry->CPI, + pNeighborEntry->MeshCapability.field.AcceptPeerLinks, pNeighborEntry->Channel, pNeighborEntry->State)); + + DBGPRINT(RT_DEBUG_TRACE, ("%d %d %d %d %d\n", + (GetMeshSecurity(pAd)==MeshCheckPeerMpCipher(pNeighborEntry->CapabilityInfo, pNeighborEntry->RSNIE, pNeighborEntry->RSNIE_Len)), + (pNeighborEntry->MeshCapability.field.AcceptPeerLinks), + (pNeighborEntry->State == NEIGHBOR_MP), MeshChCheck(pAd, pNeighborEntry), + ((pAd->MeshTab.CPI <= pNeighborEntry->CPI) + ||((pAd->MeshTab.CPI == pNeighborEntry->CPI) + && (memcmp(pNeighborEntry->PeerMac, pAd->MeshTab.CurrentAddress, MAC_ADDR_LEN) < 0))))); + + if ((GetMeshSecurity(pAd)==MeshCheckPeerMpCipher(pNeighborEntry->CapabilityInfo, pNeighborEntry->RSNIE, pNeighborEntry->RSNIE_Len)) + && (pNeighborEntry->MeshCapability.field.AcceptPeerLinks) + && (pNeighborEntry->State == NEIGHBOR_MP) + && MeshChCheck(pAd, pNeighborEntry) + && ((pAd->MeshTab.CPI <= pNeighborEntry->CPI) + ||((pAd->MeshTab.CPI == pNeighborEntry->CPI) + && (memcmp(pNeighborEntry->PeerMac, pAd->MeshTab.CurrentAddress, MAC_ADDR_LEN) < 0))) + ) + { + ULONG LinkIdx = MeshLinkAlloc(pAd, pNeighborEntry->PeerMac, MESH_LINK_DYNAMIC); + + DBGPRINT(RT_DEBUG_TRACE, ("(%d) pick LinkId=%ld\n", i, LinkIdx)); + + if (VALID_MESH_LINK_ID(LinkIdx)) + { + pAd->MeshTab.CPI = pNeighborEntry->CPI; + pNeighborEntry->State = CANDIDATE_MP; + pNeighborEntry->MeshLinkIdx = LinkIdx; + } + } + } + } + + return; +} + +void NeighborTableReset( + IN PRTMP_ADAPTER pAd) +{ + if (pAd->MeshTab.pMeshNeighborTab) + NdisZeroMemory(pAd->MeshTab.pMeshNeighborTab, sizeof(MESH_NEIGHBOR_TAB)); + else + DBGPRINT(RT_DEBUG_ERROR, ("pAd->MeshTab.pMeshNeighborTab equal NULL.\n")); + + return; +} + +void NeighborTableInit( + IN PRTMP_ADAPTER pAd) +{ +/* pAd->MeshTab.pMeshNeighborTab = kmalloc(sizeof(MESH_NEIGHBOR_TAB), GFP_ATOMIC); */ + os_alloc_mem(pAd, (UCHAR **)&(pAd->MeshTab.pMeshNeighborTab), sizeof(MESH_NEIGHBOR_TAB)); + if (pAd->MeshTab.pMeshNeighborTab) + NdisZeroMemory(pAd->MeshTab.pMeshNeighborTab, sizeof(MESH_NEIGHBOR_TAB)); + else + DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->MeshTab.pMeshNeighborTab", __FUNCTION__)); + + return; +} + +void NeighborTableDestroy( + IN PRTMP_ADAPTER pAd) +{ + if (pAd->MeshTab.pMeshNeighborTab) +/* kfree(pAd->MeshTab.pMeshNeighborTab); */ + os_free_mem(NULL, pAd->MeshTab.pMeshNeighborTab); + pAd->MeshTab.pMeshNeighborTab = NULL; + + return; +} + +VOID MeshChSwAnnounceProcess( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PHEADER_802_11 pHeader = (PHEADER_802_11)pRxBlk->pHeader; + MESH_CH_SW_ANN_MSG_STRUCT PeerChSwAnn; + PUCHAR pDA; + PUCHAR pSA; + UINT32 MeshSeq; + UINT8 MeshTTL; + PUCHAR pFrame; + ULONG FrameLen; + UINT MeshHdrLen; + ULONG LinkIdx; + UINT8 ChSwMode; + UINT8 NewCh; + UINT32 NewCPI; + UINT8 ChSwCnt; + UCHAR MeshSA[MAC_ADDR_LEN]; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> %s\n", __FUNCTION__)); + + if ((LinkIdx = GetMeshLinkId(pAd, (PCHAR)pHeader->Addr2)) == BSS_NOT_FOUND) + return; + + if (!PeerLinkValidCheck(pAd, LinkIdx)) + return; + + MeshSeq = GetMeshSeq(pRxBlk->pData); + MeshTTL = GetMeshTTL(pRxBlk->pData); + pDA = pHeader->Addr1; + pSA = GetMeshAddr4(pRxBlk->pData); + if (pSA == NULL) + pSA = pHeader->Addr2; + MeshHdrLen = GetMeshHederLen(pRxBlk->pData); + + /* skip Mesh Header */ + pRxBlk->pData += MeshHdrLen; + pRxBlk->DataSize -= MeshHdrLen; + + /* skip Category and ActionCode */ + pFrame = (PUCHAR)(pRxBlk->pData + 2); + FrameLen = pRxBlk->DataSize - 2; + + if (PktSigCheck(pAd, pHeader->Addr2, pHeader->Addr1, pSA, MeshSeq, BTYPE_MGMT) == FALSE) + return; + + MeshChannelSwitchAnnouncementSanity( pAd, + pFrame, + FrameLen, + &ChSwMode, + &NewCh, + &NewCPI, + &ChSwCnt, + MeshSA); + + PeerChSwAnn.ChSwMode = ChSwMode; + PeerChSwAnn.NewCh = NewCh; + PeerChSwAnn.NewCPI = NewCPI; + PeerChSwAnn.ChSwCnt = ChSwCnt; + PeerChSwAnn.LinkId = LinkIdx; + PeerChSwAnn.MeshSeq = MeshSeq; + PeerChSwAnn.MeshTTL = MeshTTL; + COPY_MAC_ADDR(PeerChSwAnn.MeshSA, MeshSA); + + MlmeEnqueue(pAd, MESH_CTRL_STATE_MACHINE, MESH_PEER_UCG_EVT, sizeof(MESH_CH_SW_ANN_MSG_STRUCT), &PeerChSwAnn, 0); + DBGPRINT(RT_DEBUG_TRACE, ("<----- %s\n", __FUNCTION__)); +} + +static VOID EnqueChSwAnnouncement( + IN PRTMP_ADAPTER pAd, + IN PUCHAR PeerMac, + IN UINT8 MeshTTL, + IN UINT32 MeshSeq, + IN UINT8 ChSwMode, + IN UCHAR NewCh, + IN UINT32 NewCPI, + IN UINT8 ChSwCnt, + IN PUCHAR pMeshSa) +{ + HEADER_802_11 MeshHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + MESH_FLAG MeshFlag; + + 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; + } + + MeshHeaderInit(pAd, &MeshHdr, + PeerMac, /* addr1 */ + pAd->MeshTab.CurrentAddress, /* addr2 */ + ZERO_MAC_ADDR); /* addr3 */ + NdisMoveMemory(pOutBuffer, (PCHAR)&MeshHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + /* Mesh Header */ + MeshFlag.word = 0; + MeshFlag.field.AE = 0; /* Peer-Link manager frame never carry 6 addresses. */ + InsertMeshHeader(pAd, (pOutBuffer + FrameLen), &FrameLen, MeshFlag.word, + MeshTTL, MeshSeq, NULL, NULL, NULL); + + /* Action field */ + InsertMeshActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_MESH_RES_COORDINATION, RESOURCE_CHANNEL_SWITCH_ANNOUNCEMENT); + + /* Channel Switch Announcement IE. */ + InsertMeshChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode, NewCh, NewCPI, ChSwCnt, pMeshSa); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + +/* + ======================================================================== + + Routine Description: + Prior to beginning the MSA authentication mechanism, the MP + determines if it is the Selector MP for the duration of the protocol. + The MP is the Selector MP if its MAC address is numerically larger + than that of the candidate peer MP. + + This routine shall determine if the local MP is Selector MP + + Arguments: + + Return Value: + + Note: + refer to 802.11s-D1.06 11A.4.2.2 + + ======================================================================== +*/ +void ValidateLocalMPAsSelector( + IN PRTMP_ADAPTER pAd, + IN INT idx) +{ + UCHAR i = 0; + + /* clear this flag */ + pAd->MeshTab.MeshLink[idx].Entry.bValidLocalMpAsSelector = FALSE; + + while(i < MAC_ADDR_LEN) + { + if (pAd->MeshTab.CurrentAddress[i] != pAd->MeshTab.MeshLink[idx].Entry.PeerMacAddr[i]) + { + if (pAd->MeshTab.CurrentAddress[i] > pAd->MeshTab.MeshLink[idx].Entry.PeerMacAddr[i]) + { + pAd->MeshTab.MeshLink[idx].Entry.bValidLocalMpAsSelector = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("The local MP is the Selector MP")); + } + else + { + pAd->MeshTab.MeshLink[idx].Entry.bValidLocalMpAsSelector = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("The local MP is NOT the Selector MP")); + } + + /* Initial MSAIE */ + LocalMsaIeInit(pAd, idx); + + return; + } + i++; + } + + return; +} + +/* + ======================================================================== + + Routine Description: + The MP shall perform the 802.1X role selection procedure based on + the contents of the received peer link open frame and its own + configuration. + + This routine shall determine if the local MP is Authenticator MP + + Arguments: + + Return Value: + + Note: + refer to 802.11s-D1.06 11A.4.2.2.2 + + ======================================================================== +*/ +void ValidateLocalMPAsAuthenticator( + IN PRTMP_ADAPTER pAd, + IN UCHAR idx, + IN PUCHAR pMscIe, + IN PUCHAR pMsaIe) +{ + UCHAR offset = 0; + PMESH_LINK_ENTRY pMeshLinkEntry; + PMESH_SECURITY_CAPABILITY_IE pPeerMSCIE; + PMSA_HANDSHAKE_IE pPeerMSAIE; + + pMeshLinkEntry = &pAd->MeshTab.MeshLink[idx].Entry; + pPeerMSCIE = (PMESH_SECURITY_CAPABILITY_IE)pMscIe; + pPeerMSAIE = (PMSA_HANDSHAKE_IE)pMsaIe; + + /* clear this flag */ + pMeshLinkEntry->bValidLocalMpAsAuthenticator = FALSE; + + if (pPeerMSCIE->MeshSecurityConfig.field.ConnectedToMKD == 0 && + pAd->MeshTab.LocalMSCIE.MeshSecurityConfig.field.ConnectedToMKD == 0) + { + if (pMeshLinkEntry->bValidLocalMpAsSelector) + pMeshLinkEntry->bValidLocalMpAsAuthenticator = TRUE; + } + /*If both MPs have "Connected to MKD" bit set to 1, then: */ + else if (pPeerMSCIE->MeshSecurityConfig.field.ConnectedToMKD == 1 && + pAd->MeshTab.LocalMSCIE.MeshSecurityConfig.field.ConnectedToMKD == 1) + { + if ((pPeerMSAIE->MeshHSControl.field.RequestAuth == 1 && pAd->MeshTab.bInitialMsaDone) || + (pPeerMSAIE->MeshHSControl.field.RequestAuth == 0 && !pAd->MeshTab.bInitialMsaDone)) + { + if (pMeshLinkEntry->bValidLocalMpAsSelector) + pMeshLinkEntry->bValidLocalMpAsAuthenticator = TRUE; + } + else + { + if (!pAd->MeshTab.bInitialMsaDone) + pMeshLinkEntry->bValidLocalMpAsAuthenticator = TRUE; + } + } + else + { + if (pAd->MeshTab.LocalMSCIE.MeshSecurityConfig.field.ConnectedToMKD == 1) + pMeshLinkEntry->bValidLocalMpAsAuthenticator = TRUE; + } + + offset += sizeof(MESH_HANDSHAKE_CONTROL); + + /* Once the Authenticator MP is decided, fill in MA-ID of MSAIE for local MP */ + if (pMeshLinkEntry->bValidLocalMpAsAuthenticator) + NdisMoveMemory(&pMeshLinkEntry->LocalMsaIe[offset], pAd->MeshTab.CurrentAddress, MAC_ADDR_LEN); + else + NdisMoveMemory(&pMeshLinkEntry->LocalMsaIe[offset], pMeshLinkEntry->PeerMacAddr, MAC_ADDR_LEN); + + return; +} + + +BOOLEAN MeshKeySelectionAction( + IN PRTMP_ADAPTER pAd, + IN PMESH_LINK_ENTRY pMeshLinkEntry, + IN PUCHAR pMscIe, + IN PUCHAR pPmkId, + IN UCHAR PmkIdLen) +{ + PMESH_SECURITY_CAPABILITY_IE pPeerMSCIE; + BOOLEAN bValidLocalKey = FALSE; + BOOLEAN bCachedPeerKey = FALSE; + + if (pAd->MeshTab.EasyMeshSecurity) + { + pMeshLinkEntry->MeshKeySelection = MESH_KEY_NONE; + return TRUE; + } + + pPeerMSCIE = (PMESH_SECURITY_CAPABILITY_IE)pMscIe; + + /* The key selection procedure first determines */ + /* if Initial MSA Authentication shall occur. */ + if (PmkIdLen == 0 || + pAd->MeshTab.bInitialMsaDone == FALSE || + pAd->MeshTab.PMKID_Len == 0 || + !NdisEqualMemory(pPeerMSCIE->MKDDID, pAd->MeshTab.LocalMSCIE.MKDDID, MAC_ADDR_LEN)) + { + pMeshLinkEntry->MeshKeySelection = MESH_KEY_NONE; + return TRUE; + } + + if (PmkIdLen == MESH_MAX_PMKID_LEN) + { + if (NdisEqualMemory(pMeshLinkEntry->PMK_MA_NAME, pPmkId + LEN_PMKID, MESH_PMK_NAME_LEN)) + bValidLocalKey = TRUE; + } + + if (PmkIdLen >= LEN_PMKID && pAd->MeshTab.bKeyholderDone) + { + if (NdisEqualMemory(pMeshLinkEntry->PMK_MA_NAME, pPmkId, MESH_PMK_NAME_LEN)) + bCachedPeerKey = TRUE; + } + + /* The key selection procedure, it refers to IEEE 802.11s/D1.06 Table-s46 */ + if (bValidLocalKey == FALSE && bCachedPeerKey == FALSE) + { + /* No PMK-MA available and no connection to MKD available, it shall close this link */ + if (pPeerMSCIE->MeshSecurityConfig.field.ConnectedToMKD == 0 && + pAd->MeshTab.LocalMSCIE.MeshSecurityConfig.field.ConnectedToMKD == 0) + { + return FALSE; + } + /* Local MP connected to MKD, but peer MP not */ + else if (pPeerMSCIE->MeshSecurityConfig.field.ConnectedToMKD == 0 && + pAd->MeshTab.LocalMSCIE.MeshSecurityConfig.field.ConnectedToMKD == 1) + { + pMeshLinkEntry->MeshKeySelection = MESH_KEY_PMKMA_PEER; + } + /* Peer MP connected to MKD, but local MP not */ + else if (pPeerMSCIE->MeshSecurityConfig.field.ConnectedToMKD == 1 && + pAd->MeshTab.LocalMSCIE.MeshSecurityConfig.field.ConnectedToMKD == 0) + { + pMeshLinkEntry->MeshKeySelection = MESH_KEY_PMKMA_LOCAL; + } + /* Peer and local MP both connected to MKD */ + else + { + if (pMeshLinkEntry->bValidLocalMpAsSelector) + pMeshLinkEntry->MeshKeySelection = MESH_KEY_PMKMA_PEER; + else + pMeshLinkEntry->MeshKeySelection = MESH_KEY_PMKMA_LOCAL; + } + + } + else if (bValidLocalKey == FALSE && bCachedPeerKey == TRUE) + { + pMeshLinkEntry->MeshKeySelection = MESH_KEY_PMKMA_PEER; + } + else if (bValidLocalKey == TRUE && bCachedPeerKey == FALSE) + { + pMeshLinkEntry->MeshKeySelection = MESH_KEY_PMKMA_LOCAL; + } + else + { + if (pMeshLinkEntry->bValidLocalMpAsSelector) + pMeshLinkEntry->MeshKeySelection = MESH_KEY_PMKMA_PEER; + else + pMeshLinkEntry->MeshKeySelection = MESH_KEY_PMKMA_LOCAL; + } + + return TRUE; +} + +#endif /* MESH_SUPPORT */ + diff --git a/mt7620/src/common/mesh_forwarding.c b/mt7620/src/common/mesh_forwarding.c new file mode 100644 index 0000000..002722d --- /dev/null +++ b/mt7620/src/common/mesh_forwarding.c @@ -0,0 +1,1032 @@ +/* + *************************************************************************** + * 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: + mesh_forwarding.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Arvin 2007-07-04 For mesh (802.11s) support. +*/ +#ifdef MESH_SUPPORT + + +#include "rt_config.h" +#include "mesh_def.h" + +NDIS_STATUS MeshEntryTable_Init( + IN PRTMP_ADAPTER pAd) +{ + NdisAllocateSpinLock(pAd, &pAd->MeshTab.MeshEntryTabLock); + + pAd->MeshTab.pMeshEntryTab = vmalloc(sizeof(MESH_ENTRY_TABLE)); + + if (pAd->MeshTab.pMeshEntryTab) + NdisZeroMemory(pAd->MeshTab.pMeshEntryTab, sizeof(MESH_ENTRY_TABLE)); + else + DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->MeshTab.pMeshEntryTab", __FUNCTION__)); + + return TRUE; +} + +NDIS_STATUS MeshEntryTable_Exit( + IN PRTMP_ADAPTER pAd) +{ + INT i; + MESH_ENTRY *pMeshEntry; + PMESH_ENTRY_TABLE pEntryTab = pAd->MeshTab.pMeshEntryTab; + + if (pEntryTab) + { + if (pEntryTab->Size == 0) + { + vfree(pEntryTab); + pEntryTab = NULL; + return TRUE; + } + } + else + { + return TRUE; + } + + + for (i=0; i < HASH_TABLE_SIZE; i++) + { + while((pMeshEntry = pEntryTab->Hash[i]) != NULL) + { + BOOLEAN Cancelled; + + if (pMeshEntry->PathReq) + { + RTMPCancelTimer(&pMeshEntry->PathReq->PathReqTimer, &Cancelled); +/* kfree((PUCHAR)pMeshEntry->PathReq); */ + os_free_mem(NULL, pMeshEntry->PathReq); + pMeshEntry->PathReq = NULL; + } + + pEntryTab->Hash[i] = pMeshEntry->pNext; +/* kfree((PUCHAR)pMeshEntry); */ + os_free_mem(NULL, pMeshEntry); + } + } + + vfree(pEntryTab); + pEntryTab = NULL; + + NdisFreeSpinLock(&pAd->MeshTab.MeshEntryTabLock); + + return TRUE; +} + +PMESH_ENTRY MeshEntryTableLookUp( + IN PRTMP_ADAPTER pAd, + IN PUCHAR DestAddr) +{ + UINT HashIdx; + PMESH_ENTRY pEntry = NULL; + PMESH_ENTRY_TABLE pEntryTab = pAd->MeshTab.pMeshEntryTab; + + + if (pEntryTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Entry Table doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + RTMP_SEM_LOCK(&pAd->MeshTab.MeshEntryTabLock); + + HashIdx = MAC_ADDR_HASH_INDEX(DestAddr); + pEntry = pEntryTab->Hash[HashIdx]; + + while (pEntry) + { + if (MAC_ADDR_EQUAL(pEntry->DestAddr, DestAddr)) + break; + else + pEntry = pEntry->pNext; + } + + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshEntryTabLock); + + + return pEntry; +} + +PMESH_ENTRY MeshEntryTableInsert( + IN PRTMP_ADAPTER pAd, + IN PUCHAR DestAddr, + IN UCHAR Idx) +{ + UINT HashIdx; + MESH_ENTRY *pNewEntry =NULL, *pCurrEntry; + PMESH_ENTRY_TABLE pEntryTab = pAd->MeshTab.pMeshEntryTab; + + + if (pEntryTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Entry Table doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + if (MAC_ADDR_EQUAL(ZERO_MAC_ADDR, DestAddr)) + return NULL; + + if (pEntryTab->Size > MAX_HASH_ENTRY_TAB_SIZE) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Entry Table size more than 256 .\n", __FUNCTION__)); + return NULL; + } + + RTMP_SEM_LOCK(&pAd->MeshTab.MeshEntryTabLock); + + HashIdx = MAC_ADDR_HASH_INDEX(DestAddr); + +/* pNewEntry = (PMESH_ENTRY) kmalloc(sizeof(MESH_ENTRY), MEM_ALLOC_FLAG); */ + os_alloc_mem(NULL, (UCHAR **)&pNewEntry, sizeof(MESH_ENTRY)); + + if (pNewEntry) + { + NdisZeroMemory(pNewEntry, sizeof(MESH_ENTRY)); + + pNewEntry->Idx = Idx; + COPY_MAC_ADDR(pNewEntry->DestAddr, DestAddr); + pNewEntry->pNext = NULL; + + if (pEntryTab->Hash[HashIdx] == NULL) + { /* Hash list is empty, directly assign it. */ + pEntryTab->Hash[HashIdx] = pNewEntry; + } + else + { + /* Ok, we insert the new entry into the Hash[HashIdx] */ + pCurrEntry = pEntryTab->Hash[HashIdx]; + while (pCurrEntry->pNext != NULL) + pCurrEntry = pCurrEntry->pNext; + pCurrEntry->pNext = pNewEntry; + } + pEntryTab->Size++; + } + + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshEntryTabLock); + + + return pNewEntry; +} + +BOOLEAN MeshEntryTableDelete( + IN PRTMP_ADAPTER pAd, + IN PUCHAR DestAddr) +{ + UINT HashIdx; + MESH_ENTRY *pEntry = NULL, *pPrev = NULL; + PMESH_ENTRY_TABLE pEntryTab = pAd->MeshTab.pMeshEntryTab; + + + if (pEntryTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Entry Table doesn't exist.\n", __FUNCTION__)); + return FALSE; + } + + RTMP_SEM_LOCK(&pAd->MeshTab.MeshEntryTabLock); + + HashIdx = MAC_ADDR_HASH_INDEX(DestAddr); + pEntry = pPrev = pEntryTab->Hash[HashIdx]; + + while (pEntry) + { + /* Find the existed Mapping entry */ + if (MAC_ADDR_EQUAL(pEntry->DestAddr, DestAddr)) + { + if (pEntry->PathReq) + { + BOOLEAN Cancelled; + + RTMPCancelTimer(&pEntry->PathReq->PathReqTimer, &Cancelled); + +/* kfree((PUCHAR)pEntry->PathReq); */ + os_free_mem(NULL, pEntry->PathReq); + pEntry->PathReq = NULL; + } + pEntry->PathReqTimerRunning = FALSE; + + if (pPrev == pEntry) + pEntryTab->Hash[HashIdx] = pEntry->pNext; + else + pPrev->pNext = pEntry->pNext; + + break; + } + else + { + pPrev = pEntry; + pEntry = pEntry->pNext; + } + } + + /*remove this entry from Hash list. */ + if (pEntry) + { + pEntryTab->Size--; +/* kfree((PUCHAR)pEntry); */ + os_free_mem(NULL, pEntry); + } + + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshEntryTabLock); + + + return TRUE; +} + +PMESH_ENTRY MeshEntryTableUpdate( + IN PRTMP_ADAPTER pAd, + IN PUCHAR DestAddr, + IN UCHAR Idx) +{ + UINT HashIdx; + MESH_ENTRY *pEntry = NULL; + PMESH_ENTRY_TABLE pEntryTab = pAd->MeshTab.pMeshEntryTab; + + + if (pEntryTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Entry Table doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + RTMP_SEM_LOCK(&pAd->MeshTab.MeshEntryTabLock); + + HashIdx = MAC_ADDR_HASH_INDEX(DestAddr); + pEntry = pEntryTab->Hash[HashIdx]; + + while (pEntry) + { + /* Find the existed Mapping entry */ + if (MAC_ADDR_EQUAL(pEntry->DestAddr, DestAddr)) + { + pEntry->Idx = Idx; + COPY_MAC_ADDR(pEntry->DestAddr, DestAddr); + break; + } + else + { + pEntry = pEntry->pNext; + } + } + + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshEntryTabLock); + + + return pEntry; +} + +VOID +MeshEntryTableGet( + IN PRTMP_ADAPTER pAd) +{ + INT i; + MESH_ENTRY *pEntry = NULL; + PMESH_ENTRY_TABLE pEntryTab = pAd->MeshTab.pMeshEntryTab; + + if (pEntryTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Entry Table doesn't exist.\n", __FUNCTION__)); + return; + } + + RTMP_SEM_LOCK(&pAd->MeshTab.MeshEntryTabLock); + + for (i=0; i < HASH_TABLE_SIZE; i++) + { + pEntry = pEntryTab->Hash[i]; + while(pEntry != NULL) + { + DBGPRINT(RT_DEBUG_OFF, ("%02X:%02X:%02X:%02X:%02X:%02X ", + pEntry->DestAddr[0], pEntry->DestAddr[1], pEntry->DestAddr[2], + pEntry->DestAddr[3], pEntry->DestAddr[4], pEntry->DestAddr[5])); + DBGPRINT(RT_DEBUG_OFF, ("%-10d\n", (int)pEntry->Idx)); + pEntry = pEntry->pNext; + } + } + + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshEntryTabLock); +} + +NDIS_STATUS MeshProxyEntryTable_Init( + IN PRTMP_ADAPTER pAd) +{ + + NdisAllocateSpinLock(pAd, &pAd->MeshTab.MeshProxyTabLock); + + pAd->MeshTab.pMeshProxyTab = vmalloc(sizeof(MESH_PROXY_ENTRY_TABLE)); + + if (pAd->MeshTab.pMeshProxyTab) + { + PMESH_PROXY_ENTRY_TABLE pMeshProxyTab=pAd->MeshTab.pMeshProxyTab; + int i; + + NdisZeroMemory(pAd->MeshTab.pMeshProxyTab, sizeof(MESH_PROXY_ENTRY_TABLE)); + + pMeshProxyTab->AgeList.Head=-1; + pMeshProxyTab->AgeList.Tail=-1; + pMeshProxyTab->AgeList.Number=0; + + pMeshProxyTab->FreeEntryList.Head=-1; + pMeshProxyTab->FreeEntryList.Tail=-1; + pMeshProxyTab->FreeEntryList.Number=0; + + pMeshProxyTab->Size=0; + for (i=0;iHash[i]=-1; + + for (i=0;iContent[i]; + pProxyEnrtry->DLNext=-1; + pProxyEnrtry->DLPrev=-1; + pProxyEnrtry->Next=-1; + SignalLinkListInsertHeadQueue(pAd->MeshTab.pMeshProxyTab->Content, &pAd->MeshTab.pMeshProxyTab->FreeEntryList, i); + } + + + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->MeshTab.pMeshProxyTab", __FUNCTION__)); + + return TRUE; +} + +NDIS_STATUS MeshProxyEntryTable_Exit( + IN PRTMP_ADAPTER pAd) +{ + + if (pAd->MeshTab.pMeshProxyTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Proxy Table doesn't exist.\n", __FUNCTION__)); + return TRUE; + } + + if (pAd->MeshTab.pMeshProxyTab) + { + vfree(pAd->MeshTab.pMeshProxyTab); + pAd->MeshTab.pMeshProxyTab = NULL; + return TRUE; + } + + NdisFreeSpinLock(&pAd->MeshTab.MeshProxyTabLock); + + return TRUE; +} + +PMESH_PROXY_ENTRY MeshProxyEntryTableLookUp( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSA) +{ + UINT HashIdx; + SHORT EntryIndex; + PMESH_PROXY_ENTRY pEntry = NULL; + PMESH_PROXY_ENTRY_TABLE pProxyTab = pAd->MeshTab.pMeshProxyTab; + + + if (pProxyTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Proxy Table doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + if ( !(pAd->MeshTab.OpMode & MESH_AP) && !(pAd->MeshTab.OpMode & MESH_POTAL)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Proxy does not enable!\n", __FUNCTION__)); + return NULL; + } + + RTMP_SEM_LOCK(&pAd->MeshTab.MeshProxyTabLock); + + /*find entry first */ + HashIdx = MAC_ADDR_HASH_INDEX(pSA); + EntryIndex=pProxyTab->Hash[HashIdx]; + + while (EntryIndex!=-1) + { + if (MAC_ADDR_EQUAL(pProxyTab->Content[EntryIndex].MacAddr, pSA)) + { + pEntry=&pProxyTab->Content[EntryIndex]; + break; + } + + EntryIndex=pProxyTab->Content[EntryIndex].Next; + } + + /*refresh age time */ + if (EntryIndex!=-1) + { + DoubleLinkListRemoveNode(pProxyTab->Content, &pProxyTab->AgeList, EntryIndex); + DoubleLinkListInsertTailQueue(pProxyTab->Content, &pProxyTab->AgeList, EntryIndex); + } + + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshProxyTabLock); + + + return pEntry; +} + +PMESH_PROXY_ENTRY MeshProxyEntryTableInsert( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMeshSA, + IN PUCHAR pSA) +{ + ULONG Now; + UINT HashIdx; + SHORT NewEntryIndex =-1, CurrEntryIndex=-1; + MESH_PROXY_ENTRY *pNewEntry =NULL, *pCurrEntry; + PMESH_PROXY_ENTRY_TABLE pProxyTab = pAd->MeshTab.pMeshProxyTab; + + + if (pProxyTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Proxy Table doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + if ( !(pAd->MeshTab.OpMode & MESH_AP) && !(pAd->MeshTab.OpMode & MESH_POTAL)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Proxy does not enable!\n", __FUNCTION__)); + return NULL; + } + + if (GetMeshLinkId(pAd, (PCHAR)pSA) != BSS_NOT_FOUND) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: The address are neighbor peer mesh link .\n", __FUNCTION__)); + return NULL; + } + + if (MAC_ADDR_EQUAL(ZERO_MAC_ADDR, pSA)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Receive Zero MAC Address .\n", __FUNCTION__)); + return NULL; + } + + RTMP_SEM_LOCK(&pAd->MeshTab.MeshProxyTabLock); + + /* get free entry */ + /* if the table is full , we use the oldest entry */ + NewEntryIndex=SignalLinkListRemoveFromHeadQueue(pProxyTab->Content, &pProxyTab->FreeEntryList); + + if (NewEntryIndex==-1) + { + SHORT PrevEntryIndex=-1; + NewEntryIndex=DoubleLinkListRemoveHeadQueue(pProxyTab->Content, &pProxyTab->AgeList); + + if (NewEntryIndex==-1) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Bug when remove doublelinkheadqueue .\n", __FUNCTION__)); + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshProxyTabLock); + return NULL; + } + + /*remove from hash list */ + HashIdx=MAC_ADDR_HASH_INDEX(pProxyTab->Content[NewEntryIndex].MacAddr); + CurrEntryIndex=pProxyTab->Hash[HashIdx]; + + RTMP_GetCurrentSystemTick(&Now); + if (RTMP_TIME_AFTER(Now,pProxyTab->Content[NewEntryIndex].LastUpdateTime+MESH_PROXY_AGEOUT)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Proxy table is full , Age Out Proxy Entry: Index:%d HashIdx:%d\n",NewEntryIndex,HashIdx)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Age Out Expired Proxy Entry: Index:%d HashIdx:%d\n",NewEntryIndex,HashIdx)); + } + + while(CurrEntryIndex!=-1 && CurrEntryIndex!=NewEntryIndex) + { + PrevEntryIndex=CurrEntryIndex; + CurrEntryIndex=pProxyTab->Content[CurrEntryIndex].Next; + } + + if (CurrEntryIndex==NewEntryIndex) + { + if (PrevEntryIndex==-1) + pProxyTab->Hash[HashIdx]=pProxyTab->Content[NewEntryIndex].Next; + else + pProxyTab->Content[PrevEntryIndex].Next=pProxyTab->Content[NewEntryIndex].Next; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("BUG in MeshProxyEntry Table %d \n",CurrEntryIndex)); + Set_MeshProxyInfo_Display_Proc(pAd, ""); + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshProxyTabLock); + return NULL; + } + /* remove from hash list end */ + } + + pNewEntry=&pProxyTab->Content[NewEntryIndex]; + pNewEntry->DLNext=-1; + pNewEntry->DLPrev=-1; + pNewEntry->Next=-1; + pNewEntry->isMesh=FALSE; + pNewEntry->isProxied=FALSE; + + RTMP_GetCurrentSystemTick(&Now); + pNewEntry->LastUpdateTime=Now; + + HashIdx = MAC_ADDR_HASH_INDEX(pSA); + COPY_MAC_ADDR(pNewEntry->MacAddr, pSA); + DBGPRINT(RT_DEBUG_TRACE, ("Proxy Entry = (%02x:%02x:%02x:%02x:%02x:%02x) !!!\n", + pNewEntry->MacAddr[0], pNewEntry->MacAddr[1], pNewEntry->MacAddr[2], + pNewEntry->MacAddr[3], pNewEntry->MacAddr[4], pNewEntry->MacAddr[5])); + if (MacTableLookup(pAd, pSA)) + pNewEntry->isMesh = TRUE; + else + pNewEntry->isMesh = FALSE; + pNewEntry->isProxied = TRUE; + COPY_MAC_ADDR(pNewEntry->Owner, pMeshSA); + + /*insert to hash list */ + if (pProxyTab->Hash[HashIdx] == -1) + { /* Hash list is empty, directly assign it. */ + pProxyTab->Hash[HashIdx] = NewEntryIndex; + pNewEntry->Next=-1; + } + else + { + /* Ok, we insert the new entry into the Hash[HashIdx] */ + CurrEntryIndex=pProxyTab->Hash[HashIdx]; + pCurrEntry=&pProxyTab->Content[CurrEntryIndex]; + + pProxyTab->Hash[HashIdx]=NewEntryIndex; + pNewEntry->Next=CurrEntryIndex; + } + /*insert to hash list end */ + + /*insert to age out list */ + DoubleLinkListInsertTailQueue(pProxyTab->Content, &pProxyTab->AgeList, NewEntryIndex); + + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshProxyTabLock); + return pNewEntry; +} + +BOOLEAN MeshProxyEntryTableDelete( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSA) +{ + UINT HashIdx; + SHORT EntryIndex,CurrEntryIndex,PrevEntryIndex=-1; + PMESH_PROXY_ENTRY pEntry = NULL; + PMESH_PROXY_ENTRY_TABLE pProxyTab = pAd->MeshTab.pMeshProxyTab; + + + if (pProxyTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Proxy Table doesn't exist.\n", __FUNCTION__)); + return FALSE; + } + + RTMP_SEM_LOCK(&pAd->MeshTab.MeshProxyTabLock); + + /*find the entry first */ + HashIdx = MAC_ADDR_HASH_INDEX(pSA); + EntryIndex=pProxyTab->Hash[HashIdx]; + + while (EntryIndex!=-1) + { + if (MAC_ADDR_EQUAL(pProxyTab->Content[EntryIndex].MacAddr, pSA)) + { + pEntry=&pProxyTab->Content[EntryIndex]; + break; + } + EntryIndex=pProxyTab->Content[EntryIndex].Next; + } + + if (EntryIndex==-1) + { + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshProxyTabLock); + return FALSE; + } + + /*remove from hash list */ + CurrEntryIndex=pProxyTab->Hash[HashIdx]; + + while(CurrEntryIndex!=-1 && CurrEntryIndex!=EntryIndex) + { + PrevEntryIndex=CurrEntryIndex; + CurrEntryIndex=pProxyTab->Content[CurrEntryIndex].Next; + } + + if (CurrEntryIndex==EntryIndex) + { + if (PrevEntryIndex==-1) + pProxyTab->Hash[HashIdx]=pProxyTab->Content[EntryIndex].Next; + else + pProxyTab->Content[PrevEntryIndex].Next=pProxyTab->Content[EntryIndex].Next; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("BUG in MeshProxyEntry Table %d \n",CurrEntryIndex)); + Set_MeshProxyInfo_Display_Proc(pAd, ""); + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshProxyTabLock); + return FALSE; + } + + DoubleLinkListRemoveNode(pProxyTab->Content, &pProxyTab->AgeList, EntryIndex); + SignalLinkListInsertHeadQueue(pProxyTab->Content, &pProxyTab->FreeEntryList, EntryIndex); + + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshProxyTabLock); + + + return TRUE; +} + +PMESH_PROXY_ENTRY MeshProxyEntryTableUpdate( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMeshSA, + IN PUCHAR pSA) +{ + UINT HashIdx; + SHORT EntryIndex; + MESH_PROXY_ENTRY *pEntry = NULL; + PMESH_PROXY_ENTRY_TABLE pProxyTab = pAd->MeshTab.pMeshProxyTab; + + + if (pProxyTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Proxy Table doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + if (MAC_ADDR_EQUAL(ZERO_MAC_ADDR, pSA)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Receive Zero MAC Address .\n", __FUNCTION__)); + return NULL; + } + + RTMP_SEM_LOCK(&pAd->MeshTab.MeshProxyTabLock); + + HashIdx = MAC_ADDR_HASH_INDEX(pSA); + EntryIndex=pProxyTab->Hash[HashIdx]; + + while (EntryIndex!=-1) + { + if (MAC_ADDR_EQUAL(pProxyTab->Content[EntryIndex].MacAddr, pSA)) + { + pEntry=&pProxyTab->Content[EntryIndex]; + break; + } + + EntryIndex=pProxyTab->Content[EntryIndex].Next; + } + + if (EntryIndex!=-1) + { + COPY_MAC_ADDR(pProxyTab->Content[EntryIndex].Owner, pMeshSA); + DoubleLinkListRemoveNode(pProxyTab->Content, &pProxyTab->AgeList, EntryIndex); + DoubleLinkListInsertTailQueue(pProxyTab->Content, &pProxyTab->AgeList, EntryIndex); + } + + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshProxyTabLock); + + + return pEntry; +} + +NDIS_STATUS MeshRoutingTable_Init( + IN PRTMP_ADAPTER pAd) +{ + NdisAllocateSpinLock(pAd, &pAd->MeshTab.MeshRouteTabLock); + + pAd->MeshTab.pMeshRouteTab = vmalloc(sizeof(MESH_ROUTING_TABLE)); + + if (pAd->MeshTab.pMeshRouteTab) + NdisZeroMemory(pAd->MeshTab.pMeshRouteTab, sizeof(MESH_ROUTING_TABLE)); + else + DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->MeshTab.pMeshRouteTab", __FUNCTION__)); + + return TRUE; +} + +NDIS_STATUS MeshRoutingTable_Exit( + IN PRTMP_ADAPTER pAd) +{ + NdisFreeSpinLock(&pAd->MeshTab.MeshRouteTabLock); + + if (pAd->MeshTab.pMeshRouteTab) + vfree(pAd->MeshTab.pMeshRouteTab); + pAd->MeshTab.pMeshRouteTab = NULL; + + return TRUE; +} + +PMESH_ROUTING_ENTRY MeshRoutingTableLookup( + IN PRTMP_ADAPTER pAd, + IN PUCHAR MeshDA) +{ + ULONG HashIdx; + PMESH_ROUTING_ENTRY pEntry = NULL; + PMESH_ROUTING_TABLE pRouteTab = pAd->MeshTab.pMeshRouteTab; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> MeshRoutingTableLookup\n")); + + if (pRouteTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Route Table doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + RTMP_SEM_LOCK(&pAd->MeshTab.MeshRouteTabLock); + + HashIdx = MAC_ADDR_HASH_INDEX(MeshDA); + pEntry = pRouteTab->Hash[HashIdx]; + + while (pEntry) + { + if (MAC_ADDR_EQUAL(pEntry->MeshDA, MeshDA)) + { + break; + } + else + pEntry = pEntry->pNext; + } + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshRouteTabLock); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- MeshRoutingTableLookup\n")); + return pEntry; +} + +PMESH_ROUTING_ENTRY MeshRoutingTableInsert( + IN PRTMP_ADAPTER pAd, + IN PUCHAR MeshDestAddr, + IN UINT32 Dsn, + IN PUCHAR NextHop, + IN UCHAR NextHopLinkID, + IN UINT32 Metric) +{ + UCHAR i, HashIdx; + MESH_ROUTING_ENTRY *pEntry = NULL, *pCurrEntry; + PMESH_ROUTING_TABLE pRouteTab = pAd->MeshTab.pMeshRouteTab; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> MeshRoutingTableInsert\n")); + + if (pRouteTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Route Table doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + /* if FULL, return */ + if (pRouteTab->Size >= MAX_ROUTE_TAB_SIZE) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Route Table size > %d.\n", __FUNCTION__, MAX_ROUTE_TAB_SIZE)); + return NULL; + } + + if((pEntry = MeshRoutingTableLookup(pAd, MeshDestAddr)) != NULL) + return pEntry; + + /* allocate one Mesh entry */ + RTMP_SEM_LOCK(&pAd->MeshTab.MeshRouteTabLock); + + for (i = 0; i< MAX_ROUTE_TAB_SIZE; i++) + { + if (pRouteTab->Content[i].Valid == FALSE) + { + pEntry = &pRouteTab->Content[i]; + NdisZeroMemory(pEntry, sizeof(MESH_ROUTING_ENTRY)); + pEntry->Valid = TRUE; + COPY_MAC_ADDR(pEntry->MeshDA, MeshDestAddr); + pEntry->Dsn = Dsn; + COPY_MAC_ADDR(pEntry->NextHop, NextHop); + pEntry->NextHopLinkID = NextHopLinkID; + pEntry->PathMetric = Metric; + pEntry->LifeTime = HWMP_FORWARD_TABLE_LIFE_TIME; + pEntry->Idx = i; + pRouteTab->Size ++; + break; + } + } + + /* add this MAC entry into HASH table */ + if (pEntry) + { + HashIdx = MAC_ADDR_HASH_INDEX(MeshDestAddr); + if (pRouteTab->Hash[HashIdx] == NULL) + { + pRouteTab->Hash[HashIdx] = pEntry; + } + else + { + pCurrEntry = pRouteTab->Hash[HashIdx]; + while (pCurrEntry->pNext != NULL) + pCurrEntry = pCurrEntry->pNext; + pCurrEntry->pNext = pEntry; + } + + } + + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshRouteTabLock); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- MeshRoutingTableInsert\n")); + return pEntry; +} + +BOOLEAN MeshRoutingTableDelete( + IN PRTMP_ADAPTER pAd, + IN PUCHAR MeshDA) +{ + USHORT HashIdx, i; + MESH_ROUTING_ENTRY *pEntry = NULL, *pPrevEntry, *pProbeEntry; + MESH_ENTRY *pMeshPrevEntry, *pMeshProbeEntry; + PMESH_ROUTING_TABLE pRouteTab = pAd->MeshTab.pMeshRouteTab; + PMESH_ENTRY_TABLE pEntryTab = pAd->MeshTab.pMeshEntryTab; + + + if (pRouteTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Route Table doesn't exist.\n", __FUNCTION__)); + return FALSE; + } + + if (pEntryTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Entry Table doesn't exist.\n", __FUNCTION__)); + return FALSE; + } + + RTMP_SEM_LOCK(&pAd->MeshTab.MeshRouteTabLock); + + for (i = 0; i< MAX_ROUTE_TAB_SIZE; i++) + { + pEntry = &pRouteTab->Content[i]; + + if (pEntry->Valid == TRUE) + { + if (MAC_ADDR_EQUAL(pEntry->MeshDA, MeshDA)) + break; + } + } + + if (i == MAX_ROUTE_TAB_SIZE) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: The Mesh Route Entry doesn't exist.\n", __FUNCTION__)); + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshRouteTabLock); + return FALSE; + } + + HashIdx = MAC_ADDR_HASH_INDEX(MeshDA); + + pPrevEntry = NULL; + pProbeEntry = pRouteTab->Hash[HashIdx]; + + ASSERT(pProbeEntry); + + /* update Hash list */ + do + { + if (pProbeEntry == pEntry) + { + if (pPrevEntry == NULL) + { + pRouteTab->Hash[HashIdx] = pEntry->pNext; + } + else + { + pPrevEntry->pNext = pEntry->pNext; + } + break; + } + + pPrevEntry = pProbeEntry; + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + + RTMP_SEM_LOCK(&pAd->MeshTab.MeshEntryTabLock); + /* delete entry table mapping to the route idx */ + for (i=0; i < MAX_HASH_ENTRY_TAB_SIZE; i++) + { + if (pEntryTab->Hash[i] != NULL) + { + pMeshPrevEntry = NULL; + pMeshProbeEntry = pEntryTab->Hash[i]; + + do + { + if (pEntry->Idx == pMeshProbeEntry->Idx) + { + if (pMeshProbeEntry->PathReq) + { + BOOLEAN Cancelled; + + RTMPCancelTimer(&pMeshProbeEntry->PathReq->PathReqTimer, &Cancelled); + +/* kfree((PUCHAR)pMeshProbeEntry->PathReq); */ + os_free_mem(NULL, pMeshProbeEntry->PathReq); + pMeshProbeEntry->PathReq = NULL; + } + pMeshProbeEntry->PathReqTimerRunning = FALSE; + + if (pMeshPrevEntry == NULL) + pEntryTab->Hash[i] = pMeshProbeEntry->pNext; + else + pMeshPrevEntry->pNext = pMeshProbeEntry->pNext; + +/* kfree((PUCHAR)pMeshProbeEntry); */ + os_free_mem(NULL, pMeshProbeEntry); + pEntryTab->Size--; + break; + } + + pMeshPrevEntry = pMeshProbeEntry; + pMeshProbeEntry = pMeshProbeEntry->pNext; + } while (pMeshProbeEntry); + } + } + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshEntryTabLock); + + NdisZeroMemory(pEntry, sizeof(MESH_ROUTING_ENTRY)); + pRouteTab->Size--; + + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshRouteTabLock); + + + return TRUE; +} + +PMESH_ROUTING_ENTRY MeshRoutingTableUpdate( + IN PRTMP_ADAPTER pAd, + IN PUCHAR MeshDestAddr, + IN UINT32 Dsn, + IN PUCHAR NextHop, + IN UCHAR NextHopLinkID, + IN UINT32 Metric) +{ + MESH_ROUTING_ENTRY *pEntry = NULL; + + + if((pEntry = MeshRoutingTableLookup(pAd, MeshDestAddr)) == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: The Mesh Route Entry doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + RTMP_SEM_LOCK(&pAd->MeshTab.MeshRouteTabLock); + + pEntry->Valid = TRUE; + COPY_MAC_ADDR(pEntry->MeshDA, MeshDestAddr); + pEntry->Dsn = Dsn; + COPY_MAC_ADDR(pEntry->NextHop, NextHop); + pEntry->NextHopLinkID = NextHopLinkID; + pEntry->PathMetric = Metric; + pEntry->LifeTime = HWMP_FORWARD_TABLE_LIFE_TIME; + + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshRouteTabLock); + + + return pEntry; +} + +PMESH_ROUTING_ENTRY MeshRoutingTablePrecursorUpdate( + IN PRTMP_ADAPTER pAd, + IN PUCHAR MeshDestAddr, + IN PUCHAR Precursor) +{ + MESH_ROUTING_ENTRY *pEntry = NULL; + + if((pEntry = MeshRoutingTableLookup(pAd, MeshDestAddr)) == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("Can't find the route entry !\n")); + return NULL; + } + + RTMP_SEM_LOCK(&pAd->MeshTab.MeshRouteTabLock); + + if (pEntry->Valid == TRUE) + { + COPY_MAC_ADDR(pEntry->Precursor, Precursor); + pEntry->bPrecursor = TRUE; + } + + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshRouteTabLock); + + return pEntry; +} + +#endif /* MESH_SUPPORT */ + diff --git a/mt7620/src/common/mesh_inf.c b/mt7620/src/common/mesh_inf.c new file mode 100644 index 0000000..fd06ecd --- /dev/null +++ b/mt7620/src/common/mesh_inf.c @@ -0,0 +1,280 @@ +/* + *************************************************************************** + * 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: + mesh.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi 2007-06-25 For mesh (802.11s) support. +*/ +#define RTMP_MODULE_OS + +#ifdef MESH_SUPPORT + + +/*#include "rt_config.h" */ +/*#include "mesh_sanity.h" */ +#include "rtmp_comm.h" +#include "rt_os_util.h" +#include "rt_os_net.h" + +/*static VOID MeshCfgInit( */ +/* IN PRTMP_ADAPTER pAd, */ +/* IN PSTRING pHostName); */ + + +/* +======================================================================== +Routine Description: + Init Mesh function. + +Arguments: + ad_p 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 RTMP_Mesh_Init( + IN VOID *pAd, + IN PNET_DEV main_dev_p, + IN PSTRING pHostName) +{ + RTMP_OS_NETDEV_OP_HOOK netDevOpHook; + ULONG OpMode; + + + /* init operation functions */ + NdisZeroMemory((PUCHAR)&netDevOpHook, sizeof(RTMP_OS_NETDEV_OP_HOOK)); + netDevOpHook.open = Mesh_VirtualIF_Open; + netDevOpHook.stop = Mesh_VirtualIF_Close; + netDevOpHook.xmit = Mesh_VirtualIF_PacketSend; + netDevOpHook.ioctl = Mesh_VirtualIF_Ioctl; + + /* init operation functions */ + RTMP_DRIVER_OP_MODE_GET(pAd, &OpMode); + +#ifdef CONFIG_STA_SUPPORT +#if WIRELESS_EXT >= 12 + if (OpMode == OPMODE_STA) + { + netDevOpHook.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) + { + netDevOpHook.iw_handler = &rt28xx_ap_iw_handler_def; + } +#endif /*WIRELESS_EXT >= 12 */ +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ + + RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_MESH_INIT, + 0, &netDevOpHook, 0); + + + +} /* End of RTMP_Mesh_Init */ + + +/* +======================================================================== +Routine Description: + Open a virtual network interface. + +Arguments: + pDev which WLAN network interface + +Return Value: + 0: open successfully + otherwise: open fail + +Note: +======================================================================== +*/ +INT Mesh_VirtualIF_Open( + IN PNET_DEV pDev) +{ + VOID *pAd; + + pAd = RTMP_OS_NETDEV_GET_PRIV(pDev); + ASSERT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: ===> %s\n", __FUNCTION__, RTMP_OS_NETDEV_GET_DEVNAME(pDev))); + + + if (RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_MESH_OPEN_PRE, 0, + pDev, 0) != NDIS_STATUS_SUCCESS) + return -1; + + if (VIRTUAL_IF_UP(pAd) != 0) + return -1; + + /* increase MODULE use count */ + RT_MOD_INC_USE_COUNT(); + + RTMP_OS_NETDEV_START_QUEUE(pDev); + + if (RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_MESH_OPEN_POST, 0, + pDev, 0) != NDIS_STATUS_SUCCESS) + return -1; + + + DBGPRINT(RT_DEBUG_TRACE, ("%s: <=== %s\n", __FUNCTION__, RTMP_OS_NETDEV_GET_DEVNAME(pDev))); + + 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 Mesh_VirtualIF_Close( + IN PNET_DEV pDev) +{ + VOID *pAd; + + pAd = RTMP_OS_NETDEV_GET_PRIV(pDev); + ASSERT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: ===> %s\n", __FUNCTION__, RTMP_OS_NETDEV_GET_DEVNAME(pDev))); + + + /* stop mesh. */ + RTMP_OS_NETDEV_STOP_QUEUE(pDev); + + RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_MESH_CLOSE, 0, pDev, 0); + + + VIRTUAL_IF_DOWN(pAd); + + RT_MOD_DEC_USE_COUNT(); + + return 0; +} + + +/* +======================================================================== +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 Mesh_VirtualIF_PacketSend( + IN PNDIS_PACKET pPktSrc, + IN PNET_DEV pDev) +{ + + MEM_DBG_PKT_ALLOC_INC(pPktSrc); + + if(!(RTMP_OS_NETDEV_STATE_RUNNING(pDev))) + { + /* the interface is down */ + RELEASE_NDIS_PACKET(NULL, pPktSrc, NDIS_STATUS_FAILURE); + return 0; + } + + return MESH_PacketSend(pPktSrc, pDev, rt28xx_packet_xmit); + + +} /* End of Mesh_VirtualIF_PacketSend */ + + +/* +======================================================================== +Routine Description: + IOCTL to WLAN. + +Arguments: + dev_p which WLAN network interface + rq_p command information + cmd command ID + +Return Value: + 0: IOCTL successfully + otherwise: IOCTL fail + +Note: + SIOCETHTOOL 8946 New drivers use this ETHTOOL interface to + report link failure activity. +======================================================================== +*/ +INT Mesh_VirtualIF_Ioctl( + IN PNET_DEV dev_p, + IN OUT VOID *rq_p, + IN INT cmd) +{ +/* if (dev_p->priv_flags == INT_MESH) */ + return rt28xx_ioctl(dev_p, rq_p, cmd); +/* else */ +/* return -1; */ +} /* End of Mesh_VirtualIF_Ioctl */ + + + +#ifdef LINUX +#if (WIRELESS_EXT >= 12) +struct iw_statistics *Mesh_VirtualIF_get_wireless_stats( + IN struct net_device *net_dev); +#endif +#endif /* LINUX */ + + +VOID RTMP_Mesh_Remove( + IN VOID *pAd) +{ + + RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_MESH_REMOVE, 0, NULL, 0); + +} /* End of RTMP_Mesh_Remove */ + + +#endif /* MESH_SUPPORT */ diff --git a/mt7620/src/common/mesh_link_mng.c b/mt7620/src/common/mesh_link_mng.c new file mode 100644 index 0000000..8761d54 --- /dev/null +++ b/mt7620/src/common/mesh_link_mng.c @@ -0,0 +1,2779 @@ +/* + *************************************************************************** + * 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: + mesh_link_mng.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi 2007-06-25 For mesh (802.11s) support. +*/ +#ifdef MESH_SUPPORT + + +#include "rt_config.h" +#include "mesh_def.h" +#include "mesh_sanity.h" + + +static VOID MeshTORTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +static VOID MeshTOCTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +static VOID MeshTOHTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID PeerLinkEstablished( + IN PRTMP_ADAPTER pAd, + IN USHORT Idx); + +VOID PeerLinkClosed( + IN PRTMP_ADAPTER pAd, + IN USHORT Idx); + +static VOID MlmePasopAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID MlmeActopAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerClsAcptWhenListen( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID MlmeCnclActionWhenListen( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerOpenAcptWhenListen( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID TOR1WhenOpnSnt( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerCfnAcptWhenOpnSnt( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerOpenAcptWhenOpnSnt( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerClsAcptWhenOpnSnt( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerOpnRjctWhenOpnSnt( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerCfnRjctWhenOpnSnt( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID TOR2WhenOpnSnt( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID MlmeCnclWhenOpnSnt( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerOpnAcptWhenCfnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerClsAcptWhenCfnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerOpnRjctWhenCfnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerCfnRjctWhenCfnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID MlmeCnclWhenCfnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID TOCWhenCfnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerOpnAcptWhenCfnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID TOR1WhenOpnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerOpnAcptWhenOpnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerCfnAcptWhenOpnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerClsAcptWhenOpnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerOpnRjctWhenOpnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerCfnRjctWhenOpnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID TOR2WhenOpnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID MlmeCnclWhenOpnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerOpnAcptWhenEstab( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerClsAcptWhenEstab( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerOpnRjctWhenEstab( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerCfnRjctWhenEstab( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID CnclWhenEstab( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID TOHWhenHolding( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerOpnActpWhenHolding( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerCfnactpWhenHolding( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID PeerClsActpWhenHolding( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + + +static VOID EnquePeerLinkOpen( + IN PRTMP_ADAPTER pAd, + IN UCHAR LinkIdx); + +static VOID EnquePeerLinkConfirm( + IN PRTMP_ADAPTER pAd, + IN UCHAR LinkIdx, + IN UINT16 Aid, + IN UINT16 StatusCode); + +static VOID EnquePeerLinkClose( + IN PRTMP_ADAPTER pAd, + IN UCHAR LinkIdx, + IN UINT16 ReasonCode); + +static VOID EnquePeerLinkCloseEx( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pPeerMac, + IN UINT32 LocalLinkId, + IN UINT32 PeerLinkId, + IN UINT16 ReasonCode); + +static BOOLEAN PeerLinkOpnRcvd( + IN PRTMP_ADAPTER pAd, + IN USHORT Idx); + +static BOOLEAN PeerLinkCfnRcvd( + IN PRTMP_ADAPTER pAd, + IN USHORT Idx); + +static USHORT MeshBuildOpen( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR MaxSupportedRateIn500Kbps, + IN UCHAR SupRateLen, + IN BOOLEAN bWmmCapable, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen); + +DECLARE_TIMER_FUNCTION(MeshTORTimeout); +DECLARE_TIMER_FUNCTION(MeshTOCTimeout); +DECLARE_TIMER_FUNCTION(MeshTOHTimeout); + +BUILD_TIMER_FUNCTION(MeshTORTimeout); +BUILD_TIMER_FUNCTION(MeshTOCTimeout); +BUILD_TIMER_FUNCTION(MeshTOHTimeout); + +/* + ========================================================================== + Description: + check the Link is runing or not. + Parameters: + Standard timer parameters + ========================================================================== + */ +BOOLEAN PeerLinkMngRuning( + IN PRTMP_ADAPTER pAd, + IN USHORT Idx) +{ + BOOLEAN Valid; + + if ((pAd->MeshTab.MeshLink[Idx].CurrentState == MESH_LINK_MNG_IDLE) + || (pAd->MeshTab.MeshLink[Idx].CurrentState == MESH_LINK_MNG_LISTEN) + || (pAd->MeshTab.MeshLink[Idx].CurrentState == MESH_LINK_MNG_ESTAB)) + Valid = FALSE; + else + Valid = TRUE; + + return Valid; +} + +BOOLEAN PeerLinkValidCheck( + IN PRTMP_ADAPTER pAd, + IN USHORT Idx) +{ + BOOLEAN Valid; + + if(!VALID_MESH_LINK_ID(Idx)) + Valid = FALSE; + else if (pAd->MeshTab.MeshLink[Idx].CurrentState == MESH_LINK_MNG_ESTAB) + Valid = TRUE; + else + Valid = FALSE; + + return Valid; +} + +VOID PeerLinkEstablished( + IN PRTMP_ADAPTER pAd, + IN USHORT Idx) +{ + PMESH_NEIGHBOR_ENTRY pNeighbor = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link Index (%d).\n", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("!!! Mesh link-%d is established !!!\n", Idx)); + + /* Check if the current state is established. */ + if (pAd->MeshTab.MeshLink[Idx].CurrentState != MESH_LINK_MNG_ESTAB) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!! ERROR : This link(%d) isn't established (state=%d)!!!\n", Idx, pAd->MeshTab.MeshLink[Idx].CurrentState)); + return; + } + + pNeighbor = NeighborSearch(pAd, pAd->MeshTab.MeshLink[Idx].Entry.PeerMacAddr); + if (pNeighbor) + { + pNeighbor->State = LINK_AVAILABLE; + pNeighbor->MeshLinkIdx = Idx; + pAd->MeshTab.MeshLink[Idx].Entry.ExtChOffset = pNeighbor->ExtChOffset; + } + + /* Check if this link exists in MAC_TABLE_ENTRY */ + if((pEntry = MeshTableLookup(pAd, pAd->MeshTab.MeshLink[Idx].Entry.PeerMacAddr, TRUE)) == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!! ERROR : This link(%d) doesn't exist in MAC_TABLE_ENTRY. (%02x:%02x:%02x:%02x:%02x:%02x)!!!\n", + (UCHAR)Idx, PRINT_MAC(pAd->MeshTab.MeshLink[Idx].Entry.PeerMacAddr))); + return; + } + + if (pEntry) + { + /* In WEP or WPANone mode, set pairwise-key to ASIC for per-Mesh-Entry */ + if (pEntry->AuthMode < Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPANone) + { + UCHAR BssIdx = BSS0; + + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + BssIdx = pAd->ApCfg.BssidNum + MIN_NET_DEVICE_FOR_MESH; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + BssIdx = BSS0 + MIN_NET_DEVICE_FOR_MESH; +#endif /* CONFIG_STA_SUPPORT */ + + if ((pEntry->WepStatus == Ndis802_11WEPEnabled) || + (pEntry->AuthMode == Ndis802_11AuthModeWPANone)) + { + UCHAR Keyidx = 0; + + if (pEntry->AuthMode == Ndis802_11WEPEnabled) + Keyidx = pAd->MeshTab.DefaultKeyId; + + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + NdisMoveMemory(&pEntry->PairwiseKey, &pAd->MeshTab.SharedKey, sizeof(CIPHER_KEY)); + + /* Add Pair-wise key to Asic */ + RTMP_ASIC_PAIRWISE_KEY_TABLE(pAd, + (UCHAR)pEntry->Aid, + &pEntry->PairwiseKey); + + RTMP_SET_WCID_SEC_INFO(pAd, + BssIdx, + Keyidx, + pEntry->PairwiseKey.CipherAlg, + (UCHAR)pEntry->Aid, + PAIRWISEKEYTABLE); + } + + /* Once a mesh link is established, turn on this flag. */ + pAd->MeshTab.bInitialMsaDone = TRUE; + + } + + + } + + return; +} + +VOID PeerLinkClosed( + IN PRTMP_ADAPTER pAd, + IN USHORT Idx) +{ + PMESH_NEIGHBOR_ENTRY pNeighbor = NULL; + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link Index (%d).\n", __FUNCTION__, Idx)); + return; + } + + pNeighbor = NeighborSearch(pAd, pAd->MeshTab.MeshLink[Idx].Entry.PeerMacAddr); + if (pNeighbor) + { + pNeighbor->State = NEIGHBOR_MP; + pNeighbor->MeshLinkIdx = 0; + } + + if (pAd->MeshTab.LinkSize == 0) + { + pAd->MeshTab.bInitialMsaDone = FALSE; + } + + MultipathListDelete(pAd, Idx); + + return; +} + +PMESH_LINK_ENTRY MeshLinkLookUp( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr) +{ + INT i; + PMESH_LINK_ENTRY pLinkEntry = NULL; + + RTMP_SEM_LOCK(&pAd->MeshTabLock); + + for (i = 0; i < MAX_MESH_LINKS; i++) + { + if ((pAd->MeshTab.MeshLink[i].Entry.Valid == TRUE) + && MAC_ADDR_EQUAL(pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr, pAddr)) + { + pLinkEntry = &pAd->MeshTab.MeshLink[i].Entry; + break; + } + } + + RTMP_SEM_UNLOCK(&pAd->MeshTabLock); + + return pLinkEntry; +} + +ULONG MeshLinkAlloc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR LinkType) +{ + UINT i; + ULONG MeshLinkIdx = BSS_NOT_FOUND; + ULONG Now; + +/* + if (!MESH_ON(pAd)) + { + return -1; + } +*/ + +#ifdef WDS_SUPPORT + if (WdsTableLookup(pAd, pAddr, FALSE) != NULL) + { + + return MeshLinkIdx; + } +#endif /* WDS_SUPPORT */ + + /* allocate one Mesh entry */ + RTMP_SEM_LOCK(&pAd->MeshTabLock); + + do + { + for (i = 0; i < MAX_MESH_LINKS; i++) + { + if ((pAd->MeshTab.MeshLink[i].Entry.Valid == TRUE) + && MAC_ADDR_EQUAL(pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr, pAddr)) + break; + } + + if (i < MAX_MESH_LINKS) + { + MeshLinkIdx = i; + break; + } + + for (i = 0; i < MAX_MESH_LINKS; i++) + { + if (pAd->MeshTab.MeshLink[i].Entry.Valid == FALSE) + { + int ii; + NdisGetSystemUpTime(&Now); + pAd->MeshTab.MeshLink[i].Entry.LastBeaconTime = Now; + pAd->MeshTab.MeshLink[i].Entry.Valid = TRUE; + pAd->MeshTab.MeshLink[i].Entry.LocalLinkId = RandomLinkId(pAd); + pAd->MeshTab.MeshLink[i].Entry.Metrics = 1; + pAd->MeshTab.MeshLink[i].Entry.LinkType = LinkType; + COPY_MAC_ADDR(pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr, pAddr); + pAd->MeshTab.LinkSize ++; + MeshLinkIdx = i; + pAd->MeshTab.MeshCapability.field.AcceptPeerLinks = MeshAcceptPeerLink(pAd); + for (ii = 0; ii < MULTIPATH_HASH_TAB_SIZE; ii++) + initList(&pAd->MeshTab.MeshLink[i].Entry.MultiPathHash[ii]); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: LocalLinkId(%d)=%x\n", __FUNCTION__, i, pAd->MeshTab.MeshLink[i].Entry.LocalLinkId)); + break; + } + } + + if (i == MAX_MESH_LINKS) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unable to allocate Mesh-Link.\n", __FUNCTION__)); + MeshLinkIdx = BSS_NOT_FOUND; + break; + } + } while(FALSE); + + + if (VALID_MESH_LINK_ID(MeshLinkIdx)) + ValidateLocalMPAsSelector(pAd, MeshLinkIdx); + + RTMP_SEM_UNLOCK(&pAd->MeshTabLock); + + return MeshLinkIdx; +} + +VOID MeshLinkDelete( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UINT MeshLinkIdx) +{ + /* delete one Mesh entry */ + RTMP_SEM_LOCK(&pAd->MeshTabLock); + + if (MeshLinkIdx < MAX_MESH_LINKS) + { + if (pAd->MeshTab.MeshLink[MeshLinkIdx].Entry.Valid == TRUE) + { + pAd->MeshTab.MeshLink[MeshLinkIdx].Entry.Valid = FALSE; + NdisZeroMemory(&pAd->MeshTab.MeshLink[MeshLinkIdx].Entry, sizeof(MESH_LINK_ENTRY)); + pAd->MeshTab.LinkSize --; + pAd->MeshTab.MeshCapability.field.AcceptPeerLinks = MeshAcceptPeerLink(pAd); + } + } + + RTMP_SEM_UNLOCK(&pAd->MeshTabLock); + + return; +} + +/* + ========================================================================== + Description: + The mesh link management state machine, + Parameters: + Sm - pointer to the state machine + Note: + the state machine looks like the following + ========================================================================== + */ +VOID MeshLinkMngStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + UCHAR i; + + StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, (ULONG)MESH_LINK_MNG_MAX_STATES, + (ULONG)MESH_LINK_MNG_MAX_EVENTS, (STATE_MACHINE_FUNC)Drop, MESH_LINK_MNG_IDLE, MESH_LINK_MNG_IDLE); + + /* IDLE state */ + StateMachineSetAction(Sm, MESH_LINK_MNG_IDLE, MESH_LINK_MNG_PASOPN, (STATE_MACHINE_FUNC)MlmePasopAction); + StateMachineSetAction(Sm, MESH_LINK_MNG_IDLE, MESH_LINK_MNG_ACTOPN, (STATE_MACHINE_FUNC)MlmeActopAction); + + /* LISTEN state */ + StateMachineSetAction(Sm, MESH_LINK_MNG_LISTEN, MESH_LINK_MNG_CNCL, (STATE_MACHINE_FUNC)MlmeCnclActionWhenListen); + StateMachineSetAction(Sm, MESH_LINK_MNG_LISTEN, MESH_LINK_MNG_ACTOPN, (STATE_MACHINE_FUNC)MlmeActopAction); + StateMachineSetAction(Sm, MESH_LINK_MNG_LISTEN, MESH_LINK_MNG_CLS_ACPT, (STATE_MACHINE_FUNC)PeerClsAcptWhenListen); + StateMachineSetAction(Sm, MESH_LINK_MNG_LISTEN, MESH_LINK_MNG_OPEN_ACPT, (STATE_MACHINE_FUNC)PeerOpenAcptWhenListen); + + /* OPN_SNT state */ + StateMachineSetAction(Sm, MESH_LINK_MNG_OPN_SNT, MESH_LINK_MNG_TOR1, (STATE_MACHINE_FUNC)TOR1WhenOpnSnt); + StateMachineSetAction(Sm, MESH_LINK_MNG_OPN_SNT, MESH_LINK_MNG_CFN_ACPT, (STATE_MACHINE_FUNC)PeerCfnAcptWhenOpnSnt); + StateMachineSetAction(Sm, MESH_LINK_MNG_OPN_SNT, MESH_LINK_MNG_OPEN_ACPT, (STATE_MACHINE_FUNC)PeerOpenAcptWhenOpnSnt); + StateMachineSetAction(Sm, MESH_LINK_MNG_OPN_SNT, MESH_LINK_MNG_CLS_ACPT, (STATE_MACHINE_FUNC)PeerClsAcptWhenOpnSnt); + StateMachineSetAction(Sm, MESH_LINK_MNG_OPN_SNT, MESH_LINK_MNG_OPEN_RJCT, (STATE_MACHINE_FUNC)PeerOpnRjctWhenOpnSnt); + StateMachineSetAction(Sm, MESH_LINK_MNG_OPN_SNT, MESH_LINK_MNG_CFN_RJCT, (STATE_MACHINE_FUNC)PeerCfnRjctWhenOpnSnt); + StateMachineSetAction(Sm, MESH_LINK_MNG_OPN_SNT, MESH_LINK_MNG_TOR2, (STATE_MACHINE_FUNC)TOR2WhenOpnSnt); + StateMachineSetAction(Sm, MESH_LINK_MNG_OPN_SNT, MESH_LINK_MNG_CNCL, (STATE_MACHINE_FUNC)MlmeCnclWhenOpnSnt); + + /* CFN_RCVD state */ + StateMachineSetAction(Sm, MESH_LINK_MNG_CFN_RCVD, MESH_LINK_MNG_CFN_ACPT, (STATE_MACHINE_FUNC)Drop); + StateMachineSetAction(Sm, MESH_LINK_MNG_CFN_RCVD, MESH_LINK_MNG_OPEN_ACPT, (STATE_MACHINE_FUNC)PeerOpnAcptWhenCfnRcvd); + StateMachineSetAction(Sm, MESH_LINK_MNG_CFN_RCVD, MESH_LINK_MNG_CLS_ACPT, (STATE_MACHINE_FUNC)PeerClsAcptWhenCfnRcvd); + StateMachineSetAction(Sm, MESH_LINK_MNG_CFN_RCVD, MESH_LINK_MNG_OPEN_RJCT, (STATE_MACHINE_FUNC)PeerOpnRjctWhenCfnRcvd); + StateMachineSetAction(Sm, MESH_LINK_MNG_CFN_RCVD, MESH_LINK_MNG_CFN_RJCT, (STATE_MACHINE_FUNC)PeerCfnRjctWhenCfnRcvd); + StateMachineSetAction(Sm, MESH_LINK_MNG_CFN_RCVD, MESH_LINK_MNG_CNCL, (STATE_MACHINE_FUNC)MlmeCnclWhenCfnRcvd); + StateMachineSetAction(Sm, MESH_LINK_MNG_CFN_RCVD, MESH_LINK_MNG_TOC, (STATE_MACHINE_FUNC)TOCWhenCfnRcvd); + + /* OPN_RCVD state */ + StateMachineSetAction(Sm, MESH_LINK_MNG_OPN_RCVD, MESH_LINK_MNG_TOR1, (STATE_MACHINE_FUNC)TOR1WhenOpnRcvd); + StateMachineSetAction(Sm, MESH_LINK_MNG_OPN_RCVD, MESH_LINK_MNG_OPEN_ACPT, (STATE_MACHINE_FUNC)PeerOpnAcptWhenOpnRcvd); + StateMachineSetAction(Sm, MESH_LINK_MNG_OPN_RCVD, MESH_LINK_MNG_CFN_ACPT, (STATE_MACHINE_FUNC)PeerCfnAcptWhenOpnRcvd); + StateMachineSetAction(Sm, MESH_LINK_MNG_OPN_RCVD, MESH_LINK_MNG_CLS_ACPT, (STATE_MACHINE_FUNC)PeerClsAcptWhenOpnRcvd); + StateMachineSetAction(Sm, MESH_LINK_MNG_OPN_RCVD, MESH_LINK_MNG_OPEN_RJCT, (STATE_MACHINE_FUNC)PeerOpnRjctWhenOpnRcvd); + StateMachineSetAction(Sm, MESH_LINK_MNG_OPN_RCVD, MESH_LINK_MNG_CFN_RJCT, (STATE_MACHINE_FUNC)PeerCfnRjctWhenOpnRcvd); + StateMachineSetAction(Sm, MESH_LINK_MNG_OPN_RCVD, MESH_LINK_MNG_TOR2, (STATE_MACHINE_FUNC)TOR2WhenOpnRcvd); + StateMachineSetAction(Sm, MESH_LINK_MNG_OPN_RCVD, MESH_LINK_MNG_CNCL, (STATE_MACHINE_FUNC)MlmeCnclWhenOpnRcvd); + + /* ESTAB state */ + StateMachineSetAction(Sm, MESH_LINK_MNG_ESTAB, MESH_LINK_MNG_OPEN_ACPT, (STATE_MACHINE_FUNC)PeerOpnAcptWhenEstab); + StateMachineSetAction(Sm, MESH_LINK_MNG_ESTAB, MESH_LINK_MNG_CLS_ACPT, (STATE_MACHINE_FUNC)PeerClsAcptWhenEstab); + StateMachineSetAction(Sm, MESH_LINK_MNG_ESTAB, MESH_LINK_MNG_OPEN_RJCT, (STATE_MACHINE_FUNC)PeerOpnRjctWhenEstab); + StateMachineSetAction(Sm, MESH_LINK_MNG_ESTAB, MESH_LINK_MNG_CFN_RJCT, (STATE_MACHINE_FUNC)PeerCfnRjctWhenEstab); + StateMachineSetAction(Sm, MESH_LINK_MNG_ESTAB, MESH_LINK_MNG_CNCL, (STATE_MACHINE_FUNC)CnclWhenEstab); + + /* HOLDING state */ + StateMachineSetAction(Sm, MESH_LINK_MNG_HOLDING, MESH_LINK_MNG_TOH, (STATE_MACHINE_FUNC)TOHWhenHolding); + StateMachineSetAction(Sm, MESH_LINK_MNG_HOLDING, MESH_LINK_MNG_OPEN_ACPT, (STATE_MACHINE_FUNC)PeerOpnActpWhenHolding); + StateMachineSetAction(Sm, MESH_LINK_MNG_HOLDING, MESH_LINK_MNG_CFN_ACPT, (STATE_MACHINE_FUNC)PeerCfnactpWhenHolding); + StateMachineSetAction(Sm, MESH_LINK_MNG_HOLDING, MESH_LINK_MNG_CLS_ACPT, (STATE_MACHINE_FUNC)PeerClsActpWhenHolding); + + for (i = 0; i < MAX_MESH_LINKS; i++) + { + /* init all Mesh link state. */ + pAd->MeshTab.MeshLink[i].CurrentState = MESH_LINK_MNG_LISTEN; + + /* init all timer such as Timer-R, Timer-C and Timer-H relative to mesh Link-Mng. */ + RTMPInitTimer(pAd, &pAd->MeshTab.MeshLink[i].TOR, GET_TIMER_FUNCTION(MeshTORTimeout), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->MeshTab.MeshLink[i].TOC, GET_TIMER_FUNCTION(MeshTOCTimeout), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->MeshTab.MeshLink[i].TOH, GET_TIMER_FUNCTION(MeshTOHTimeout), pAd, FALSE); + } + + return; +} + +/* + ========================================================================== + Description: + Peer-Link-Discovery timeout procedure. + Parameters: + Standard timer parameters + ========================================================================== + */ +static VOID MeshTORTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + UCHAR idx; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + PRALINK_TIMER_STRUCT pTimer = (PRALINK_TIMER_STRUCT) SystemSpecific3; + + for (idx = 0; idx < MAX_MESH_LINKS; idx++) + { + if (&pAd->MeshTab.MeshLink[idx].TOR == pTimer) + break; + } + + if (idx == MAX_MESH_LINKS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s - unknow timer.\n", __FUNCTION__)); + return; + } + + if (pAd->MeshTab.MeshLink[idx].Entry.OpenRetyCnt < MAX_OPEN_RETRY) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s - enqueue MESH_LINK_MNG_TOR1 to MESH_LINK_MNG_STATE_MACHINE State-Machine. idx(%d)\n", __FUNCTION__, idx)); + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_TOR1, 0, NULL, idx); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s - enqueue MESH_LINK_MNG_TOR2 to MESH_LINK_MNG_STATE_MACHINE State-Machine.idx(%d)\n", __FUNCTION__, idx)); + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_TOR2, 0, NULL, idx); + } + + MeshMlmeHandler(pAd); + + return; +} + +/* + ========================================================================== + Description: + Mesh-Channel-Switch timeout procedure. + Parameters: + Standard timer parameters + ========================================================================== + */ +static VOID MeshTOCTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + UCHAR idx; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + PRALINK_TIMER_STRUCT pTimer = (PRALINK_TIMER_STRUCT) SystemSpecific3; + + for (idx = 0; idx < MAX_MESH_LINKS; idx++) + { + if (&pAd->MeshTab.MeshLink[idx].TOC == pTimer) + break; + } + + if (idx == MAX_MESH_LINKS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s - unknow timer.\n", __FUNCTION__)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s - enqueue MESH_LINK_MNG_TOC to MESH_LINK_MNG_STATE_MACHINE State-Machine. idx(%d)\n", __FUNCTION__, idx)); + + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_TOC, 0, NULL, idx); + MeshMlmeHandler(pAd); + + return; +} + +/* + ========================================================================== + Description: + Mesh-Channel-Switch timeout procedure. + Parameters: + Standard timer parameters + ========================================================================== + */ +static VOID MeshTOHTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + UCHAR idx; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + PRALINK_TIMER_STRUCT pTimer = (PRALINK_TIMER_STRUCT) SystemSpecific3; + + for (idx = 0; idx < MAX_MESH_LINKS; idx++) + { + if (&pAd->MeshTab.MeshLink[idx].TOH == pTimer) + break; + } + + if (idx == MAX_MESH_LINKS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s - unknow timer.\n", __FUNCTION__)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s - enqueue MESH_LINK_MNG_TOH to MESH_LINK_MNG_STATE_MACHINE State-Machine. idx(%d)\n", __FUNCTION__, idx)); + + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_TOH, 0, NULL, idx); + MeshMlmeHandler(pAd); + + return; +} + +static VOID MlmePasopAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + /* transit state to MESH_LINK_MNG_LISTEN state. */ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get PASOPN Event at Idle (Idx=%d).\n", __FUNCTION__, Idx)); + + *pCurrState = MESH_LINK_MNG_LISTEN; + + return; +} + +static VOID MlmeActopAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get ACTOPN Event at Idle (Idx=%d).\n", __FUNCTION__, Idx)); + + EnquePeerLinkOpen(pAd, Idx); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOR, TOR_TIME); + *pCurrState = MESH_LINK_MNG_OPN_SNT; + + return; +} + +static VOID PeerClsAcptWhenListen( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + /* transit state to MESH_LINK_MNG_IDLE. */ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get CLSAcpt event at Listen (Idx=%d).\n", __FUNCTION__, Idx)); + + *pCurrState = MESH_LINK_MNG_LISTEN; + + return; +} + +static VOID MlmeCnclActionWhenListen( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + /* transit state to MESH_LINK_MNG_IDLE state. */ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get MlmeCNCL enent at Listen (Idx=%d).\n", __FUNCTION__, Idx)); + + if ((pAd->MeshTab.MeshLink[Idx].Entry.LinkType == MESH_LINK_DYNAMIC) + && (pAd->MeshTab.MeshLink[Idx].Entry.Valid)) + MeshLinkDelete(pAd, pAd->MeshTab.MeshLink[Idx].Entry.PeerMacAddr, Idx); + + *pCurrState = MESH_LINK_MNG_LISTEN; + + return; +} + +static VOID PeerOpenAcptWhenListen( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + PMAC_TABLE_ENTRY pMacEntry = NULL; + PMESH_LINK_OPEN_MSG_STRUCT pInfo = (PMESH_LINK_OPEN_MSG_STRUCT)(Elem->Msg); + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get OPNAcpt at Listen (Idx=%d).\n", __FUNCTION__, Idx)); + + pAd->MeshTab.MeshLink[Idx].Entry.PeerLinkId = pInfo->PeerLinkId; + + pMacEntry = MacTableInsertMeshEntry(pAd, pAd->MeshTab.MeshLink[Idx].Entry.PeerMacAddr, Idx); + if (MeshBuildOpen(pAd, pMacEntry, pInfo->MaxSupportedRate,pInfo->SupRateLen, pInfo->bWmmCapable, + &pInfo->HTCapability, pInfo->HTCapability_Len) != MLME_SUCCESS) + { + MacTableDeleteEntry(pAd, pMacEntry->Aid, pMacEntry->Addr); + pMacEntry = NULL; + } + + if (pMacEntry) + { + EnquePeerLinkOpen(pAd, Idx); + EnquePeerLinkConfirm(pAd, Idx, pMacEntry->Aid, MLME_SUCCESS); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOR, TOR_TIME); + *pCurrState = MESH_LINK_MNG_OPN_RCVD; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unable to allocate MacEntry here.\n", __FUNCTION__)); + EnquePeerLinkConfirm(pAd, Idx, 0, MLME_FAIL_NO_RESOURCE); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + } + + return; +} + +static VOID TOR1WhenOpnSnt( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get TOR1 event at OpnSnt (Idx=%d).\n", __FUNCTION__, Idx)); + + EnquePeerLinkOpen(pAd, Idx); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOR, TOR_TIME); + + return; +} + +static VOID PeerCfnAcptWhenOpnSnt( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + BOOLEAN Cancelled; + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get CFNAcpt event at OpnSnt (Idx=%d).\n", __FUNCTION__, Idx)); + + RTMPCancelTimer(&pAd->MeshTab.MeshLink[Idx].TOR, &Cancelled); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOC, TOC_TIME); + *pCurrState = MESH_LINK_MNG_CFN_RCVD; + + return; +} + +static VOID PeerOpenAcptWhenOpnSnt( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + PMAC_TABLE_ENTRY pMacEntry = NULL; + PMESH_LINK_OPEN_MSG_STRUCT pInfo = (PMESH_LINK_OPEN_MSG_STRUCT)(Elem->Msg); + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get OPNAcpt event at OpnSnt (Idx=%d).\n", __FUNCTION__, Idx)); + + pAd->MeshTab.MeshLink[Idx].Entry.PeerLinkId = pInfo->PeerLinkId; + pMacEntry = MacTableInsertMeshEntry(pAd, pAd->MeshTab.MeshLink[Idx].Entry.PeerMacAddr, Idx); + if (MeshBuildOpen(pAd, pMacEntry, pInfo->MaxSupportedRate,pInfo->SupRateLen, pInfo->bWmmCapable, + &pInfo->HTCapability, pInfo->HTCapability_Len) != MLME_SUCCESS) + { + MacTableDeleteMeshEntry(pAd, pMacEntry->Aid, pMacEntry->Addr); + pMacEntry = NULL; + } + + if (pMacEntry) + { + EnquePeerLinkConfirm(pAd, Idx, pMacEntry->Aid, MLME_SUCCESS); + *pCurrState = MESH_LINK_MNG_OPN_RCVD; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unable to a MacEntry here.\n", __FUNCTION__)); + EnquePeerLinkConfirm(pAd, Idx, 0, MLME_FAIL_NO_RESOURCE); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + } + + return; +} + +static VOID PeerClsAcptWhenOpnSnt( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + BOOLEAN Cancelled; + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get ClsAcpt event at OpnSnt (Idx=%d).\n", __FUNCTION__, Idx)); + + EnquePeerLinkClose(pAd, Idx, MESH_CLOSE_RCVD); + RTMPCancelTimer(&pAd->MeshTab.MeshLink[Idx].TOR, &Cancelled); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + + return; +} + +static VOID PeerOpnRjctWhenOpnSnt( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + BOOLEAN Cancelled; + PMESH_LINK_OPEN_MSG_STRUCT pInfo = (PMESH_LINK_OPEN_MSG_STRUCT)(Elem->Msg); + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get OPNRjct event at OpnSnt (Idx=%d).\n", __FUNCTION__, Idx)); + + RTMPCancelTimer(&pAd->MeshTab.MeshLink[Idx].TOR, &Cancelled); + EnquePeerLinkClose(pAd, Idx, pInfo->ReasonCode); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + + return; +} + +static VOID PeerCfnRjctWhenOpnSnt( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + BOOLEAN Cancelled; + PMESH_LINK_CONFIRM_MSG_STRUCT pInfo = (PMESH_LINK_CONFIRM_MSG_STRUCT)(Elem->Msg); + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get CFNRjct event at OpnSnt (Idx=%d).\n", __FUNCTION__, Idx)); + + RTMPCancelTimer(&pAd->MeshTab.MeshLink[Idx].TOR, &Cancelled); + EnquePeerLinkClose(pAd, Idx, pInfo->ReasonCode); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + + return; +} + +static VOID TOR2WhenOpnSnt( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get TOR2 event at OpnSnt (Idx=%d).\n", __FUNCTION__, Idx)); + + EnquePeerLinkClose(pAd, Idx, MESH_MAX_RETRIES); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + + return; +} + +static VOID MlmeCnclWhenOpnSnt( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + BOOLEAN Cancelled; + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get Cncl event at OpnSnt (Idx=%d).\n", __FUNCTION__, Idx)); + + RTMPCancelTimer(&pAd->MeshTab.MeshLink[Idx].TOR, &Cancelled); + EnquePeerLinkClose(pAd, Idx, MESH_LINK_CANCELLED); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + + return; +} + +static VOID PeerOpnAcptWhenCfnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + BOOLEAN Cancelled; + PMAC_TABLE_ENTRY pMacEntry = NULL; + PMESH_LINK_OPEN_MSG_STRUCT pInfo = (PMESH_LINK_OPEN_MSG_STRUCT)(Elem->Msg); + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get OPNAcpt event at CfnRcvd (Idx=%d).\n", __FUNCTION__, Idx)); + + RTMPCancelTimer(&pAd->MeshTab.MeshLink[Idx].TOC, &Cancelled); + pAd->MeshTab.MeshLink[Idx].Entry.PeerLinkId = pInfo->PeerLinkId; + pMacEntry = MacTableInsertMeshEntry(pAd, pAd->MeshTab.MeshLink[Idx].Entry.PeerMacAddr, Idx); + if (MeshBuildOpen(pAd, pMacEntry, pInfo->MaxSupportedRate,pInfo->SupRateLen, pInfo->bWmmCapable, + &pInfo->HTCapability, pInfo->HTCapability_Len) != MLME_SUCCESS) + { + MacTableDeleteEntry(pAd, pMacEntry->Aid, pMacEntry->Addr); + pMacEntry = NULL; + } + + if (pMacEntry) + { + EnquePeerLinkConfirm(pAd, Idx, pMacEntry->Aid, MLME_SUCCESS); + *pCurrState = MESH_LINK_MNG_ESTAB; + PeerLinkEstablished(pAd, Idx); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unable to a MacEntry here.\n", __FUNCTION__)); + EnquePeerLinkConfirm(pAd, Idx, 0, MLME_FAIL_NO_RESOURCE); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + } + + return; +} + +static VOID PeerClsAcptWhenCfnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + BOOLEAN Cancelled; + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get CLSAcpt event at CfnRcvd (Idx=%d).\n", __FUNCTION__, Idx)); + + RTMPCancelTimer(&pAd->MeshTab.MeshLink[Idx].TOC, &Cancelled); + EnquePeerLinkClose(pAd, Idx, MESH_CLOSE_RCVD); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + + return; +} + +static VOID PeerOpnRjctWhenCfnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + BOOLEAN Cancelled; + PMESH_LINK_OPEN_MSG_STRUCT pInfo = (PMESH_LINK_OPEN_MSG_STRUCT)(Elem->Msg); + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get OPNRjct event at CfnRcvd (Idx=%d).\n", __FUNCTION__, Idx)); + + RTMPCancelTimer(&pAd->MeshTab.MeshLink[Idx].TOC, &Cancelled); + EnquePeerLinkClose(pAd, Idx, pInfo->ReasonCode); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + + return; +} + +static VOID PeerCfnRjctWhenCfnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + BOOLEAN Cancelled; + PMESH_LINK_CONFIRM_MSG_STRUCT pInfo = (PMESH_LINK_CONFIRM_MSG_STRUCT)(Elem->Msg); + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get CFNRjct event at CfnRcvd (Idx=%d).\n", __FUNCTION__, Idx)); + + RTMPCancelTimer(&pAd->MeshTab.MeshLink[Idx].TOC, &Cancelled); + EnquePeerLinkClose(pAd, Idx, pInfo->ReasonCode); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + + return; +} + +static VOID MlmeCnclWhenCfnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + BOOLEAN Cancelled; + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get Cncl event at CfnRcvd (Idx=%d).\n", __FUNCTION__, Idx)); + + RTMPCancelTimer(&pAd->MeshTab.MeshLink[Idx].TOC, &Cancelled); + EnquePeerLinkClose(pAd, Idx, MESH_LINK_CANCELLED); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + + return; +} + +static VOID TOCWhenCfnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get TOC event at CfnRcvd (Idx=%d).\n", __FUNCTION__, Idx)); + + EnquePeerLinkClose(pAd, Idx, MESH_CONFIRM_TIMEOUT); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + + return; +} + +static VOID TOR1WhenOpnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + /* Send Peer Link Open frame to Candidate MP. */ + /* Set Time TOR. */ + + USHORT Idx = Elem->Priv; + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get TOR1 event at OpnRcvd (Idx=%d).\n", __FUNCTION__, Idx)); + + EnquePeerLinkOpen(pAd, Idx); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOR, TOR_TIME); + +} + +static VOID PeerOpnAcptWhenOpnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + /* send Peer Link Confirm to Candidate MP. */ + + USHORT Idx = Elem->Priv; + PMAC_TABLE_ENTRY pMacEntry = NULL; + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get OPNAcpt event at OpnRcvd (Idx=%d).\n", __FUNCTION__, Idx)); + + pMacEntry = MeshTableLookup(pAd, pAd->MeshTab.MeshLink[Idx].Entry.PeerMacAddr, TRUE); + + if (pMacEntry) + EnquePeerLinkConfirm(pAd, Idx, pMacEntry->Aid, MLME_SUCCESS); + else + DBGPRINT(RT_DEBUG_OFF, ("%s: MacEntry doesn't exist.\n", __FUNCTION__)); + + return; +} + +static VOID PeerCfnAcptWhenOpnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + /* Cancel TOR */ + /* transit state to MESH_LINK_MNG_ESTAB. */ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + BOOLEAN Cancelled; + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get CFNAcpt event at OpnRcvd (Idx=%d).\n", __FUNCTION__, Idx)); + + RTMPCancelTimer(&pAd->MeshTab.MeshLink[Idx].TOR, &Cancelled); + *pCurrState = MESH_LINK_MNG_ESTAB; + PeerLinkEstablished(pAd, Idx); + + return; +} + +static VOID PeerClsAcptWhenOpnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + BOOLEAN Cancelled; + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get ClsAcpt event at OpnRcvd (Idx=%d).\n", __FUNCTION__, Idx)); + + EnquePeerLinkClose(pAd, Idx, MESH_CLOSE_RCVD); + RTMPCancelTimer(&pAd->MeshTab.MeshLink[Idx].TOR, &Cancelled); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + + return; +} + +static VOID PeerOpnRjctWhenOpnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + BOOLEAN Cancelled; + PMESH_LINK_OPEN_MSG_STRUCT pInfo = (PMESH_LINK_OPEN_MSG_STRUCT)(Elem->Msg); + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get OPNRjct event at OpnRcvd (Idx=%d).\n", __FUNCTION__, Idx)); + + RTMPCancelTimer(&pAd->MeshTab.MeshLink[Idx].TOR, &Cancelled); + EnquePeerLinkClose(pAd, Idx, pInfo->ReasonCode); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + + return; +} + +static VOID PeerCfnRjctWhenOpnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + BOOLEAN Cancelled; + PMESH_LINK_CONFIRM_MSG_STRUCT pInfo = (PMESH_LINK_CONFIRM_MSG_STRUCT)(Elem->Msg); + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get CFNRjct event at OpnRcvd (Idx=%d).\n", __FUNCTION__, Idx)); + + RTMPCancelTimer(&pAd->MeshTab.MeshLink[Idx].TOR, &Cancelled); + EnquePeerLinkClose(pAd, Idx, pInfo->ReasonCode); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + + return; +} + +static VOID TOR2WhenOpnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get TOR2 event at OpnRcvd (Idx=%d).\n", __FUNCTION__, Idx)); + + EnquePeerLinkClose(pAd, Idx, MESH_MAX_RETRIES); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + + return; +} + +static VOID MlmeCnclWhenOpnRcvd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + BOOLEAN Cancelled; + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get Cncl event at OpnRcvd (Idx=%d).\n", __FUNCTION__, Idx)); + + RTMPCancelTimer(&pAd->MeshTab.MeshLink[Idx].TOR, &Cancelled); + EnquePeerLinkClose(pAd, Idx, MESH_LINK_CANCELLED); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + + return; +} + +static VOID PeerOpnAcptWhenEstab( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + /* send Peer Link Confirm to Candidate MP. */ + + USHORT Idx = Elem->Priv; + PMAC_TABLE_ENTRY pMacEntry = NULL; + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get OPNAcpt event at Estab (Idx=%d).\n", __FUNCTION__, Idx)); + + pMacEntry = MeshTableLookup(pAd, pAd->MeshTab.MeshLink[Idx].Entry.PeerMacAddr, TRUE); + + if (pMacEntry) + EnquePeerLinkConfirm(pAd, Idx, pMacEntry->Aid, MLME_SUCCESS); + else + DBGPRINT(RT_DEBUG_ERROR, ("%s: MacEntry doesn't exist.\n", __FUNCTION__)); + + return; +} + +static VOID PeerClsAcptWhenEstab( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + BOOLEAN Cancelled; + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get ClsAcpt event at Estab (Idx=%d).\n", __FUNCTION__, Idx)); + + EnquePeerLinkClose(pAd, Idx, MESH_CLOSE_RCVD); + RTMPCancelTimer(&pAd->MeshTab.MeshLink[Idx].TOR, &Cancelled); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + + return; +} + +static VOID PeerOpnRjctWhenEstab( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + BOOLEAN Cancelled; + PMESH_LINK_OPEN_MSG_STRUCT pInfo = (PMESH_LINK_OPEN_MSG_STRUCT)(Elem->Msg); + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get OPNRjct event at Estab (Idx=%d).\n", __FUNCTION__, Idx)); + + RTMPCancelTimer(&pAd->MeshTab.MeshLink[Idx].TOR, &Cancelled); + EnquePeerLinkClose(pAd, Idx, pInfo->ReasonCode); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + + return; +} + +static VOID PeerCfnRjctWhenEstab( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + BOOLEAN Cancelled; + PMESH_LINK_CONFIRM_MSG_STRUCT pInfo = (PMESH_LINK_CONFIRM_MSG_STRUCT)(Elem->Msg); + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get CFNRjct event at Estab (Idx=%d).\n", __FUNCTION__, Idx)); + + RTMPCancelTimer(&pAd->MeshTab.MeshLink[Idx].TOR, &Cancelled); + EnquePeerLinkClose(pAd, Idx, pInfo->ReasonCode); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + + return; +} + +static VOID CnclWhenEstab( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get Cncl event at Estab (Idx=%d).\n", __FUNCTION__, Idx)); + + EnquePeerLinkClose(pAd, Idx, MESH_LINK_CANCELLED); + RTMPSetTimer(&pAd->MeshTab.MeshLink[Idx].TOH, TOH_TIME); + *pCurrState = MESH_LINK_MNG_HOLDING; + + return; +} + +static VOID TOHWhenHolding( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get TOH event at Holding (Idx=%d).\n", __FUNCTION__, Idx)); + + PeerLinkClosed(pAd, Idx); + + if(MeshTableLookup(pAd, pAd->MeshTab.MeshLink[Idx].Entry.PeerMacAddr, TRUE)) + MacTableDeleteMeshEntry(pAd, pAd->MeshTab.MeshLink[Idx].Entry.MacTabMatchWCID, + pAd->MeshTab.MeshLink[Idx].Entry.PeerMacAddr); + + if ((pAd->MeshTab.MeshLink[Idx].Entry.LinkType == MESH_LINK_DYNAMIC) + && (pAd->MeshTab.MeshLink[Idx].Entry.Valid)) + MeshLinkDelete(pAd, pAd->MeshTab.MeshLink[Idx].Entry.PeerMacAddr, Idx); + + *pCurrState = MESH_LINK_MNG_LISTEN; + + return; +} + +static VOID PeerOpnActpWhenHolding( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Idx = Elem->Priv; + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get OPNActp at Holding (Idx=%d).\n", __FUNCTION__, Idx)); + + EnquePeerLinkClose(pAd, Idx, MESH_LINK_CANCELLED); + + return; +} + +static VOID PeerCfnactpWhenHolding( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Idx = Elem->Priv; + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get CFNActp at Holding (Idx=%d).\n", __FUNCTION__, Idx)); + + EnquePeerLinkClose(pAd, Idx, MESH_LINK_CANCELLED); + + return; +} + +static VOID PeerClsActpWhenHolding( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Idx = Elem->Priv; + MESH_LINK_MNG_STATE *pCurrState = &(pAd->MeshTab.MeshLink[Idx].CurrentState); + BOOLEAN Cancelled; + + if (!VALID_MESH_LINK_ID(Idx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid Link-Idx=%d", __FUNCTION__, Idx)); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get CLSActp at Holding (Idx=%d).\n", __FUNCTION__, Idx)); + + RTMPCancelTimer(&pAd->MeshTab.MeshLink[Idx].TOH, &Cancelled); + + PeerLinkClosed(pAd, Idx); + + if(MeshTableLookup(pAd, pAd->MeshTab.MeshLink[Idx].Entry.PeerMacAddr, TRUE)) + MacTableDeleteMeshEntry(pAd, pAd->MeshTab.MeshLink[Idx].Entry.MacTabMatchWCID, + pAd->MeshTab.MeshLink[Idx].Entry.PeerMacAddr); + + if ((pAd->MeshTab.MeshLink[Idx].Entry.LinkType == MESH_LINK_DYNAMIC) + && (pAd->MeshTab.MeshLink[Idx].Entry.Valid)) + MeshLinkDelete(pAd, pAd->MeshTab.MeshLink[Idx].Entry.PeerMacAddr, Idx); + + *pCurrState = MESH_LINK_MNG_LISTEN; + + return; +} + + +static VOID EnquePeerLinkOpen( + IN PRTMP_ADAPTER pAd, + IN UCHAR LinkIdx) +{ + HEADER_802_11 MeshHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + MESH_FLAG MeshFlag; + UINT16 CapabilityInfoForAssocResp; + UINT32 MeshSeq = INC_MESH_SEQ(pAd->MeshTab.MeshSeq); + + 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; + } + + MeshHeaderInit(pAd, &MeshHdr, + pAd->MeshTab.MeshLink[LinkIdx].Entry.PeerMacAddr, /* addr1 */ + pAd->MeshTab.CurrentAddress, /* addr2 */ + ZERO_MAC_ADDR); /* addr3 */ + NdisMoveMemory(pOutBuffer, (PCHAR)&MeshHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + /* Mesh Header */ + MeshFlag.word = 0; + MeshFlag.field.AE = 0; /* Peer-Link manager frame never carry 6 addresses. */ + InsertMeshHeader(pAd, (pOutBuffer + FrameLen), &FrameLen, MeshFlag.word, + pAd->MeshTab.TTL, MeshSeq, NULL, NULL, NULL); + + /* Action field */ + InsertMeshActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_MESH_PEER_LINK, ACT_CODE_PEER_LINK_OPEN); + + /* Capability */ + CapabilityInfoForAssocResp = GET_CAPABILITY_INFO(pAd) & ~(0x0003); + InsertCapabilityInfo(pAd, (pOutBuffer + FrameLen), &FrameLen, CapabilityInfoForAssocResp); + + /* Supported rates */ + InsertSupRateIE(pAd, (pOutBuffer + FrameLen), &FrameLen); + + /* Extend rate */ + InsertExtRateIE(pAd, (pOutBuffer + FrameLen), &FrameLen); + + /* RSN IE */ + if (pAd->MeshTab.AuthMode >= Ndis802_11AuthModeWPA) + InsertRSNIE(pAd, pAd->MeshTab.MeshLink[LinkIdx].Entry.PeerMacAddr, (pOutBuffer + FrameLen), &FrameLen); + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + InsertHtCapIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &pAd->CommonCfg.HtCapability); + InsertAddHtInfoIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &pAd->CommonCfg.AddHTInfo); + } +#endif /* DOT11_N_SUPPORT */ + + /* Mesh Id IE */ + InsertMeshIdIE(pAd, (pOutBuffer + FrameLen), &FrameLen); + + /* Mesh Configuration IE */ + InsertMeshConfigurationIE(pAd, (pOutBuffer + FrameLen), &FrameLen,TRUE); + + /* Mesh Peer Link Management IE */ + InsertMeshPeerLinkMngIE(pAd, (pOutBuffer + FrameLen), &FrameLen, SUBTYPE_PEER_LINK_OPEN, + pAd->MeshTab.MeshLink[LinkIdx].Entry.LocalLinkId, 0, 0); + + /* Insert MSCIE */ + InsertMSCIE(pAd, (pOutBuffer+FrameLen), &FrameLen); + + /* Insert MSAIE */ + InsertMSAIE(pAd, LinkIdx, SUBTYPE_PEER_LINK_OPEN, (pOutBuffer+FrameLen), &FrameLen); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + pAd->MeshTab.MeshLink[LinkIdx].Entry.OpenRetyCnt++; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: LocalLinkId(%d)=%x\n", + __FUNCTION__, LinkIdx, pAd->MeshTab.MeshLink[LinkIdx].Entry.LocalLinkId)); + + return; +} + +static VOID EnquePeerLinkConfirm( + IN PRTMP_ADAPTER pAd, + IN UCHAR LinkIdx, + IN UINT16 Aid, + IN UINT16 StatusCode) +{ + HEADER_802_11 MeshHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + MESH_FLAG MeshFlag; + UINT16 CapabilityInfoForAssocResp; + UINT32 MeshSeq = INC_MESH_SEQ(pAd->MeshTab.MeshSeq); + + 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; + } + + MeshHeaderInit(pAd, &MeshHdr, + pAd->MeshTab.MeshLink[LinkIdx].Entry.PeerMacAddr, /* addr1 */ + pAd->MeshTab.CurrentAddress, /* addr2 */ + ZERO_MAC_ADDR); /* addr3 */ + NdisMoveMemory(pOutBuffer, (PCHAR)&MeshHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + /* Mesh Header */ + MeshFlag.word = 0; + MeshFlag.field.AE = 0; /* Peer-Link manager frame never carry 6 addresses. */ + InsertMeshHeader(pAd, (pOutBuffer + FrameLen), &FrameLen, MeshFlag.word, + pAd->MeshTab.TTL, MeshSeq, NULL, NULL, NULL); + + /* Action field */ + InsertMeshActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_MESH_PEER_LINK, ACT_CODE_PEER_LINK_CONFIRM); + + /* Capability */ + CapabilityInfoForAssocResp = GET_CAPABILITY_INFO(pAd) & ~(0x0003); + InsertCapabilityInfo(pAd, (pOutBuffer + FrameLen), &FrameLen, CapabilityInfoForAssocResp); + + /* Status code */ + InsertStatusCode(pAd, (pOutBuffer + FrameLen), &FrameLen, StatusCode); + + InsertAID(pAd, (pOutBuffer + FrameLen), &FrameLen, Aid); + + /* Supported rates */ + InsertSupRateIE(pAd, (pOutBuffer + FrameLen), &FrameLen); + + /* Extend rate */ + InsertExtRateIE(pAd, (pOutBuffer + FrameLen), &FrameLen); + + /* RSN IE */ + if (pAd->MeshTab.AuthMode >= Ndis802_11AuthModeWPA) + InsertRSNIE(pAd, pAd->MeshTab.MeshLink[LinkIdx].Entry.PeerMacAddr, (pOutBuffer + FrameLen), &FrameLen); + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[pAd->MeshTab.MeshLink[LinkIdx].Entry.MacTabMatchWCID]; + if (IS_ENTRY_MESH(pEntry)) + { + InsertHtCapIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &pAd->CommonCfg.HtCapability); + InsertAddHtInfoIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &pAd->CommonCfg.AddHTInfo); + } + } +#endif /* DOT11_N_SUPPORT */ + + /* Mesh Id IE */ + InsertMeshIdIE(pAd, (pOutBuffer + FrameLen), &FrameLen); + + /* Mesh Configuration IE */ + InsertMeshConfigurationIE(pAd, (pOutBuffer + FrameLen), &FrameLen,TRUE); + + /* Mesh Peer Link Management IE */ + InsertMeshPeerLinkMngIE(pAd, (pOutBuffer + FrameLen), &FrameLen, SUBTYPE_PEER_LINK_CONFIRM, + pAd->MeshTab.MeshLink[LinkIdx].Entry.LocalLinkId, pAd->MeshTab.MeshLink[LinkIdx].Entry.PeerLinkId, 0); + + /* Insert MSCIE */ + InsertMSCIE(pAd, (pOutBuffer+FrameLen), &FrameLen); + + /* Insert MSAIE */ + InsertMSAIE(pAd, LinkIdx, SUBTYPE_PEER_LINK_CONFIRM, (pOutBuffer+FrameLen), &FrameLen); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: LocalLinkId(%d)=%x, PeerLinkId=%x\n", + __FUNCTION__, LinkIdx, pAd->MeshTab.MeshLink[LinkIdx].Entry.LocalLinkId, + pAd->MeshTab.MeshLink[LinkIdx].Entry.PeerLinkId)); + + return; +} + +static VOID EnquePeerLinkClose( + IN PRTMP_ADAPTER pAd, + IN UCHAR LinkIdx, + IN UINT16 ReasonCode) +{ + EnquePeerLinkCloseEx(pAd, pAd->MeshTab.MeshLink[LinkIdx].Entry.PeerMacAddr, + pAd->MeshTab.MeshLink[LinkIdx].Entry.LocalLinkId, + pAd->MeshTab.MeshLink[LinkIdx].Entry.PeerLinkId, + ReasonCode); + + pAd->MeshTab.MeshLink[LinkIdx].Entry.OpenRetyCnt = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: LocalLinkId(%d)=%x, PeerLinkId=%x, Reason=%d\n", + __FUNCTION__, LinkIdx, pAd->MeshTab.MeshLink[LinkIdx].Entry.LocalLinkId, + pAd->MeshTab.MeshLink[LinkIdx].Entry.PeerLinkId, ReasonCode)); + + return; +} + +static VOID EnquePeerLinkCloseEx( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pPeerMac, + IN UINT32 LocalLinkId, + IN UINT32 PeerLinkId, + IN UINT16 ReasonCode) +{ + HEADER_802_11 MeshHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + MESH_FLAG MeshFlag; + UINT32 MeshSeq = INC_MESH_SEQ(pAd->MeshTab.MeshSeq); + + 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; + } + + MeshHeaderInit(pAd, &MeshHdr, + pPeerMac, /* addr1 */ + pAd->MeshTab.CurrentAddress, /* addr2 */ + ZERO_MAC_ADDR); /* addr3 */ + NdisMoveMemory(pOutBuffer, (PCHAR)&MeshHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + /* Mesh Header */ + MeshFlag.word = 0; + MeshFlag.field.AE = 0; /* Peer-Link manager frame never carry 6 addresses. */ + InsertMeshHeader(pAd, (pOutBuffer + FrameLen), &FrameLen, MeshFlag.word, + pAd->MeshTab.TTL, MeshSeq, NULL, NULL, NULL); + + /* Action field */ + InsertMeshActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_MESH_PEER_LINK, ACT_CODE_PEER_LINK_CLOSE); + + /* Reason code */ + InsertReasonCode(pAd, (pOutBuffer + FrameLen), &FrameLen, ReasonCode); + + /* Mesh Peer Link Management IE */ + InsertMeshPeerLinkMngIE(pAd, (pOutBuffer + FrameLen), &FrameLen, SUBTYPE_PEER_LINK_CLOSE, + LocalLinkId, PeerLinkId, ReasonCode); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: LocalLinkId=%x, PeerLinkId=%x, Reason=%d\n", + __FUNCTION__, LocalLinkId, PeerLinkId, ReasonCode)); + + return; +} + +static BOOLEAN PeerLinkOpnRcvd( + IN PRTMP_ADAPTER pAd, + IN USHORT Idx) +{ + if ((pAd->MeshTab.MeshLink[Idx].CurrentState == MESH_LINK_MNG_OPN_RCVD) + || (pAd->MeshTab.MeshLink[Idx].CurrentState == MESH_LINK_MNG_ESTAB)) + return TRUE; + else + return FALSE; +} + +static BOOLEAN PeerLinkCfnRcvd( + IN PRTMP_ADAPTER pAd, + IN USHORT Idx) +{ + if ((pAd->MeshTab.MeshLink[Idx].CurrentState == MESH_LINK_MNG_CFN_RCVD) + || (pAd->MeshTab.MeshLink[Idx].CurrentState == MESH_LINK_MNG_ESTAB)) + return TRUE; + else + return FALSE; +} + +static USHORT MeshBuildOpen( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR MaxSupportedRateIn500Kbps, + IN UCHAR SupRateLen, + IN BOOLEAN bWmmCapable, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen) +{ + USHORT StatusCode = MLME_SUCCESS; + UCHAR MaxSupportedRate = RATE_11; + + 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; + } + + if ((pAd->CommonCfg.PhyMode == PHY_11G) && (MaxSupportedRate < RATE_FIRST_OFDM_RATE)) + return MLME_ASSOC_REJ_DATA_RATE; + +#ifdef DOT11_N_SUPPORT + /* 11n only */ + if (((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)) + && (HtCapabilityLen == 0)) + return MLME_ASSOC_REJ_DATA_RATE; +#endif /* DOT11_N_SUPPORT */ + + if (!pEntry) + return MLME_UNSPECIFY_FAIL; + + do + { + /* should qualify other parameters, for example - capablity, supported rates, listen interval, ... etc */ + /* to decide the Status Code */ + pEntry->NoDataIdleCount = 0; + + + if (pEntry->Aid == 0) + StatusCode = MLME_ASSOC_REJ_UNABLE_HANDLE_STA; + else + { + pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, 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; +#endif /* DOT11_N_SUPPORT */ + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + + +#ifdef DOT11_N_SUPPORT + /* If this Entry supports 802.11n, upgrade to HT rate. */ + if ((HtCapabilityLen != 0) && + (pAd->MeshTab.DesiredHtPhyInfo.bHtEnable) && + (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + UCHAR j, bitmask; /*k,bitmask; */ + CHAR i; + + if ((pHtCapability->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 ((pHtCapability->HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth) +#ifdef CONFIG_STA_SUPPORT + &&( (INFRA_ON(pAd) && pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) + || !INFRA_ON(pAd)) +#endif /* CONFIG_STA_SUPPORT */ + ) + { + DBGPRINT(RT_DEBUG_TRACE, ("MeshBuildOpen BW_40 %d %d \n",INFRA_ON(pAd),pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth)); + pEntry->MaxHTPhyMode.field.BW= BW_40; + pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(pHtCapability->HtCapInfo.ShortGIfor40)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("MeshBuildOpen BW_20 \n")); + 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 (i=15; i>=0; i--) */ + for (i=23; i>=0; i--) /* 3*3 */ + { + j = i/8; + bitmask = (1<<(i-(j*8))); + if ( (pAd->MeshTab.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (pHtCapability->MCSSet[j]&bitmask)) + { + pEntry->MaxHTPhyMode.field.MCS = i; + break; + } + if (i==0) + break; + } + + if (pAd->MeshTab.DesiredTransmitSetting.field.MCS != MCS_AUTO) + { + + DBGPRINT(RT_DEBUG_OFF, ("@@@ pAd->CommonCfg.RegTransmitSetting.field.MCS = %d\n", + pAd->MeshTab.DesiredTransmitSetting.field.MCS)); + if (pAd->MeshTab.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->MeshTab.HTPhyMode.field.MCS) + { + /* STA supports fixed MCS */ + pEntry->MaxHTPhyMode.field.MCS = pAd->MeshTab.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; + + /* 1. The user-define configuration or */ + /* 2. Not ralink-chipset and the encryption mode is WEP or TKIP (for fix Atheros STA issue in MacBook) */ + 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)); + } +#endif /* DOT11_N_SUPPORT */ + + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + + pEntry->CurrTxRate = pEntry->MaxSupportedRate; + + 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); + } + + /* Set asic auto fall back */ + if (pAd->MeshTab.bAutoTxRateSwitch == TRUE) + { + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, pEntry, &pEntry->pTable, &TableSize, &pEntry->CurrTxRateIndex); + /*AsicUpdateAutoFallBackTable(pAd, pTable); */ + pEntry->bAutoTxRateSwitch = TRUE; + } + else + { + pEntry->HTPhyMode.field.MODE = pAd->MeshTab.HTPhyMode.field.MODE; + pEntry->HTPhyMode.field.MCS = pAd->MeshTab.HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + + RTMPUpdateLegacyTxSetting((UCHAR)pAd->MeshTab.DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + + pEntry->RateLen = SupRateLen; + + StatusCode = MLME_SUCCESS; + } + } while(FALSE); + + return StatusCode; +} + +VOID MeshPeerLinkOpenProcess( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PHEADER_802_11 pHeader = (PHEADER_802_11)pRxBlk->pHeader; + PUCHAR pFrame; + ULONG FrameLen; + UINT MeshLinkId = 0; + MESH_LINK_OPEN_MSG_STRUCT PeerLinkOpen; + + UINT16 CapabilityInfo; + UCHAR SupRateLen = 0; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR MeshIdLen; + UCHAR MeshId[MAX_MESH_ID_LEN] = {0}; + UINT8 MeshSelPathId = 0xff; + UINT8 MeshSelMetricId = 0xff; + UINT32 CPI = 0; + MESH_CAPABILITY MeshCapabilty; + UINT16 PeerLinkId = 0; + BOOLEAN bWmmCapable = FALSE; + HT_CAPABILITY_IE HTCapability; + UCHAR HTCapability_Len = 0; + UCHAR MaxSupportedRate = 0; + + UCHAR RSNIE_Len; + UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; + MESH_SECURITY_CAPABILITY_IE PeerMscIe; + UCHAR PeerMsaIe[MESH_MAX_MSAIE_LEN]; + UCHAR PeerMsaIeLen = 0; + PMESH_LINK_ENTRY pMeshLinkEntry; + + MESH_LINK_MNG_EVENT result = MESH_LINK_MNG_OPEN_ACPT; + UINT16 ReasonCode = MLME_SUCCESS; + + NdisZeroMemory(&HTCapability, sizeof(HT_CAPABILITY_IE)); + + do + { + UCHAR i; + ULONG Idx; + UCHAR MeshHdrLen; + UCHAR pure_rsn_len = 0; /* exclude elementID, length and PMKID */ + UCHAR pmkid_len = 0; + + MeshHdrLen = GetMeshHederLen(pRxBlk->pData); + /* skip Mesh Header */ + pRxBlk->pData += MeshHdrLen; + pRxBlk->DataSize -= MeshHdrLen; + + /* skip Category and ActionCode */ + pFrame = (PUCHAR)(pRxBlk->pData + 2); + FrameLen = pRxBlk->DataSize - 2; + + NdisZeroMemory(RSN_IE, MAX_LEN_OF_RSNIE); + NdisZeroMemory(PeerMsaIe, MESH_MAX_MSAIE_LEN); + + MeshLinkMngOpenSanity( pAd, + pFrame, + FrameLen, + &CapabilityInfo, + SupRate, + &SupRateLen, + &MeshIdLen, + MeshId, + &MeshSelPathId, + &MeshSelMetricId, + &CPI, + &MeshCapabilty, + &PeerLinkId, + &PeerMscIe, + PeerMsaIe, + &PeerMsaIeLen, + RSN_IE, + &RSNIE_Len, + &bWmmCapable, + &HTCapability, + &HTCapability_Len); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: PeerLinkId=%x, PeerMac=%02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, PeerLinkId, pHeader->Addr2[0], pHeader->Addr2[1], pHeader->Addr2[2], + pHeader->Addr2[3], pHeader->Addr2[4], pHeader->Addr2[5])); + + Idx = GetMeshLinkId(pAd, (PCHAR)pHeader->Addr2); + if (Idx == BSS_NOT_FOUND) + { + Idx = MeshLinkAlloc(pAd, pHeader->Addr2, MESH_LINK_DYNAMIC); + if (Idx == BSS_NOT_FOUND) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() OpenRjct, PeerLink Not found.\n", __FUNCTION__)); + result = MESH_LINK_MNG_OPEN_RJCT; + ReasonCode = MESH_MAX_PEERS; + EnquePeerLinkCloseEx(pAd, pHeader->Addr2, RandomLinkId(pAd), PeerLinkId, ReasonCode); + return; + } + } + + MeshLinkId = (UINT)Idx; + pMeshLinkEntry = &pAd->MeshTab.MeshLink[MeshLinkId].Entry; + + if (MeshTableLookup(pAd, pHeader->Addr2, TRUE)) + { + /* peer link exist already. */ + /* check peer link Id. */ + if (PeerLinkId != pAd->MeshTab.MeshLink[Idx].Entry.PeerLinkId) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() OpenRjct, PeerLinkId not match. %x, %x\n", + __FUNCTION__, PeerLinkId, pAd->MeshTab.MeshLink[Idx].Entry.PeerLinkId)); + result = MESH_LINK_MNG_OPEN_RJCT; + ReasonCode = MLME_UNSPECIFY_FAIL; + } + break; + } + + if (!(NdisEqualMemory(MeshId, pAd->MeshTab.MeshId, pAd->MeshTab.MeshIdLen) + && (MeshSelPathId == pAd->MeshTab.PathProtocolId) + && (MeshSelMetricId == pAd->MeshTab.PathMetricId))) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() OpenIgnr, Link Instance Not match.\n", __FUNCTION__)); + result = MESH_LINK_MNG_OPEN_IGNR; + ReasonCode = MLME_UNSPECIFY_FAIL; + break; + } + + if (!MeshCapabilty.field.AcceptPeerLinks) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() OpenRjct, Not AcceptPeerLinks.\n", __FUNCTION__)); + result = MESH_LINK_MNG_OPEN_RJCT; + ReasonCode = MESH_MAX_PEERS; + break; + } + + /* Verify the length of the received MSAIE */ + if (PeerMsaIeLen < sizeof(MSA_HANDSHAKE_IE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("The received length of MSAIE is too short(%d)\n", PeerMsaIeLen)); + result = MESH_LINK_MNG_OPEN_RJCT; + ReasonCode = MESH_SECURITY_FAILED_VERIFICATION; + break; + } + + if (PeerMscIe.MeshSecurityConfig.field.DefaultRole != + pAd->MeshTab.LocalMSCIE.MeshSecurityConfig.field.DefaultRole) + { + DBGPRINT(RT_DEBUG_ERROR, ("The Default Role Negotiation doesn't match(%d) \n", PeerMscIe.MeshSecurityConfig.field.DefaultRole)); + result = MESH_LINK_MNG_OPEN_RJCT; + ReasonCode = MESH_SECURITY_ROLE_NEGOTIATION_DIFFERS; + break; + } + + if (!MeshValidateRSNIE(pAd, RSN_IE, RSNIE_Len, &pure_rsn_len, &pmkid_len)) + { + result = MESH_LINK_MNG_OPEN_RJCT; + ReasonCode = MESH_SECURITY_FAILED_VERIFICATION; + break; + } + + hex_dump("Peer MSA IE", PeerMsaIe, PeerMsaIeLen); + + /* Sanity check the selected AKM and pairwise-cipher of MSAIE in */ + /* the received peer link open frame */ + if ((ReasonCode = MeshCheckPeerMsaIeCipherValidity(pAd, + SUBTYPE_PEER_LINK_OPEN, + pMeshLinkEntry, + PeerMsaIe)) != MLME_SUCCESS) + { + result = MESH_LINK_MNG_OPEN_RJCT; + break; + } + + /* Determine if the local MP is the Authenticator MP */ + ValidateLocalMPAsAuthenticator(pAd, MeshLinkId, (PUCHAR)&PeerMscIe, PeerMsaIe); + + if (!MeshKeySelectionAction(pAd, pMeshLinkEntry, (PUCHAR)&PeerMscIe, &RSN_IE[RSNIE_Len-pmkid_len], pmkid_len)) + { + DBGPRINT(RT_DEBUG_ERROR, ("No any MP connect to MKD !!! \n")); + result = MESH_LINK_MNG_OPEN_RJCT; + ReasonCode = MESH_SECURITY_AUTHENTICATION_IMPOSSBLE; + break; + } + + if (PeerLinkCfnRcvd(pAd, Idx)) + { + if ((ReasonCode = MeshValidateOpenAndCfnPeerLinkMsg(pAd, + SUBTYPE_PEER_LINK_OPEN, + pMeshLinkEntry, + (PUCHAR)&PeerMscIe, + PeerMsaIe, + PeerMsaIeLen, + RSN_IE, + RSNIE_Len, + pure_rsn_len, + pmkid_len)) != MLME_SUCCESS) + { + result = MESH_LINK_MNG_OPEN_RJCT; + break; + } + + } + /* Record these information for peer link confirm frame check later */ + else + { + /* Record the peer RSNIE */ + if (RSNIE_Len > 0) + { + /* record the peer RSNIE except element-ID, length and the PMKID list. */ + NdisMoveMemory(pMeshLinkEntry->RcvdRSNIE, &RSN_IE[2], pure_rsn_len); + pMeshLinkEntry->RcvdRSNIE_Len = pure_rsn_len; + + hex_dump("RSNIE in PL-open ", pMeshLinkEntry->RcvdRSNIE, pMeshLinkEntry->RcvdRSNIE_Len); + + if (pmkid_len > 0) + { + /* Record the PMKID fields (include PMKID-count and PMKID-list) */ + NdisMoveMemory(pMeshLinkEntry->RcvdPMKID, &RSN_IE[RSNIE_Len-pmkid_len], pmkid_len); + pMeshLinkEntry->RcvdPMKID_Len = pmkid_len; + + hex_dump("PMKID in PL-open ", pMeshLinkEntry->RcvdPMKID, pMeshLinkEntry->RcvdPMKID_Len); + } + } + + /* Record the peer MSCIE */ + NdisMoveMemory((PUCHAR)&pMeshLinkEntry->RcvdMscIe, (PUCHAR)&PeerMscIe, sizeof(MESH_SECURITY_CAPABILITY_IE)); + + /* Record the peer MSAIE */ + NdisMoveMemory(pMeshLinkEntry->RcvdMsaIe, PeerMsaIe, PeerMsaIeLen); + pMeshLinkEntry->RcvdMsaIeLen = PeerMsaIeLen; + + } + + /* supported rates array may not be sorted. sort it and find the maximum rate */ + for (i=0; ipHeader; + PUCHAR pFrame; + ULONG FrameLen; + UINT MeshLinkId = 0; + MESH_LINK_CONFIRM_MSG_STRUCT PeerLinkCnf; + + UINT16 CapabilityInfo; + UCHAR SupRateLen = 0; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR MeshIdLen; + UCHAR MeshId[MAX_MESH_ID_LEN] = {0}; + UINT8 MeshSelPathId = 0xff; + UINT8 MeshSelMetricId = 0xff; + UINT32 CPI = 0; + MESH_CAPABILITY MeshCapabilty; + UINT16 StatusCode; + UINT16 Aid; + UINT16 LocalLinkId = 0; + UINT16 PeerLinkId = 0; + UCHAR RSNIE_Len; + UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; + MESH_SECURITY_CAPABILITY_IE PeerMscIe; + UCHAR PeerMsaIe[MESH_MAX_MSAIE_LEN]; + UCHAR PeerMsaIeLen = 0; + HT_CAPABILITY_IE HTCapability; + UCHAR HTCapability_Len; + + PMESH_LINK_ENTRY pMeshLinkEntry; + + MESH_LINK_MNG_EVENT result = MESH_LINK_MNG_CFN_ACPT; + UINT16 ReasonCode = MLME_SUCCESS; + + do + { + ULONG Idx; + UCHAR MeshHdrLen; + UCHAR pure_rsn_len = 0; /* exclude elementID, length and PMKID */ + UCHAR pmkid_len = 0; + + Idx = GetMeshLinkId(pAd, (PCHAR)pHeader->Addr2); + if (Idx == BSS_NOT_FOUND) + { + result = MESH_LINK_MNG_CFN_IGNR; + ReasonCode = MLME_UNSPECIFY_FAIL; + return; + } + MeshLinkId = (UINT)Idx; + pMeshLinkEntry = &pAd->MeshTab.MeshLink[MeshLinkId].Entry; + + MeshHdrLen = GetMeshHederLen(pRxBlk->pData); + /* skip Mesh Header */ + pRxBlk->pData += MeshHdrLen; + pRxBlk->DataSize -= MeshHdrLen; + + /* skip Category and ActionCode */ + pFrame = (PUCHAR)(pRxBlk->pData + 2); + FrameLen = pRxBlk->DataSize - 2; + + MeshLinkMngCfnSanity( pAd, + pFrame, + FrameLen, + &CapabilityInfo, + &StatusCode, + &Aid, + SupRate, + &SupRateLen, + &MeshIdLen, + MeshId, + &MeshSelPathId, + &MeshSelMetricId, + &CPI, + &MeshCapabilty, + &LocalLinkId, + &PeerLinkId, + &PeerMscIe, + PeerMsaIe, + &PeerMsaIeLen, + RSN_IE, + &RSNIE_Len, + &HTCapability, + &HTCapability_Len); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: LocalLinkId=%x, PeerLinkId=%x, PeerMac=%02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, LocalLinkId, PeerLinkId, pHeader->Addr2[0], pHeader->Addr2[1], + pHeader->Addr2[2], pHeader->Addr2[3], pHeader->Addr2[4], pHeader->Addr2[5])); + + if (!(NdisEqualMemory(MeshId, pAd->MeshTab.MeshId, pAd->MeshTab.MeshIdLen) + && (MeshSelPathId == pAd->MeshTab.PathProtocolId) + && (MeshSelMetricId == pAd->MeshTab.PathMetricId))) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() CfnIgnr, Link Instance Not match.\n", __FUNCTION__)); + result = MESH_LINK_MNG_CFN_IGNR; + ReasonCode = MLME_UNSPECIFY_FAIL; + break; + } + + if (StatusCode != MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() CfnRjct, Status Code=%d.\n", __FUNCTION__, StatusCode)); + result = MESH_LINK_MNG_CFN_RJCT; + ReasonCode = MLME_UNSPECIFY_FAIL; + break; + } + + if (PeerLinkId != pAd->MeshTab.MeshLink[MeshLinkId].Entry.LocalLinkId) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() CfnRjct, Link Id Not match. %x, %x\n", + __FUNCTION__, PeerLinkId, pAd->MeshTab.MeshLink[MeshLinkId].Entry.LocalLinkId)); + result = MESH_LINK_MNG_CFN_RJCT; + ReasonCode = MLME_UNSPECIFY_FAIL; + break; + } + + /* Verify the received RSNIE */ + if (!MeshValidateRSNIE(pAd, RSN_IE, RSNIE_Len, &pure_rsn_len, &pmkid_len)) + { + result = MESH_LINK_MNG_CFN_RJCT; + ReasonCode = MESH_SECURITY_FAILED_VERIFICATION; + break; + } + + /* Verify the length of the received MSAIE */ + if (PeerMsaIeLen < sizeof(MSA_HANDSHAKE_IE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("The received length of MSAIE in P.L. confirm frame is too short(%d)\n", PeerMsaIeLen)); + result = MESH_LINK_MNG_CFN_RJCT; + ReasonCode = MESH_SECURITY_FAILED_VERIFICATION; + break; + } + + /* If the local MP has received a peer link open */ + /* frame from the candidate peer MP, the local MP shall: */ + if (PeerLinkOpnRcvd(pAd, Idx)) + { + if ((ReasonCode = MeshValidateOpenAndCfnPeerLinkMsg(pAd, + SUBTYPE_PEER_LINK_CONFIRM, + pMeshLinkEntry, + (PUCHAR)&PeerMscIe, + PeerMsaIe, + PeerMsaIeLen, + RSN_IE, + RSNIE_Len, + pure_rsn_len, + pmkid_len)) != MLME_SUCCESS) + { + result = MESH_LINK_MNG_OPEN_RJCT; + break; + } + } + /* On the other hand, if the local MP has not received a peer link open frame from the candidate peer MP, */ + else + { + /* Sanity check the selected AKM and pairwise-cipher of MSAIE in */ + /* the received peer link confirm frame */ + if ((ReasonCode = MeshCheckPeerMsaIeCipherValidity(pAd, + SUBTYPE_PEER_LINK_CONFIRM, + pMeshLinkEntry, + PeerMsaIe)) != MLME_SUCCESS) + { + result = MESH_LINK_MNG_OPEN_RJCT; + break; + } + } + + + /* Record the received RSNIE, MSCIE and MSAIE */ + { + if (RSNIE_Len > 0) + { + /* record the peer RSNIE except element-ID, length and the PMKID list. */ + NdisMoveMemory(pMeshLinkEntry->RcvdRSNIE, &RSN_IE[2], pure_rsn_len); + pMeshLinkEntry->RcvdRSNIE_Len = pure_rsn_len; + + hex_dump("RSNIE in PL-confirm ", pMeshLinkEntry->RcvdRSNIE, pMeshLinkEntry->RcvdRSNIE_Len); + + if (pmkid_len > 0) + { + /* Record the PMKID fields (include PMKID-count and PMKID-list) */ + NdisMoveMemory(pMeshLinkEntry->RcvdPMKID, &RSN_IE[RSNIE_Len-pmkid_len], pmkid_len); + pMeshLinkEntry->RcvdPMKID_Len = pmkid_len; + + hex_dump("PMKID in PL-confirm ", pMeshLinkEntry->RcvdPMKID, pMeshLinkEntry->RcvdPMKID_Len); + } + } + + NdisMoveMemory((PUCHAR)&pMeshLinkEntry->RcvdMscIe, (PUCHAR)&PeerMscIe, sizeof(MESH_SECURITY_CAPABILITY_IE)); + + NdisMoveMemory(pMeshLinkEntry->RcvdMsaIe, PeerMsaIe, PeerMsaIeLen); + pMeshLinkEntry->RcvdMsaIeLen = PeerMsaIeLen; + } + + /* Got Peer link confirm. reset OpenRetryCnt; */ + pAd->MeshTab.MeshLink[MeshLinkId].Entry.OpenRetyCnt = 0; + } while(FALSE); + + PeerLinkCnf.CPI = CPI; + PeerLinkCnf.StatusCode = StatusCode; + PeerLinkCnf.Aid = Aid; + PeerLinkCnf.MeshCapabilty = MeshCapabilty.word; + PeerLinkCnf.LocalLinkId = PeerLinkId; + PeerLinkCnf.PeerLinkId = LocalLinkId; + PeerLinkCnf.ReasonCode = ReasonCode; + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, result, + sizeof(MESH_LINK_CONFIRM_MSG_STRUCT), &PeerLinkCnf, MeshLinkId); + + MeshMlmeHandler(pAd); + + return; +} + +VOID MeshPeerLinkCloseProcess( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PHEADER_802_11 pHeader = (PHEADER_802_11)pRxBlk->pHeader; + PUCHAR pFrame; + ULONG FrameLen; + UINT MeshLinkId = 0; + MESH_LINK_CLOSE_MSG_STRUCT PeerLinkClose; + + UINT16 LocalLinkId = 0; + UINT16 PeerLinkId = 0; + UINT16 ReasonCode = 0; + + MESH_LINK_MNG_EVENT result = MESH_LINK_MNG_CLS_ACPT; + + do + { + ULONG Idx; + UCHAR MeshHdrLen; + + Idx = GetMeshLinkId(pAd, (PCHAR)pHeader->Addr2); + if (Idx == BSS_NOT_FOUND) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() ClsIgnore, PeerLink Not found.\n", __FUNCTION__)); + result = MESH_LINK_MNG_CLS_IGNR; + ReasonCode = MLME_UNSPECIFY_FAIL; + return; + } + MeshLinkId = (UINT)Idx; + + MeshHdrLen = GetMeshHederLen(pRxBlk->pData); + /* skip Mesh Header */ + pRxBlk->pData += MeshHdrLen; + pRxBlk->DataSize -= MeshHdrLen; + + /* skip Category and ActionCode */ + pFrame = (PUCHAR)(pRxBlk->pData + 2); + FrameLen = pRxBlk->DataSize - 2; + + NdisMoveMemory(&ReasonCode, pFrame, 2); + pFrame += 2; + FrameLen -= 2; + + MeshLinkMngClsSanity( pAd, + pFrame, + FrameLen, + &LocalLinkId, + &PeerLinkId, + &ReasonCode); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: LocalLinkId=%x, PeerLinkId=%x, Reason=%d, PeerMac=%02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, LocalLinkId, PeerLinkId, ReasonCode, pHeader->Addr2[0], pHeader->Addr2[1], + pHeader->Addr2[2], pHeader->Addr2[3], pHeader->Addr2[4], pHeader->Addr2[5])); + + if ((PeerLinkId != pAd->MeshTab.MeshLink[MeshLinkId].Entry.LocalLinkId) + || (LocalLinkId != pAd->MeshTab.MeshLink[MeshLinkId].Entry.PeerLinkId)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() ClsIgnr, Link Id Not match.\n", __FUNCTION__)); + result = MESH_LINK_MNG_CLS_IGNR; + ReasonCode = MLME_UNSPECIFY_FAIL; + break; + } + } while (FALSE); + + PeerLinkClose.LocalLinkId = LocalLinkId; + PeerLinkClose.PeerLinkId = PeerLinkId; + PeerLinkClose.ReasonCode = ReasonCode; + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, result, + sizeof(MESH_LINK_CLOSE_MSG_STRUCT), &PeerLinkClose, MeshLinkId); + + MeshMlmeHandler(pAd); + + return; +} + +VOID MeshLinkTableMaintenace( + IN PRTMP_ADAPTER pAd) +{ + UCHAR idx; + ULONG Now; + + NdisGetSystemUpTime(&Now); + + for (idx = 0; idx < MAX_MESH_LINKS; idx++) + { + if (PeerLinkValidCheck(pAd, idx) == FALSE) + continue; +/*+++didn't use now */ +/*---didn't use now */ + pAd->MeshTab.MeshLink[idx].Entry.OneSecBeaconCount=0; + + if (RTMP_TIME_AFTER(Now, pAd->MeshTab.MeshLink[idx].Entry.LastBeaconTime + (MESH_AGEOUT_TIME * OS_HZ / 1000))) + { + DBGPRINT(RT_DEBUG_TRACE, ("ageout MESH #%d.\n", idx)); + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_CNCL, 0, NULL, idx); + } + } + + return; +} + +#endif /* MESH_SUPPORT*/ + diff --git a/mt7620/src/common/mesh_path_mng.c b/mt7620/src/common/mesh_path_mng.c new file mode 100644 index 0000000..9bdaa7c --- /dev/null +++ b/mt7620/src/common/mesh_path_mng.c @@ -0,0 +1,1769 @@ +/* + *************************************************************************** + * 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: + mesh_forwarding.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Arvin 2007-07-04 For mesh (802.11s) support. +*/ +#ifdef MESH_SUPPORT + + +#include "rt_config.h" +#include "mesh_def.h" +#include "mesh_sanity.h" + + +VOID +MeshPreqRcvProcess( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PHEADER_802_11 pHeader = (PHEADER_802_11)pRxBlk->pHeader; + UINT8 MeshTTL = 0; + UINT32 MeshSeq = 0; + UCHAR Ie; + UCHAR IeLen; + UINT8 PreqFlag; + UCHAR PreqHopCount; + UCHAR PreqTTL; + UINT32 PreqID; + UCHAR PreqOrigAddr[MAC_ADDR_LEN]; + UINT32 PreqOrigDsn; + UCHAR PreqProxyAddr[MAC_ADDR_LEN]; + PUCHAR pPreqProxyAddr = NULL; + UINT32 PreqLifeTime; + UINT32 Metric; + UCHAR PreqDestCount; + MESH_DEST_ENTRY PreqDestEntry; + UCHAR VarOffset; + MESH_ROUTING_ENTRY *pRouteEntry; + PMAC_TABLE_ENTRY pMacEntry = NULL; + PMESH_ENTRY pMeshEntry = NULL; + BOOLEAN bForward = TRUE; + PUCHAR pFrame; + ULONG FrameLen; + PUCHAR pMeshHdr = (PUCHAR)(pRxBlk->pData); + UINT MeshHdrLen; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> MeshPreqRcvProcess\n")); + + if (GetMeshLinkId(pAd, (PCHAR)pHeader->Addr2) == BSS_NOT_FOUND) + return; + + + MeshTTL = GetMeshTTL(pMeshHdr); + MeshSeq = GetMeshSeq(pMeshHdr); + + if (--MeshTTL <= 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("Mesh Time to Live is zero !\n")); + return; + } + + MeshHdrLen = GetMeshHederLen(pRxBlk->pData); + /* skip Mesh Header */ + pRxBlk->pData += MeshHdrLen; + pRxBlk->DataSize -= MeshHdrLen; + + /* skip Category and ActionCode */ + pFrame = (PUCHAR)(pRxBlk->pData + 2); + FrameLen = pRxBlk->DataSize - 2; + + VarOffset = 0; + /* Get Path Select IE */ + NdisMoveMemory(&Ie, pFrame + VarOffset, 1); + VarOffset += 1; + if (Ie != IE_MESH_PREQ) + { + DBGPRINT(RT_DEBUG_ERROR, ("Receive frame packet Element IE wrong. The IE are not Path Request!!!\n")); + return; + } + + /* Get IE length */ + NdisMoveMemory(&IeLen, pFrame + VarOffset, 1); + VarOffset += 1; + + if (IeLen < 37) + { + DBGPRINT(RT_DEBUG_ERROR, ("Receive frame packet length wrong, the length must > 37!!!\n")); + return; + } + + /* Get Path Request Flags */ + NdisMoveMemory(&PreqFlag, pFrame + VarOffset, 1); + VarOffset += 1; + + /* Get HopCount */ + NdisMoveMemory(&PreqHopCount, pFrame + VarOffset, 1); + VarOffset += 1; + + /* Get Path Request TTL */ + NdisMoveMemory(&PreqTTL, pFrame + VarOffset, 1); + VarOffset += 1; + + /* Get Path Request ID */ + NdisMoveMemory(&PreqID, pFrame + VarOffset, 4); + VarOffset += 4; + PreqID = le2cpu32(PreqID); + + /* Get Originator Address */ + NdisMoveMemory(&PreqOrigAddr, pFrame + VarOffset, 6); + VarOffset += 6; + + /* Check the MP whether it's Originator of PREQ. */ + if (MAC_ADDR_EQUAL(pAd->MeshTab.CurrentAddress, PreqOrigAddr)) + return; + + /* Get Originator Dsn */ + NdisMoveMemory(&PreqOrigDsn, pFrame + VarOffset, 4); + VarOffset += 4; + PreqOrigDsn = le2cpu32(PreqOrigDsn); + + if (((PMESH_PREQ_FLAG)&PreqFlag)->field.AE == 1) + { + /* Get Proxy Address */ + NdisMoveMemory(&PreqProxyAddr, pFrame + VarOffset, 6); + pPreqProxyAddr = PreqProxyAddr; + VarOffset += 6; + } + + /* Get Life Time */ + NdisMoveMemory(&PreqLifeTime, pFrame + VarOffset, 4); + VarOffset += 4; + PreqLifeTime = le2cpu32(PreqLifeTime); + + /* Get Metric */ + NdisMoveMemory(&Metric, pFrame + VarOffset, 4); + VarOffset += 4; + Metric = le2cpu32(Metric); + + /* Get DestCount */ + NdisMoveMemory(&PreqDestCount, pFrame + VarOffset, 1); + VarOffset += 1; + + /* Get MeshDestEntry */ + NdisMoveMemory(&PreqDestEntry, pFrame + VarOffset, 11); + + if (IeLen < (26 + (PreqDestCount * 11))) + { + DBGPRINT(RT_DEBUG_ERROR, ("Receive frame packet format wrong!!!\n")); + return; + } + + /* create or update Originator route path on our route table */ + pMacEntry = MeshTableLookup(pAd, pHeader->Addr2, TRUE); + + /* check Transmission MP already exist on our LinkMP table. */ + if (pMacEntry == NULL) + return; + + + pRouteEntry = MeshRoutingTableLookup(pAd, PreqOrigAddr); + + if (pRouteEntry) + { + /* check whether the Originator Dsn < previous Originator Dsn */ + if (pRouteEntry->Dsn > PreqOrigDsn) + { + DBGPRINT(RT_DEBUG_TRACE, ("The Originator DSN=(%d) < previous Originator DSN=(%d)!!!\n", + PreqOrigDsn, pRouteEntry->Dsn)); + bForward = FALSE; + } + + /* (DSN = previous DSN) AND (updated path metric is worse than previous path metric) */ + if (pRouteEntry->Dsn == PreqOrigDsn) + { + if (pRouteEntry->PathMetric <= (Metric + pAd->MeshTab.MeshLink[pMacEntry->MatchMeshTabIdx].Entry.Metrics)) + { + DBGPRINT(RT_DEBUG_TRACE, ("The Originator Metric=(%d) > previous Originator metric=(%d)!!!\n", + Metric, pRouteEntry->PathMetric)); + bForward = FALSE; + } + } + + if (bForward == TRUE) + pRouteEntry = MeshRoutingTableUpdate(pAd, + PreqOrigAddr, + PreqOrigDsn, + pHeader->Addr2, + pMacEntry->MatchMeshTabIdx, + Metric + pAd->MeshTab.MeshLink[pMacEntry->MatchMeshTabIdx].Entry.Metrics); + + if (((PMESH_PREQ_FLAG)&PreqFlag)->field.AE == 1) + { + pMeshEntry = MeshEntryTableLookUp(pAd, PreqProxyAddr); + + if (pMeshEntry == NULL) + MeshEntryTableInsert(pAd, + PreqProxyAddr, + pRouteEntry->Idx); + else + MeshEntryTableUpdate(pAd, + PreqProxyAddr, + pRouteEntry->Idx); + } + + pMeshEntry = MeshEntryTableLookUp(pAd, PreqOrigAddr); + + if (pMeshEntry == NULL) + MeshEntryTableInsert(pAd, + PreqOrigAddr, + pRouteEntry->Idx); + else + MeshEntryTableUpdate(pAd, + PreqOrigAddr, + pRouteEntry->Idx); + } + else + { + pRouteEntry = MeshRoutingTableInsert(pAd, + PreqOrigAddr, + PreqOrigDsn, + pHeader->Addr2, + pMacEntry->MatchMeshTabIdx, + Metric + pAd->MeshTab.MeshLink[pMacEntry->MatchMeshTabIdx].Entry.Metrics); + + if (((PMESH_PREQ_FLAG)&PreqFlag)->field.AE == 1) + { + pMeshEntry = MeshEntryTableLookUp(pAd, PreqProxyAddr); + + if (pMeshEntry == NULL) + MeshEntryTableInsert(pAd, + PreqProxyAddr, + pRouteEntry->Idx); + else + MeshEntryTableUpdate(pAd, + PreqProxyAddr, + pRouteEntry->Idx); + } + + pMeshEntry = MeshEntryTableLookUp(pAd, PreqOrigAddr); + + if (pMeshEntry == NULL) + MeshEntryTableInsert(pAd, + PreqOrigAddr, + pRouteEntry->Idx); + else + MeshEntryTableUpdate(pAd, + PreqOrigAddr, + pRouteEntry->Idx); + } + + /* create or update neighbor MP route path on our route table */ + if (!MAC_ADDR_EQUAL(PreqOrigAddr, pHeader->Addr2)) + { + pMeshEntry = MeshEntryTableLookUp(pAd, pHeader->Addr2); + pRouteEntry = MeshRoutingTableLookup(pAd, pHeader->Addr2); + + if (pMeshEntry && pRouteEntry) + { + /* update neighbor MP route information */ + MeshRoutingTableUpdate(pAd, + pHeader->Addr2, + 0, + pHeader->Addr2, + pMacEntry->MatchMeshTabIdx, + pAd->MeshTab.MeshLink[pMacEntry->MatchMeshTabIdx].Entry.Metrics); + MeshEntryTableUpdate(pAd, + pHeader->Addr2, + pRouteEntry->Idx); + } + else + { + if (pRouteEntry == NULL) + pRouteEntry = MeshRoutingTableInsert(pAd, + pHeader->Addr2, + 0, + pHeader->Addr2, + pMacEntry->MatchMeshTabIdx, + pAd->MeshTab.MeshLink[pMacEntry->MatchMeshTabIdx].Entry.Metrics); + else + pRouteEntry = MeshRoutingTableUpdate(pAd, + pHeader->Addr2, + 0, + pHeader->Addr2, + pMacEntry->MatchMeshTabIdx, + pAd->MeshTab.MeshLink[pMacEntry->MatchMeshTabIdx].Entry.Metrics); + + if (pMeshEntry == NULL) + MeshEntryTableInsert(pAd, + pHeader->Addr2, + pRouteEntry->Idx); + else + MeshEntryTableUpdate(pAd, + pHeader->Addr2, + pRouteEntry->Idx); + } + } + + + if (MeshAllowToSendPathResponse(pAd, PreqDestEntry.DestAddr)) + { + pRouteEntry = MeshRoutingTableLookup(pAd, PreqOrigAddr); + + if (pRouteEntry) + if ((pRouteEntry->Dsn <= PreqOrigDsn) || + (pRouteEntry->PathMetric >= (Metric + pAd->MeshTab.MeshLink[pMacEntry->MatchMeshTabIdx].Entry.Metrics))) + { + if (MAC_ADDR_EQUAL(pAd->MeshTab.CurrentAddress, PreqDestEntry.DestAddr)) + { + MeshPrepCreate(pAd, pRouteEntry->NextHop, pRouteEntry->MeshDA, pRouteEntry->Dsn, NULL); + } + else + { + MeshPrepCreate(pAd, pRouteEntry->NextHop, pRouteEntry->MeshDA, pRouteEntry->Dsn, PreqDestEntry.DestAddr); + } + } + + bForward = FALSE; + } + + if (bForward == TRUE) + { + if (pAd->MeshTab.MeshCapability.field.Forwarding == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("Mesh Forwarding bit disable !!!\n")); + goto out; + } + + if (PreqTTL <= 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("MeshPreqRcvProcess: PreqTTL = 0 !!!\n")); + } + else + { + MeshPreqForward(pAd, + MeshTTL, + MeshSeq, + PreqFlag, + PreqHopCount, + PreqTTL, + PreqID, + PreqOrigAddr, + PreqOrigDsn, + pPreqProxyAddr, + PreqLifeTime, + (Metric + pAd->MeshTab.MeshLink[pMacEntry->MatchMeshTabIdx].Entry.Metrics), + PreqDestCount, + PreqDestEntry, + pHeader->Addr2); + } + } + +out: + + DBGPRINT(RT_DEBUG_TRACE, ("<----- MeshPreqRcvProcess\n")); + + return; +} + +VOID +MeshPreqCreate( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pProxyAddr, + IN PUCHAR pDestAddr, + IN ULONG DestDsn) +{ + HEADER_802_11 MeshHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + MESH_FLAG MeshFlag; + MESH_PREQ_FLAG MeshPreqFlag; + MESH_DEST_ENTRY MeshDestEntry; + UINT32 MeshHeaderSeq; + UINT32 MeshPreqID; + ULONG OrigDsn; + UCHAR i = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> MeshPreqCreate\n")); + + MeshHeaderSeq = INC_MESH_SEQ(pAd->MeshTab.MeshSeq); + MeshPreqID = pAd->MeshTab.MeshPreqID++; + OrigDsn = pAd->MeshTab.MeshOriginatorDsn++; + + for(i = 0; i < MAX_MESH_LINKS; i++) + { + if (PeerLinkValidCheck(pAd, i) == TRUE) + { + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /*Get an unused nonpaged memory */ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("Mesh - %s() allocate memory failed \n", __FUNCTION__)); + return; + } + + /* send metrics report frame to (DestAddrs). */ + EnqueuePeerLinkMetricReport(pAd, + pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr, + MESH_LinkMetricUpdate(pAd, (PCHAR)pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr)); + + MeshHeaderInit(pAd, &MeshHdr, + pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr, /*Addr1 */ + pAd->MeshTab.CurrentAddress, /*Addr2 */ + ZERO_MAC_ADDR); /*Addr3 */ + + NdisMoveMemory(pOutBuffer, (PCHAR)&MeshHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + /* Mesh Header */ + MeshFlag.word = 0; + MeshFlag.field.AE = 0; + InsertMeshHeader(pAd, + (pOutBuffer + FrameLen), + &FrameLen, MeshFlag.word, + pAd->MeshTab.TTL, + MeshHeaderSeq, + NULL, + NULL, + NULL); + + /* Action field */ + InsertMeshActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_MESH_PATH_SELECTION, ACT_CODE_PATH_REQUEST); + + + MeshPreqFlag.word = 0; + MeshPreqFlag.field.PortalRole = 0; + MeshPreqFlag.field.AddrType = 0; + MeshPreqFlag.field.ProactivePrep = 0; + + if (pProxyAddr) + MeshPreqFlag.field.AE = 1; + else + MeshPreqFlag.field.AE = 0; + + + MeshDestEntry.PerDestFlag = 0; + ((PMESH_PER_DEST_FLAG)&MeshDestEntry.PerDestFlag)->field.DO = 1; + ((PMESH_PER_DEST_FLAG)&MeshDestEntry.PerDestFlag)->field.RF = 1; + COPY_MAC_ADDR(MeshDestEntry.DestAddr, pDestAddr); + MeshDestEntry.Dsn = DestDsn; + + /* The Destination Address is the MAC address of the destination MP. */ + InsertMeshPathRequestIE(pAd, + (pOutBuffer + FrameLen), + &FrameLen, MeshPreqFlag.word, + 0, + HWMP_NET_DIAMETER, + MeshPreqID, + pAd->MeshTab.CurrentAddress, + OrigDsn, + pProxyAddr, + HWMP_ACTIVE_PATH_TIMEOUT, + 0, + 1, + MeshDestEntry); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + pOutBuffer = NULL; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("<----- MeshPreqCreate\n")); +} + +VOID +MeshPreqForward( + IN PRTMP_ADAPTER pAd, + IN UINT8 MeshTTL, + IN UINT32 MeshSeq, + IN UINT8 MeshPreqFlag, + IN UCHAR HopCount, + IN UCHAR PreqTTL, + IN ULONG ReqID, + IN PUCHAR pOrigAddr, + IN ULONG OrigDsn, + IN PUCHAR OrigProxyAddr, + IN ULONG LifeTime, + IN ULONG Metrics, + IN UCHAR DestCount, + IN MESH_DEST_ENTRY MeshDestEntry, + IN PUCHAR TransmissionAddr) +{ + HEADER_802_11 MeshHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + MESH_FLAG MeshFlag; + UCHAR CurrentHopCount, CurrentPreqTTL, i; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> MeshPreqForward\n")); + + CurrentHopCount = HopCount++; + CurrentPreqTTL = PreqTTL--; + + for(i = 0; i < MAX_MESH_LINKS; i++) + { + if ((PeerLinkValidCheck(pAd, i) == TRUE) && !MAC_ADDR_EQUAL(TransmissionAddr, pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr)) + { + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /*Get an unused nonpaged memory */ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("Mesh - %s() allocate memory failed \n", __FUNCTION__)); + return; + } + + /* send metrics report frame to (PreqDestEntry->DestAddr) */ + EnqueuePeerLinkMetricReport(pAd, + pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr, + MESH_LinkMetricUpdate(pAd, (PCHAR)pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr)); + + MeshHeaderInit(pAd, &MeshHdr, + pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr, /*Addr1 */ + pAd->MeshTab.CurrentAddress, /*Addr2 */ + ZERO_MAC_ADDR); /*Addr3 */ + + MakeOutgoingFrame(pOutBuffer, + &FrameLen, + sizeof(HEADER_802_11), + &MeshHdr, + END_OF_ARGS); + + /* Mesh Header */ + MeshFlag.word = 0; + MeshFlag.field.AE = 0; + InsertMeshHeader(pAd, + (pOutBuffer + FrameLen), + &FrameLen, MeshFlag.word, + MeshTTL, + MeshSeq, + NULL, + NULL, + NULL); + + /* Action field */ + InsertMeshActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_MESH_PATH_SELECTION, ACT_CODE_PATH_REQUEST); + + /* Path Request IE */ + InsertMeshPathRequestIE(pAd, + (pOutBuffer + FrameLen), + &FrameLen, + MeshPreqFlag, + CurrentHopCount, + CurrentPreqTTL, + ReqID, + pOrigAddr, + OrigDsn, + OrigProxyAddr, + LifeTime, + Metrics, + 1, + MeshDestEntry); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + pOutBuffer = NULL; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("<----- MeshPreqForward\n")); +} + +VOID +MeshPrepRcvProcess( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PHEADER_802_11 pHeader = (PHEADER_802_11)pRxBlk->pHeader; + UINT8 MeshTTL; + UINT32 MeshSeq; + UCHAR Ie; + UCHAR IeLen; + UINT8 PrepFlag; + UCHAR HopCount; + UCHAR PrepTTL; + UCHAR DestMacAddr[MAC_ADDR_LEN]; + UINT32 DestSeq; + UCHAR PrepProxyAddr[MAC_ADDR_LEN]; + PUCHAR pPrepProxyAddr = NULL; + UINT32 LifeTime; + UINT32 Metric; + UCHAR OrigMacAddr[MAC_ADDR_LEN]; + UINT32 OrigSeq; + MESH_ROUTING_ENTRY *pRouteEntry; + PMAC_TABLE_ENTRY pMacEntry = NULL; + BOOLEAN bForward = TRUE; + PMESH_ENTRY pMeshEntry = NULL; + PUCHAR pFrame; + ULONG FrameLen; + UCHAR VarOffset; + PUCHAR pMeshHdr = (PUCHAR)(pRxBlk->pData); + UINT MeshHdrLen; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> MeshPrepRcvProcess\n")); + + if (GetMeshLinkId(pAd, (PCHAR)pHeader->Addr2) == BSS_NOT_FOUND) + return; + + MeshTTL = GetMeshTTL(pMeshHdr); + MeshSeq = GetMeshSeq(pMeshHdr); + + if (--MeshTTL <= 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("Mesh Time to Live is zero !\n")); + return; + } + + MeshHdrLen = GetMeshHederLen(pRxBlk->pData); + /* skip Mesh Header */ + pRxBlk->pData += MeshHdrLen; + pRxBlk->DataSize -= MeshHdrLen; + + /* skip Category and ActionCode */ + pFrame = (PUCHAR)(pRxBlk->pData + 2); + FrameLen = pRxBlk->DataSize - 2; + + VarOffset = 0; + /* Get Path Select IE */ + NdisMoveMemory(&Ie, pFrame + VarOffset, 1); + if (Ie != IE_MESH_PREP) + { + DBGPRINT(RT_DEBUG_ERROR, ("Mesh Path Reply Element IE wrong !!!\n")); + return; + } + VarOffset += 1; + + /* Get IE length */ + NdisMoveMemory(&IeLen, pFrame + VarOffset, 1); + if (IeLen < 31) + { + DBGPRINT(RT_DEBUG_ERROR, ("Mesh Path Reply frame length < 33 !!!\n")); + return; + } + VarOffset += 1; + + /* Get Path Response Flag */ + NdisMoveMemory(&PrepFlag, pFrame + VarOffset, 1); + VarOffset += 1; + + /* Get HopCount */ + NdisMoveMemory(&HopCount, pFrame + VarOffset, 1); + VarOffset += 1; + + /* Get Path Response TTL */ + NdisMoveMemory(&PrepTTL, pFrame + VarOffset, 1); + VarOffset += 1; + + /* Get Destnation Address */ + NdisMoveMemory(&DestMacAddr, pFrame + VarOffset, 6); + VarOffset += 6; + + /* Check the MP whether it's Originator of PREP. */ + if (MAC_ADDR_EQUAL(pAd->MeshTab.CurrentAddress, DestMacAddr)) + return; + + /* Get Destnation Sequence Number */ + NdisMoveMemory(&DestSeq, pFrame + VarOffset, 4); + VarOffset += 4; + DestSeq = le2cpu32(DestSeq); + + if (((PMESH_PREP_FLAG)&PrepFlag)->field.AE == 1) + { + /* Get Proxied Address */ + NdisMoveMemory(&PrepProxyAddr, pFrame + VarOffset, 6); + pPrepProxyAddr = PrepProxyAddr; + VarOffset += 6; + } + + /* Get LifeTime */ + NdisMoveMemory(&LifeTime, pFrame + VarOffset, 4); + VarOffset += 4; + LifeTime = le2cpu32(LifeTime); + + /* Get Metric */ + NdisMoveMemory(&Metric, pFrame + VarOffset, 4); + VarOffset += 4; + Metric = le2cpu32(Metric); + + /* Get Originator Address */ + NdisMoveMemory(&OrigMacAddr, pFrame + VarOffset, 6); + VarOffset += 6; + + /* Get Originator Sequence Number */ + NdisMoveMemory(&OrigSeq, pFrame + VarOffset, 4); + + if((pMacEntry = MeshTableLookup(pAd, pHeader->Addr2, TRUE)) == NULL) + return; + + pRouteEntry = MeshRoutingTableLookup(pAd, DestMacAddr); + + if (MAC_ADDR_EQUAL(pAd->MeshTab.CurrentAddress, OrigMacAddr)) + { + if (((PMESH_PREP_FLAG)&PrepFlag)->field.AE == 1) + pMeshEntry = MeshEntryTableLookUp(pAd, PrepProxyAddr); + else + pMeshEntry = MeshEntryTableLookUp(pAd, DestMacAddr); + + if (pMeshEntry == NULL) + return; + + if (pMeshEntry->PathReqTimerRunning == TRUE) + { + if (pMeshEntry->PathReq) + { + BOOLEAN Cancelled; + + RTMPCancelTimer(&pMeshEntry->PathReq->PathReqTimer, &Cancelled); + +/* kfree((PUCHAR)pMeshEntry->PathReq); */ + os_free_mem(NULL, pMeshEntry->PathReq); + pMeshEntry->PathReq = NULL; + } + pMeshEntry->PathReqTimerRunning = FALSE; + } + + if (pRouteEntry == NULL) + { + pRouteEntry = MeshRoutingTableInsert(pAd, + DestMacAddr, + DestSeq, + pHeader->Addr2, + pMacEntry->MatchMeshTabIdx, + Metric + pAd->MeshTab.MeshLink[pMacEntry->MatchMeshTabIdx].Entry.Metrics); + } + else + { + if (pRouteEntry->Dsn < DestSeq) + { + pRouteEntry = MeshRoutingTableUpdate(pAd, + DestMacAddr, + DestSeq, + pHeader->Addr2, + pMacEntry->MatchMeshTabIdx, + Metric + pAd->MeshTab.MeshLink[pMacEntry->MatchMeshTabIdx].Entry.Metrics); + } + } + + if (((PMESH_PREP_FLAG)&PrepFlag)->field.AE == 1) + { + pMeshEntry = MeshEntryTableLookUp(pAd, PrepProxyAddr); + + if (pMeshEntry == NULL) + MeshEntryTableInsert(pAd, + PrepProxyAddr, + pRouteEntry->Idx); + else + MeshEntryTableUpdate(pAd, + PrepProxyAddr, + pRouteEntry->Idx); + + pMeshEntry = MeshEntryTableLookUp(pAd, DestMacAddr); + + if (pMeshEntry == NULL) + MeshEntryTableInsert(pAd, + DestMacAddr, + pRouteEntry->Idx); + else + MeshEntryTableUpdate(pAd, + DestMacAddr, + pRouteEntry->Idx); + } + else + { + pMeshEntry = MeshEntryTableLookUp(pAd, DestMacAddr); + + if (pMeshEntry == NULL) + MeshEntryTableInsert(pAd, + DestMacAddr, + pRouteEntry->Idx); + else + MeshEntryTableUpdate(pAd, + DestMacAddr, + pRouteEntry->Idx); + } + + bForward = FALSE; + } + else + { + if (pRouteEntry == NULL) + { + pRouteEntry = MeshRoutingTableInsert(pAd, + DestMacAddr, + DestSeq, + pHeader->Addr2, + pMacEntry->MatchMeshTabIdx, + Metric + pAd->MeshTab.MeshLink[pMacEntry->MatchMeshTabIdx].Entry.Metrics); + + if (((PMESH_PREP_FLAG)&PrepFlag)->field.AE == 1) + { + pMeshEntry = MeshEntryTableLookUp(pAd, PrepProxyAddr); + + if (pMeshEntry == NULL) + MeshEntryTableInsert(pAd, + PrepProxyAddr, + pRouteEntry->Idx); + else + MeshEntryTableUpdate(pAd, + PrepProxyAddr, + pRouteEntry->Idx); + + pMeshEntry = MeshEntryTableLookUp(pAd, DestMacAddr); + + if (pMeshEntry == NULL) + MeshEntryTableInsert(pAd, + DestMacAddr, + pRouteEntry->Idx); + else + MeshEntryTableUpdate(pAd, + DestMacAddr, + pRouteEntry->Idx); + } + else + { + pMeshEntry = MeshEntryTableLookUp(pAd, DestMacAddr); + + if (pMeshEntry == NULL) + MeshEntryTableInsert(pAd, + DestMacAddr, + pRouteEntry->Idx); + else + MeshEntryTableUpdate(pAd, + DestMacAddr, + pRouteEntry->Idx); + } + } + else + { + if (pRouteEntry->Dsn > DestSeq) + { + bForward = FALSE; + } + else + { + MeshRoutingTableUpdate(pAd, + DestMacAddr, + DestSeq, + pHeader->Addr2, + pMacEntry->MatchMeshTabIdx, + Metric + pAd->MeshTab.MeshLink[pMacEntry->MatchMeshTabIdx].Entry.Metrics); + + if (((PMESH_PREP_FLAG)&PrepFlag)->field.AE == 1) + { + pMeshEntry = MeshEntryTableLookUp(pAd, PrepProxyAddr); + + if (pMeshEntry == NULL) + MeshEntryTableInsert(pAd, + PrepProxyAddr, + pRouteEntry->Idx); + else + MeshEntryTableUpdate(pAd, + PrepProxyAddr, + pRouteEntry->Idx); + + pMeshEntry = MeshEntryTableLookUp(pAd, DestMacAddr); + + if (pMeshEntry == NULL) + MeshEntryTableInsert(pAd, + DestMacAddr, + pRouteEntry->Idx); + else + MeshEntryTableUpdate(pAd, + DestMacAddr, + pRouteEntry->Idx); + } + else + { + pMeshEntry = MeshEntryTableLookUp(pAd, DestMacAddr); + + if (pMeshEntry == NULL) + MeshEntryTableInsert(pAd, + DestMacAddr, + pRouteEntry->Idx); + else + MeshEntryTableUpdate(pAd, + DestMacAddr, + pRouteEntry->Idx); + } + } + } + + if (PrepTTL <= 1) + { + bForward = FALSE; + } + } + + /* add or update Transmission MP Route to route table */ + if (!MAC_ADDR_EQUAL(DestMacAddr, pHeader->Addr2)) + { + pMeshEntry = MeshEntryTableLookUp(pAd, pHeader->Addr2); + pRouteEntry = MeshRoutingTableLookup(pAd, pHeader->Addr2); + + if (pMeshEntry && pRouteEntry) + { + MeshRoutingTableUpdate(pAd, + pHeader->Addr2, + 0, + pHeader->Addr2, + pMacEntry->MatchMeshTabIdx, + pAd->MeshTab.MeshLink[pMacEntry->MatchMeshTabIdx].Entry.Metrics); + MeshEntryTableUpdate(pAd, + pHeader->Addr2, + pRouteEntry->Idx); + } + else + { + if (pRouteEntry == NULL) + pRouteEntry = MeshRoutingTableInsert(pAd, + pHeader->Addr2, + 0, + pHeader->Addr2, + pMacEntry->MatchMeshTabIdx, + pAd->MeshTab.MeshLink[pMacEntry->MatchMeshTabIdx].Entry.Metrics); + else + pRouteEntry = MeshRoutingTableUpdate(pAd, + pHeader->Addr2, + 0, + pHeader->Addr2, + pMacEntry->MatchMeshTabIdx, + pAd->MeshTab.MeshLink[pMacEntry->MatchMeshTabIdx].Entry.Metrics); + + if (pMeshEntry == NULL) + MeshEntryTableInsert(pAd, + pHeader->Addr2, + pRouteEntry->Idx); + else + MeshEntryTableUpdate(pAd, + pHeader->Addr2, + pRouteEntry->Idx); + } + } + + if (bForward == TRUE) + { + UCHAR TowardOrigNextHop[MAC_ADDR_LEN]; + + if (pAd->MeshTab.MeshCapability.field.Forwarding == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("Mesh Forwarding bit disable !!!\n")); + goto out; + } + + /* Update precursor to route table */ + pRouteEntry = MeshRoutingTableLookup(pAd, OrigMacAddr); + if (pRouteEntry) + { + MeshRoutingTablePrecursorUpdate(pAd, + OrigMacAddr, + pHeader->Addr2); + COPY_MAC_ADDR(TowardOrigNextHop, pRouteEntry->NextHop); + } + + pRouteEntry = MeshRoutingTableLookup(pAd, DestMacAddr); + if (pRouteEntry) + MeshRoutingTablePrecursorUpdate(pAd, DestMacAddr, TowardOrigNextHop); + + /* If the receiving MP is not the final destination of the PREP, the PREP is propagated */ + MeshPrepForward(pAd, + MeshTTL, + MeshSeq, + PrepFlag, + HopCount, + PrepTTL, + DestMacAddr, + DestSeq, + pPrepProxyAddr, + LifeTime, + (Metric + pAd->MeshTab.MeshLink[pMacEntry->MatchMeshTabIdx].Entry.Metrics), + OrigMacAddr, + OrigSeq); + } + +out: + DBGPRINT(RT_DEBUG_TRACE, ("<----- MeshPrepRcvProcess\n")); +} + +VOID +MeshPrepCreate( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pNextHop, + IN PUCHAR pOrigAddr, + IN ULONG OrigDsn, + IN PUCHAR pProxyAddr) +{ + HEADER_802_11 MeshHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + MESH_FLAG MeshFlag; + MESH_PREP_FLAG MeshPrepFlag; + UINT32 MeshSeq = INC_MESH_SEQ(pAd->MeshTab.MeshSeq); + + DBGPRINT(RT_DEBUG_TRACE, ("-----> MeshPrepCreate\n")); + + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /*Get an unused nonpaged memory */ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("Mesh - %s() allocate memory failed \n", __FUNCTION__)); + return; + } + + MeshHeaderInit(pAd, &MeshHdr, + pNextHop, /*Addr1 */ + pAd->MeshTab.CurrentAddress, /*Addr2 */ + ZERO_MAC_ADDR); /*Addr3 */ + + NdisMoveMemory(pOutBuffer, (PCHAR)&MeshHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + /* Mesh Header */ + MeshFlag.word = 0; + MeshFlag.field.AE = 0; + InsertMeshHeader(pAd, + (pOutBuffer + FrameLen), + &FrameLen, + MeshFlag.word, + MESH_TTL, + MeshSeq, + NULL, + NULL, + NULL); + + /* Action field */ + InsertMeshActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_MESH_PATH_SELECTION, ACT_CODE_PATH_REPLY); + + MeshPrepFlag.word = 0; + if (pProxyAddr) + MeshPrepFlag.field.AE = 1; + else + MeshPrepFlag.field.AE = 0; + + InsertMeshPathResponseIE(pAd, + (pOutBuffer + FrameLen), + &FrameLen, + MeshPrepFlag.word, + 0, + HWMP_NET_DIAMETER, + pAd->MeshTab.CurrentAddress, + pAd->MeshTab.MeshOriginatorDsn++, + pProxyAddr, + HWMP_ACTIVE_PATH_TIMEOUT, + 0, + pOrigAddr, + OrigDsn); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- MeshPrepCreate\n")); +} + +VOID +MeshPrepForward( + IN PRTMP_ADAPTER pAd, + IN UINT8 MeshTTL, + IN UINT32 MeshSeq, + IN UINT8 MeshPrepFlag, + IN UCHAR HopCount, + IN UCHAR PrepTTL, + IN PUCHAR pDestAddr, + IN ULONG DestSeq, + IN PUCHAR pProxyAddr, + IN ULONG LifeTime, + IN ULONG Metric, + IN PUCHAR pOrigAddr, + IN ULONG OrigSeq) +{ + HEADER_802_11 MeshHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + MESH_FLAG MeshFlag; + MESH_ROUTING_ENTRY *pEntry; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> MeshPrepForward\n")); + + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /*Get an unused nonpaged memory */ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("Mesh - %s() allocate memory failed \n", __FUNCTION__)); + return; + } + + pEntry = MeshRoutingTableLookup(pAd, pOrigAddr); + + if (pEntry == NULL) + return; + + MeshHeaderInit(pAd, &MeshHdr, + pEntry->NextHop , /*Addr1 */ + pAd->MeshTab.CurrentAddress, /*Addr2 */ + ZERO_MAC_ADDR); /*Addr3 */ + + NdisMoveMemory(pOutBuffer, (PCHAR)&MeshHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + MeshFlag.word = 0; + MeshFlag.field.AE = 0; + InsertMeshHeader(pAd, + (pOutBuffer + FrameLen), + &FrameLen, + MeshFlag.word, + MeshTTL, + MeshSeq, + NULL, + NULL, + NULL); + + InsertMeshActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_MESH_PATH_SELECTION, ACT_CODE_PATH_REPLY); + + InsertMeshPathResponseIE(pAd, + (pOutBuffer + FrameLen), + &FrameLen, + MeshPrepFlag, + HopCount+1, + PrepTTL-1, + pDestAddr, + DestSeq, + pProxyAddr, + LifeTime, + Metric, + pOrigAddr, + OrigSeq); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- MeshPrepForward\n")); +} + +VOID +MeshPerrRcvProcess( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PHEADER_802_11 pHeader = (PHEADER_802_11)pRxBlk->pHeader; + UINT8 MeshTTL = 0; + UINT32 MeshSeq = 0; + PUCHAR pFrame; + ULONG FrameLen; + PUCHAR pMeshHdr = (PUCHAR)(pRxBlk->pData); + UINT i, MeshHdrLen; + UINT8 PerrFlag; + BOOLEAN bForward = FALSE; + UCHAR VarOffset; + UCHAR Ie; + UCHAR IeLen; + UCHAR PerrDestCount; + PUCHAR pBuf = NULL; + MESH_PERR_TABLE PerrTab; + PMESH_PERR_ENTRY pErrEntry = NULL; + PMESH_ROUTING_ENTRY pRouteEntry = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> MeshPerrRcvProcess\n")); + + if (GetMeshLinkId(pAd, (PCHAR)pHeader->Addr2) == BSS_NOT_FOUND) + return; + + MeshTTL = GetMeshTTL(pMeshHdr); + MeshSeq = GetMeshSeq(pMeshHdr); + + if (--MeshTTL <= 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("Mesh Time to Live is zero !\n")); + return; + } + + MeshHdrLen = GetMeshHederLen(pRxBlk->pData); + /* skip Mesh Header */ + pRxBlk->pData += MeshHdrLen; + pRxBlk->DataSize -= MeshHdrLen; + + /* skip Category and ActionCode */ + pFrame = (PUCHAR)(pRxBlk->pData + 2); + FrameLen = pRxBlk->DataSize - 2; + + VarOffset = 0; + + /* Get Path Select IE */ + NdisMoveMemory(&Ie, pFrame + VarOffset, 1); + VarOffset += 1; + if (Ie != IE_MESH_PERR) + { + DBGPRINT(RT_DEBUG_ERROR, ("Receive frame packet Element IE wrong. The IE are not Path Error!!!\n")); + return; + } + + /* Get IE length */ + NdisMoveMemory(&IeLen, pFrame + VarOffset, 1); + VarOffset += 1; + + if (IeLen < 12) + { + DBGPRINT(RT_DEBUG_ERROR, ("Receive frame packet length wrong, the length must > 14!!!\n")); + return; + } + + /* Get Path Error Flags */ + NdisMoveMemory(&PerrFlag, pFrame + VarOffset, 1); + VarOffset += 1; + + /* Get DestCount */ + NdisMoveMemory(&PerrDestCount, pFrame + VarOffset, 1); + VarOffset += 1; + + pBuf = (pFrame + VarOffset); + + if (IeLen < (2 + (PerrDestCount * 10))) + { + DBGPRINT(RT_DEBUG_ERROR, ("Receive frame packet format wrong!!!\n")); + return; + } + + NdisZeroMemory(&PerrTab, sizeof(MESH_PERR_TABLE)); + + for (i = 0; i < PerrDestCount; i++) + { + pErrEntry = (PMESH_PERR_ENTRY) (pFrame + VarOffset); + COPY_MAC_ADDR(PerrTab.PerrEntry[PerrTab.size].DestAddr, pErrEntry->DestAddr); + PerrTab.PerrEntry[PerrTab.size].Dsn = pErrEntry->Dsn; + PerrTab.size++; + VarOffset += 10; + } + + + for (i = 0; i < PerrDestCount; i++) + { + if ((pRouteEntry = MeshRoutingTableLookup(pAd, PerrTab.PerrEntry[i].DestAddr))) + { + if (MAC_ADDR_EQUAL(pRouteEntry->NextHop, pHeader->Addr2)) + { + UCHAR DestAddr[MAC_ADDR_LEN]; + + COPY_MAC_ADDR(DestAddr, pRouteEntry->MeshDA); + if (pRouteEntry->bPrecursor == TRUE) + bForward = TRUE; + MeshRoutingTableDelete(pAd, DestAddr); + if (BMPktSigTabLookUp(pAd, DestAddr)) + BMPktSigTabDelete(pAd, DestAddr); + } + } + } + + if (bForward == TRUE) + { + if (pAd->MeshTab.MeshCapability.field.Forwarding == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("Mesh Forwarding bit disable !!!\n")); + goto out; + } + + MeshPerrForward(pAd, + MeshTTL, + MeshSeq, + PerrDestCount, + (PMESH_PERR_ENTRY) pBuf, + pHeader->Addr2); + } + +out: + + DBGPRINT(RT_DEBUG_TRACE, ("<----- MeshPerrRcvProcess\n")); +} + +VOID +MeshPerrCreate( + IN PRTMP_ADAPTER pAd, + IN UCHAR DestCount, + IN PMESH_PERR_ENTRY pDestEntry) +{ + HEADER_802_11 MeshHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + MESH_FLAG MeshFlag; + UINT32 MeshHeaderSeq; + UCHAR i; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> MeshPerrCreate\n")); + + MeshHeaderSeq = INC_MESH_SEQ(pAd->MeshTab.MeshSeq); + + for(i = 0; i < MAX_MESH_LINKS; i++) + { + if (PeerLinkValidCheck(pAd, i) == TRUE) + { + NStatus = MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); /*Get an unused nonpaged memory */ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("Mesh - %s() allocate memory failed \n", __FUNCTION__)); + return; + } + + MeshHeaderInit(pAd, &MeshHdr, + pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr, /*Addr1 */ + pAd->MeshTab.CurrentAddress, /*Addr2 */ + ZERO_MAC_ADDR); /*Addr3 */ + + NdisMoveMemory(pOutBuffer, (PCHAR)&MeshHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + /* Mesh Header */ + MeshFlag.word = 0; + MeshFlag.field.AE = 0; + InsertMeshHeader(pAd, + (pOutBuffer + FrameLen), + &FrameLen, MeshFlag.word, + pAd->MeshTab.TTL, + MeshHeaderSeq, + NULL, + NULL, + NULL); + + /* Action field */ + InsertMeshActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_MESH_PATH_SELECTION, ACT_CODE_PATH_ERROR); + + InsertMeshPathErrorIE(pAd, (pOutBuffer + FrameLen), &FrameLen, DestCount, pDestEntry); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("<----- MeshPerrCreate\n")); +} + +VOID +MeshPerrForward( + IN PRTMP_ADAPTER pAd, + IN UINT8 MeshTTL, + IN UINT32 MeshSeq, + IN UCHAR DestCount, + IN PMESH_PERR_ENTRY pDestEntry, + IN PUCHAR TxAddr) +{ + HEADER_802_11 MeshHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + MESH_FLAG MeshFlag; + UCHAR i; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> MeshPerrForward\n")); + + for(i = 0; i < MAX_MESH_LINKS; i++) + { + if ((PeerLinkValidCheck(pAd, i) == TRUE) && !MAC_ADDR_EQUAL(TxAddr, pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr)) + { + NStatus = MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); /*Get an unused nonpaged memory */ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("Mesh - %s() allocate memory failed \n", __FUNCTION__)); + return; + } + + MeshHeaderInit(pAd, &MeshHdr, + pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr, /*Addr1 */ + pAd->MeshTab.CurrentAddress, /*Addr2 */ + BROADCAST_ADDR); /*Addr3 */ + + NdisMoveMemory(pOutBuffer, (PCHAR)&MeshHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + /* Mesh Header */ + MeshFlag.word = 0; + MeshFlag.field.AE = 0; + InsertMeshHeader(pAd, + (pOutBuffer + FrameLen), + &FrameLen, + MeshFlag.word, + MeshTTL, + MeshSeq, + pAd->MeshTab.CurrentAddress, + NULL, + NULL); + + /* Action field */ + InsertMeshActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_MESH_PATH_SELECTION, ACT_CODE_PATH_ERROR); + + InsertMeshPathErrorIE(pAd, + (pOutBuffer + FrameLen), + &FrameLen, + DestCount, + pDestEntry); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + } + DBGPRINT(RT_DEBUG_TRACE, ("<----- MeshPerrForward\n")); + return; +} + +VOID +MeshCreatePreqAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pProxyAddr, + IN PUCHAR pDestAddr) +{ + UCHAR DestAddr[MAC_ADDR_LEN]; + PMESH_ENTRY pMeshEntry = NULL; + PUCHAR pBuf = NULL; + PPATH_REQ_ENTRY pNewPReqEntry = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> MeshCreatePreqAction\n")); + + COPY_MAC_ADDR(DestAddr, pDestAddr); + + if (pAd->MeshTab.LinkSize == 0) + return; + + pMeshEntry = MeshEntryTableLookUp(pAd, DestAddr); + + if (pMeshEntry) + { + if (pMeshEntry->PathReqTimerRunning) + { + DBGPRINT(RT_DEBUG_TRACE, ("Path discovery of Mesh Entry (%02x:%02x:%02x:%02x:%02x:%02x) is running !!\n", + pMeshEntry->DestAddr[0], pMeshEntry->DestAddr[1], pMeshEntry->DestAddr[2], + pMeshEntry->DestAddr[3], pMeshEntry->DestAddr[4], pMeshEntry->DestAddr[5])); + return; + } + + if (pMeshEntry->PathReq != NULL) + { + BOOLEAN Cancelled; + + RTMPCancelTimer(&pMeshEntry->PathReq->PathReqTimer, &Cancelled); +/* kfree((PUCHAR)pMeshEntry->PathReq); */ + os_free_mem(NULL, pMeshEntry->PathReq); + pMeshEntry->PathReq = NULL; + } + } + else + { + pMeshEntry = MeshEntryTableInsert(pAd, DestAddr, 0xff); + + if (!pMeshEntry) + return; + } + + if (pMeshEntry) + { +/* pNewPReqEntry = (PPATH_REQ_ENTRY) kmalloc(sizeof(PATH_REQ_ENTRY), MEM_ALLOC_FLAG); */ + os_alloc_mem(NULL, (UCHAR **)&pNewPReqEntry, sizeof(PATH_REQ_ENTRY)); + + if (pNewPReqEntry) + { + NdisZeroMemory(pNewPReqEntry, sizeof(PATH_REQ_ENTRY)); + + pMeshEntry->PathReq = pNewPReqEntry; + + /* Initialize Path Req session */ + pNewPReqEntry->RetryCount = 0; + if (pProxyAddr) + { + COPY_MAC_ADDR(pNewPReqEntry->ProxyAddr, pProxyAddr); + pNewPReqEntry->bProxied = TRUE; + } + COPY_MAC_ADDR(pNewPReqEntry->DestAddr, DestAddr); + pNewPReqEntry->DestDsn = 0; + pNewPReqEntry->pAdapter = pAd; + + RTMPInitTimer(pAd, &pNewPReqEntry->PathReqTimer, GET_TIMER_FUNCTION(MeshPathReqTimeoutAction), + pNewPReqEntry, FALSE); + + /* set timer to send Path Request message */ + pMeshEntry->PathReqTimerRunning = TRUE; + RTMPSetTimer(&pNewPReqEntry->PathReqTimer, HWMP_NETDIAMETER_TRAVERSAL_TIME); + + MeshPreqCreate(pAd, pProxyAddr, DestAddr, 0); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Create Path Req Timer Entry fail\n")); + return; + } + } + + if (pBuf != NULL) +/* kfree(pBuf); */ + os_free_mem(NULL, pBuf); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- MeshCreatePreqAction\n")); +} + +VOID MeshPathReqTimeoutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PATH_REQ_ENTRY *pPathReqEntry = (PATH_REQ_ENTRY *)FunctionContext; + PRTMP_ADAPTER pAd; + PMESH_ENTRY pMeshEntry = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> MeshPathReqTimeoutAction\n")); + + if (pPathReqEntry == NULL) + return; + + pAd = pPathReqEntry->pAdapter; + + if (pPathReqEntry->RetryCount < HWMP_MAX_PREQ_RETRIES) + { + DBGPRINT(RT_DEBUG_TRACE,("Path Request Session Timeout(%d) : Send Path Request again\n", pPathReqEntry->RetryCount)); + + pPathReqEntry->RetryCount++; + RTMPSetTimer(&pPathReqEntry->PathReqTimer, HWMP_NETDIAMETER_TRAVERSAL_TIME); + + if (pPathReqEntry->bProxied == TRUE) + MeshPreqCreate(pAd, + pPathReqEntry->ProxyAddr, + pPathReqEntry->DestAddr, + pPathReqEntry->DestDsn); + else + MeshPreqCreate(pAd, + NULL, + pPathReqEntry->DestAddr, + pPathReqEntry->DestDsn); + } + else + { + UCHAR DestAddr[MAC_ADDR_LEN]; + + COPY_MAC_ADDR(DestAddr, pPathReqEntry->DestAddr); + + pMeshEntry = MeshEntryTableLookUp(pAd, DestAddr); + + if (pMeshEntry && pMeshEntry->PathReq) + { + BOOLEAN Cancelled; + + RTMPCancelTimer(&pMeshEntry->PathReq->PathReqTimer, &Cancelled); +/* kfree((PUCHAR)pMeshEntry->PathReq); */ + os_free_mem(NULL, pMeshEntry->PathReq); + pMeshEntry->PathReq = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("Path discovery of Mesh Entry (%02x:%02x:%02x:%02x:%02x:%02x) retry limit !!\n", + pMeshEntry->DestAddr[0], pMeshEntry->DestAddr[1], pMeshEntry->DestAddr[2], + pMeshEntry->DestAddr[3], pMeshEntry->DestAddr[4], pMeshEntry->DestAddr[5])); + } + + MeshEntryTableDelete(pAd, DestAddr); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<----- MeshPathReqTimeoutAction\n")); +} + +VOID +MeshCreatePerrAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBreakMeshPoint) +{ + PMESH_ROUTING_ENTRY pEntry; + UINT i, precursor_size = 0; + MESH_PERR_TABLE PerrTab; + PUCHAR pBuf = NULL, pPtr; + PMESH_PERR_ENTRY pErrEntry = NULL; + PMESH_ROUTING_TABLE pRouteTab = pAd->MeshTab.pMeshRouteTab; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> MeshCreatePerrAction\n")); + + if (pRouteTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Mesh Route Table doesn't exist.\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(&PerrTab, sizeof(MESH_PERR_TABLE)); + + RTMP_SEM_LOCK(&pAd->MeshTab.MeshRouteTabLock); + for (i = 0; i< MAX_ROUTE_TAB_SIZE; i++) + { + pEntry = &pRouteTab->Content[i]; + if (pEntry->Valid == TRUE) + { + if (MAC_ADDR_EQUAL(pEntry->NextHop, pBreakMeshPoint)) + { + COPY_MAC_ADDR(PerrTab.PerrEntry[PerrTab.size].DestAddr, pEntry->MeshDA); + PerrTab.PerrEntry[PerrTab.size].Dsn = pEntry->Dsn; + PerrTab.size++; + + if (pEntry->bPrecursor == TRUE) + precursor_size++; + } + } + } + RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshRouteTabLock); + + if (PerrTab.size == 0) + return; + +/* pBuf = kmalloc((PerrTab.size*sizeof(MESH_PERR_ENTRY)), MEM_ALLOC_FLAG); */ + os_alloc_mem(NULL, (UCHAR **)&pBuf, (PerrTab.size*sizeof(MESH_PERR_ENTRY))); + + if (pBuf) + NdisZeroMemory(pBuf, PerrTab.size*sizeof(MESH_PERR_ENTRY)); + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pBuf \n", __FUNCTION__)); + return; + } + + pPtr = pBuf; + + for (i = 0; i< PerrTab.size; i++) + { + pErrEntry = (PMESH_PERR_ENTRY) pPtr; + COPY_MAC_ADDR(pErrEntry->DestAddr , PerrTab.PerrEntry[i].DestAddr); + pErrEntry->Dsn = PerrTab.PerrEntry[i].Dsn; + pPtr = pPtr + sizeof(MESH_PERR_ENTRY); + + MeshRoutingTableDelete(pAd, PerrTab.PerrEntry[i].DestAddr); + if (BMPktSigTabLookUp(pAd, PerrTab.PerrEntry[i].DestAddr)) + BMPktSigTabDelete(pAd, PerrTab.PerrEntry[i].DestAddr); + } + + if (precursor_size > 0) + { + MeshPerrCreate(pAd, PerrTab.size, (PMESH_PERR_ENTRY)pBuf); + } + +/* kfree(pBuf); */ + os_free_mem(NULL, pBuf); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- MeshCreatePerrAction\n")); + + return; +} + +VOID +MeshMultipathNotice( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pPeerMac, + IN PUCHAR pMeshSA, + IN UCHAR SwitchOn) +{ + HEADER_802_11 MeshHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + MESH_FLAG MeshFlag; + + UINT32 MeshSeq = INC_MESH_SEQ(pAd->MeshTab.MeshSeq); + + DBGPRINT(RT_DEBUG_TRACE, ("-----> MeshMultipathNotice\n")); + + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /*Get an unused nonpaged memory */ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("Mesh - %s() allocate memory failed \n", __FUNCTION__)); + return; + } + + MeshHeaderInit(pAd, &MeshHdr, + pPeerMac, /* addr1 */ + pAd->MeshTab.CurrentAddress, /* addr2 */ + ZERO_MAC_ADDR); /* addr3 */ + + NdisMoveMemory(pOutBuffer, (PCHAR)&MeshHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + /* Mesh Header */ + MeshFlag.word = 0; + MeshFlag.field.AE = 0; + InsertMeshHeader(pAd, (pOutBuffer + FrameLen), &FrameLen, MeshFlag.word, + pAd->MeshTab.TTL, MeshSeq, NULL, NULL, NULL); + + /* Action field */ + InsertMeshActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_MESH_PATH_SELECTION, + ACT_CODE_MULTIPATH_NOTICE); + + InsertMeshCongestionNotofocationIE(pAd, (pOutBuffer + FrameLen), &FrameLen, pMeshSA, SwitchOn); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- MeshMultipathNotice\n")); +} + +VOID MeshMultipathNoticeRcvProcess( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PHEADER_802_11 pHeader = (PHEADER_802_11)pRxBlk->pHeader; + PUCHAR pFrame; + ULONG FrameLen; + UINT MeshHdrLen; + UINT8 Flag; + UCHAR MeshSA[MAC_ADDR_LEN]; + ULONG LinkIdx; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> MeshMultipathNoticeRcvProcess\n")); + + if ((LinkIdx = GetMeshLinkId(pAd, (PCHAR)pHeader->Addr2)) == BSS_NOT_FOUND) + return; + + if (!PeerLinkValidCheck(pAd, LinkIdx)) + return; + + MeshHdrLen = GetMeshHederLen(pRxBlk->pData); + /* skip Mesh Header */ + pRxBlk->pData += MeshHdrLen; + pRxBlk->DataSize -= MeshHdrLen; + + /* skip Category and ActionCode */ + pFrame = (PUCHAR)(pRxBlk->pData + 2); + FrameLen = pRxBlk->DataSize - 2; + + MeshPathSelMultipathNoticeSanity( pAd, + pFrame, + FrameLen, + &Flag, + MeshSA); + + if ((Flag & 0x01) == 0) + MultipathEntryDelete(pAd, LinkIdx, MeshSA); + else + MultipathEntryInsert(pAd, LinkIdx, MeshSA); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- MeshMultipathNoticeRcvProcess\n")); +} + +BOOLEAN MeshAllowToSendPathResponse( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSA) +{ + if (MAC_ADDR_EQUAL(pAd->MeshTab.CurrentAddress, pSA)) + return TRUE; + + if ((pAd->MeshTab.OpMode & MESH_AP) ||(pAd->MeshTab.OpMode & MESH_POTAL)) + { + PMESH_PROXY_ENTRY pMeshProxyEntry = NULL; + + pMeshProxyEntry = MeshProxyEntryTableLookUp(pAd, pSA); + + if (pMeshProxyEntry) + { + if (MAC_ADDR_EQUAL(pAd->MeshTab.CurrentAddress, pMeshProxyEntry->Owner)) + return TRUE; + } + } + + return FALSE; +} + +#endif /* MESH_SUPPORT */ diff --git a/mt7620/src/common/mesh_sanity.c b/mt7620/src/common/mesh_sanity.c new file mode 100644 index 0000000..926bf0f --- /dev/null +++ b/mt7620/src/common/mesh_sanity.c @@ -0,0 +1,1324 @@ +/* + *************************************************************************** + * 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: + mesh_link_mng.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi 2007-07-23 For mesh (802.11s) support. +*/ +#ifdef MESH_SUPPORT + + +#include "rt_config.h" +#include "mesh_def.h" +#include "mesh_sanity.h" + +BOOLEAN MeshPeerBeaconAndProbeSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pHostName, + OUT PUCHAR pHostNameLen, + OUT PUCHAR pMeshId, + OUT PUCHAR pMeshIdLen, + OUT PMESH_CONFIGURAION_IE pMeshConfiguration) +{ + CHAR *Ptr; + PFRAME_802_11 pFrame; + PEID_STRUCT pEid; + UCHAR SubType; + ULONG Length = 0; + + pFrame = (PFRAME_802_11)Msg; + + /* get subtype from header */ + SubType = (UCHAR)pFrame->Hdr.FC.SubType; + + /*hex_dump("Beacon", Msg, MsgLen); */ + + Ptr = (PCHAR)pFrame->Octet; + Length += LENGTH_802_11; + + /* skip timestamp from payload and advance the pointer */ + Ptr += TIMESTAMP_LEN; + Length += TIMESTAMP_LEN; + + /* skip beacon interval from payload and advance the pointer */ + Ptr += 2; + Length += 2; + + /* skip 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_VENDOR_SPECIFIC: + if (NdisEqualMemory(pEid->Octet, MeshOUI, 3)) + { + PUCHAR ptr = (PUCHAR)(pEid->Octet + 3); + *pHostNameLen = pEid->Len -3; + NdisMoveMemory(pHostName, ptr, *pHostNameLen); + } + break; + + case IE_MESH_ID: + NdisMoveMemory(pMeshId, pEid->Octet, pEid->Len); + *pMeshIdLen = pEid->Len; + break; + + case IE_MESH_CONFIGURATION: + { + PUCHAR ptr; + NdisMoveMemory(&pMeshConfiguration->Version, pEid->Octet, 1); + + if (RTMPEqualMemory(pEid->Octet + 1, MeshOUI, 3)) + NdisMoveMemory(&pMeshConfiguration->PathSelProtocolId, pEid->Octet + 4, 1); + + if (RTMPEqualMemory(pEid->Octet + 5, MeshOUI, 3)) + NdisMoveMemory(&pMeshConfiguration->PathSelMetricId, pEid->Octet + 8, 1); + + ptr = (PUCHAR)&pEid->Octet[0]; + NdisMoveMemory(&pMeshConfiguration->CPI, ptr + 13, 4); + pMeshConfiguration->CPI = le2cpu32(*(UINT32 *)(&pMeshConfiguration->CPI)); + + NdisMoveMemory(&pMeshConfiguration->MeshCapability.word, ptr + 17, 2); + pMeshConfiguration->MeshCapability.word = le2cpu16(*(UINT16 *)(&pMeshConfiguration->MeshCapability.word)); + } + break; + + default: + break; + } + + Length = Length + 2 + pEid->Len; /* Eid[1] + Len[1]+ content[Len] */ + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + return TRUE; +} + +BOOLEAN MeshLinkMngOpenSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT UINT16 *pCapabilityInfo, + OUT UCHAR SupRate[], + OUT PUCHAR pSupRateLen, + OUT PUCHAR pMeshIdLen, + OUT PUCHAR pMeshId, + OUT PUCHAR pMeshSelPathId, + OUT PUCHAR pMeshSelMetricId, + OUT UINT32 *pCPI, + OUT PMESH_CAPABILITY pMeshCapabilty, + OUT UINT16 *pPeerLinkId, + OUT PMESH_SECURITY_CAPABILITY_IE pMscIe, + OUT PUCHAR pMsaIe, + OUT PUCHAR pMsaIeLen, + OUT PUCHAR pRsnIe, + OUT PUCHAR pRsnIeLen, + OUT BOOLEAN *pbWmmCapable, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT UCHAR *pHtCapabilityLen) +{ + PEID_STRUCT eid_ptr; + UCHAR WPA1_OUI[4]={0x00,0x50,0xF2,0x01}; + UCHAR WPA2_OUI[3]={0x00,0x0F,0xAC}; + + *pMsaIeLen = 0; + *pRsnIeLen = 0; + + NdisMoveMemory(pCapabilityInfo, pMsg, 2); + pMsg += 2; + MsgLen -= 2; + *pbWmmCapable = FALSE; + + eid_ptr = (PEID_STRUCT)pMsg; + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pMsg + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_SUPP_RATES: + if ((eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES) && (eid_ptr->Len > 0)) + { + NdisMoveMemory(SupRate, eid_ptr->Octet, eid_ptr->Len); + + *pSupRateLen = eid_ptr->Len; + } + else + { + /* HT rate not ready yet. return true temporarily. */ + /*DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - wrong IE_SUPP_RATES\n")); */ + *pSupRateLen = 8; + SupRate[0] = 0x82; + SupRate[1] = 0x84; + SupRate[2] = 0x8b; + SupRate[3] = 0x96; + SupRate[4] = 0x12; + SupRate[5] = 0x24; + SupRate[6] = 0x48; + SupRate[7] = 0x6c; + /*return FALSE; */ + } + break; + + case IE_EXT_SUPP_RATES: + if (eid_ptr->Len + *pSupRateLen <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(&SupRate[*pSupRateLen], eid_ptr->Octet, eid_ptr->Len); + *pSupRateLen = (*pSupRateLen) + eid_ptr->Len; + } + else + { + NdisMoveMemory(&SupRate[*pSupRateLen], eid_ptr->Octet, MAX_LEN_OF_SUPPORTED_RATES - (*pSupRateLen)); + *pSupRateLen = MAX_LEN_OF_SUPPORTED_RATES; + } + break; + + case IE_WPA: + case IE_WPA2: + if (NdisEqualMemory(eid_ptr->Octet, WME_INFO_ELEM, 6) && (eid_ptr->Len == 7)) + { + *pbWmmCapable = TRUE; + break; + } + + if (pAd->MeshTab.AuthMode < Ndis802_11AuthModeWPA) + { + DBGPRINT(RT_DEBUG_TRACE, ("The AuthMode isn't WPA!!!%d \n",pAd->MeshTab.AuthMode)); + break; + } + + /* If this IE did not begins with "0x00:0x50:0xf2:0x01" or "0x00:0x0f:0xac", 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 proprietary IE!!!\n")); + break; + } + + if (/*(eid_ptr->Len <= MAX_LEN_OF_RSNIE) && */(eid_ptr->Len > MIN_LEN_OF_RSNIE)) + { + NdisMoveMemory(pRsnIe, eid_ptr, eid_ptr->Len + 2); + *pRsnIeLen = eid_ptr->Len + 2; + } + else + { + *pRsnIeLen = 0; + DBGPRINT(RT_DEBUG_TRACE, ("The received the length(%d) of RSN_IE is invalid\n",eid_ptr->Len)); + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("Link Msg - RSNIE(%d), and its len(%d)!!!\n", eid_ptr->Eid, *pRsnIeLen)); + break; + + case IE_MESH_ID: + if (eid_ptr->Len < MAX_MESH_ID_LEN) + NdisMoveMemory(pMeshId, eid_ptr->Octet, eid_ptr->Len); + break; + + case IE_MESH_CONFIGURATION: + if (NdisEqualMemory(eid_ptr->Octet + 1, MeshOUI, 3)) + NdisMoveMemory(pMeshSelPathId, eid_ptr->Octet + 4, 1); + + if (NdisEqualMemory(eid_ptr->Octet + 5, MeshOUI, 3)) + NdisMoveMemory(pMeshSelMetricId, eid_ptr->Octet + 8, 1); + + NdisMoveMemory(pCPI, eid_ptr->Octet + 13, 4); + *pCPI = le2cpu32(*(UINT32 *)pCPI); + NdisMoveMemory(&pMeshCapabilty->word, eid_ptr->Octet + 17, 2); + pMeshCapabilty->word = le2cpu16(*(UINT16 *)(&pMeshCapabilty->word)); + break; + + case IE_MESH_PEER_LINK_MANAGEMENT: + if ((*eid_ptr->Octet == SUBTYPE_PEER_LINK_OPEN) /* subtype 1 means Peer-Link-Open frame. */ + && (eid_ptr->Len == LenPeerLinkMngIE[SUBTYPE_PEER_LINK_OPEN])) /* Length of Peer-Link-open must be 3. */ + { + NdisMoveMemory(pPeerLinkId, eid_ptr->Octet + 1, 2); + *pPeerLinkId = le2cpu16(*pPeerLinkId); + } + break; + + case IE_MESH_MSCIE: + if (eid_ptr->Len == 7) /* its Length MUST be 7 */ + { + NdisMoveMemory(pMscIe, eid_ptr->Octet, eid_ptr->Len); + } + break; + + case IE_MESH_MSAIE: + if (eid_ptr->Len >= sizeof(MSA_HANDSHAKE_IE)) + { + NdisMoveMemory(pMsaIe, eid_ptr->Octet, eid_ptr->Len); + *pMsaIeLen = eid_ptr->Len; + } + 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)); + *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); + + *pHtCapabilityLen = SIZE_HT_CAP_IE; + 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; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return TRUE; +} + +BOOLEAN MeshLinkMngCfnSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT UINT16 *pCapabilityInfo, + OUT UINT16 *pStatusCode, + OUT UINT16 *pAid, + OUT UCHAR SupRate[], + OUT PUCHAR pSupRateLen, + OUT PUCHAR pMeshIdLen, + OUT PUCHAR pMeshId, + OUT PUCHAR pMeshSelPathId, + OUT PUCHAR pMeshSelMetricId, + OUT UINT32 *pCPI, + OUT PMESH_CAPABILITY pMeshCapabilty, + OUT UINT16 *pLocalLinkId, + OUT UINT16 *pPeerLinkId, + OUT PMESH_SECURITY_CAPABILITY_IE pMscIe, + OUT PUCHAR pMsaIe, + OUT PUCHAR pMsaIeLen, + OUT PUCHAR pRsnIe, + OUT PUCHAR pRsnIeLen, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT UCHAR *pHtCapabilityLen) +{ + PEID_STRUCT eid_ptr; + UCHAR WPA1_OUI[4]={0x00,0x50,0xF2,0x01}; + UCHAR WPA2_OUI[3]={0x00,0x0F,0xAC}; + + *pMsaIeLen = 0; + *pRsnIeLen = 0; + + NdisMoveMemory(pCapabilityInfo, pMsg, 2); + pMsg += 2; + MsgLen -= 2; + + NdisMoveMemory(pStatusCode, pMsg, 2); + pMsg += 2; + MsgLen -= 2; + + NdisMoveMemory(pAid, pMsg, 2); + pMsg += 2; + MsgLen -= 2; + + + eid_ptr = (PEID_STRUCT)pMsg; + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pMsg + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_SUPP_RATES: + if ((eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES) && (eid_ptr->Len > 0)) + { + NdisMoveMemory(SupRate, eid_ptr->Octet, eid_ptr->Len); + + *pSupRateLen = eid_ptr->Len; + } + else + { + /* HT rate not ready yet. return true temporarily. */ + /*DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - wrong IE_SUPP_RATES\n")); */ + *pSupRateLen = 8; + SupRate[0] = 0x82; + SupRate[1] = 0x84; + SupRate[2] = 0x8b; + SupRate[3] = 0x96; + SupRate[4] = 0x12; + SupRate[5] = 0x24; + SupRate[6] = 0x48; + SupRate[7] = 0x6c; + + /*return FALSE; */ + } + break; + + case IE_EXT_SUPP_RATES: + if (eid_ptr->Len + *pSupRateLen <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(&SupRate[*pSupRateLen], eid_ptr->Octet, eid_ptr->Len); + *pSupRateLen = (*pSupRateLen) + eid_ptr->Len; + } + else + { + NdisMoveMemory(&SupRate[*pSupRateLen], eid_ptr->Octet, MAX_LEN_OF_SUPPORTED_RATES - (*pSupRateLen)); + *pSupRateLen = MAX_LEN_OF_SUPPORTED_RATES; + } + break; + + case IE_WPA: + case IE_WPA2: + if (pAd->MeshTab.AuthMode < Ndis802_11AuthModeWPA) + break; + + /* If this IE did not begins with "0x00:0x50:0xf2:0x01" or "0x00:0x0f:0xac", 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 proprietary IE!!!\n")); + break; + } + + if (/*(eid_ptr->Len <= MAX_LEN_OF_RSNIE) && */(eid_ptr->Len > MIN_LEN_OF_RSNIE)) + { + NdisMoveMemory(pRsnIe, eid_ptr, eid_ptr->Len + 2); + *pRsnIeLen = eid_ptr->Len + 2; + } + else + { + *pRsnIeLen = 0; + DBGPRINT(RT_DEBUG_TRACE, ("The received the length(%d) of RSN_IE is invalid\n",eid_ptr->Len)); + break; + } + + break; + + case IE_MESH_ID: + if (eid_ptr->Len < MAX_MESH_ID_LEN) + NdisMoveMemory(pMeshId, eid_ptr->Octet, eid_ptr->Len); + break; + + case IE_MESH_CONFIGURATION: + if (NdisEqualMemory(eid_ptr->Octet + 1, MeshOUI, 3)) + { + *pMeshSelPathId = eid_ptr->Octet[4]; + } + if (NdisEqualMemory(eid_ptr->Octet + 5, MeshOUI, 3)) + { + *pMeshSelMetricId = eid_ptr->Octet[8]; + } + NdisMoveMemory(pCPI, eid_ptr->Octet + 13, 4); + *pCPI = le2cpu32(*pCPI); + NdisMoveMemory(&pMeshCapabilty->word, eid_ptr->Octet + 17, 2); + pMeshCapabilty->word = le2cpu16(pMeshCapabilty->word); + break; + + case IE_MESH_PEER_LINK_MANAGEMENT: + { + if ((eid_ptr->Octet[0] == SUBTYPE_PEER_LINK_CONFIRM) /* subtype 1 means Peer-Link-Confirm frame. */ + && (eid_ptr->Len == LenPeerLinkMngIE[SUBTYPE_PEER_LINK_CONFIRM])) /* Length of Peer-Link-close must be 3. */ + { + NdisMoveMemory(pLocalLinkId, eid_ptr->Octet + 1, 2); + *pLocalLinkId = le2cpu16(*(UINT16 *)(pLocalLinkId)); + NdisMoveMemory(pPeerLinkId, eid_ptr->Octet + 3, 2); + *pPeerLinkId = le2cpu16(*(UINT16 *)(pPeerLinkId)); + } + } + break; + + case IE_MESH_MSCIE: + if (eid_ptr->Len == 7) /* its Length MUST be 7 */ + { + NdisMoveMemory(pMscIe,eid_ptr->Octet, eid_ptr->Len); + } + break; + + case IE_MESH_MSAIE: + if (eid_ptr->Len >= sizeof(MSA_HANDSHAKE_IE)) + { + NdisMoveMemory(pMsaIe,eid_ptr->Octet, eid_ptr->Len); + *pMsaIeLen = eid_ptr->Len; + } + 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)); + *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); + + *pHtCapabilityLen = SIZE_HT_CAP_IE; + 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; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return TRUE; +} + +BOOLEAN MeshLinkMngClsSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT UINT16 *pLocalLinkId, + OUT UINT16 *pPeerLinkId, + OUT UINT16 *pReasonCode) +{ + PEID_STRUCT eid_ptr; + + eid_ptr = (PEID_STRUCT)pMsg; + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pMsg + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_MESH_PEER_LINK_MANAGEMENT: + { + if ((eid_ptr->Octet[0] == SUBTYPE_PEER_LINK_CLOSE) /* subtype 1 means Peer-Link-Close frame. */ + && (eid_ptr->Len == LenPeerLinkMngIE[SUBTYPE_PEER_LINK_CLOSE])) /* Length of Peer-Link-close must be 7. */ + { + NdisMoveMemory(pLocalLinkId, eid_ptr->Octet + 1, 2); + *pLocalLinkId = le2cpu16(*(UINT16 *)(pLocalLinkId)); + NdisMoveMemory(pPeerLinkId, eid_ptr->Octet + 3, 2); + *pPeerLinkId = le2cpu16(*(UINT16 *)(pPeerLinkId)); + NdisMoveMemory(pReasonCode, eid_ptr->Octet + 5, 2); + *pReasonCode = le2cpu16(*(UINT16 *)(pReasonCode)); + } + } + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return TRUE; +} + +BOOLEAN MeshPathSelMultipathNoticeSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT UINT8 *pFlag, + OUT PUCHAR pMeshSA) +{ + PEID_STRUCT eid_ptr; + + eid_ptr = (PEID_STRUCT)pMsg; + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pMsg + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_MESH_MULITI_PATH_NOTICE_IE: + { + if (eid_ptr->Len == 7) /* Length must be 7. */ + { + NdisMoveMemory(pFlag, eid_ptr->Octet, 1); + NdisMoveMemory(pMeshSA, eid_ptr->Octet + 1, MAC_ADDR_LEN); + } + } + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return TRUE; +} + + +BOOLEAN MeshChannelSwitchAnnouncementSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT UINT8 *pChSwMode, + OUT UINT8 *pNewCh, + OUT UINT32 *pNewCPI, + OUT UINT8 *pChSwCnt, + OUT PUCHAR pMeshSA) +{ + PEID_STRUCT eid_ptr; + + eid_ptr = (PEID_STRUCT)pMsg; + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pMsg + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_MESH_CHANNEL_SWITCH_ANNOUNCEMENT: + { + if (eid_ptr->Len == 13) /* Length must be 7. */ + { + NdisMoveMemory(pChSwMode, eid_ptr->Octet, 1); + NdisMoveMemory(pNewCh, eid_ptr->Octet + 1, 1); + NdisMoveMemory(pNewCPI, eid_ptr->Octet + 2, 4); + *pNewCPI = le2cpu32(*pNewCPI); + NdisMoveMemory(pChSwCnt, eid_ptr->Octet + 6, 1); + NdisMoveMemory(pMeshSA, eid_ptr->Octet + 7, MAC_ADDR_LEN); + } + } + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return TRUE; +} + +/* + ========================================================================== + Description: + Check sanity RSN IE and get PMKID offset. + Return: + TRUE if match + FALSE otherwise + ========================================================================== +*/ +BOOLEAN MeshValidateRSNIE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pRsnIe, + IN USHORT peerRsnIeLen, + OUT UCHAR *PureRsnLen, + OUT UCHAR *PmkIdLen) +{ + PEID_STRUCT eid_ptr; + PUCHAR pBufTmp; + USHORT Count; + UCHAR offset = 0; + BOOLEAN isValid = FALSE; + BOOLEAN RsnEid = IE_WPA; + + /* Check if both MPs are RSNIE */ + if (pAd->MeshTab.AuthMode < Ndis802_11AuthModeWPA) + { + if (peerRsnIeLen == 0) + { + /* Don't check it */ + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("MeshValidateRSNIE, the local MP has no RSNIE \n")); + return FALSE; + } + } + else + { + if (peerRsnIeLen == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("MeshValidateRSNIE, the peer MP has no RSNIE \n")); + return FALSE; + } + } + + /* hex_dump("Peer RSNIE", pRsnIe, peerRsnIeLen); */ + eid_ptr = (PEID_STRUCT)pRsnIe; + + if (pAd->MeshTab.AuthMode == Ndis802_11AuthModeWPA2PSK || pAd->MeshTab.AuthMode == Ndis802_11AuthModeWPA2) + RsnEid = IE_WPA2; + + if (eid_ptr->Eid != IE_WPA && eid_ptr->Eid != IE_WPA2) + { + DBGPRINT(RT_DEBUG_ERROR, ("MeshValidateRSNIE has unknown element ID(%d) \n", eid_ptr->Eid)); + return FALSE; + } + + if (eid_ptr->Len < sizeof(RSNIE2)) + { + DBGPRINT(RT_DEBUG_ERROR, ("MeshValidateRSNIE, its length is too short(%d)\n", eid_ptr->Len)); + return FALSE; + } + + *PureRsnLen = 0; + *PmkIdLen = 0; + + /* Store STA RSN_IE capability */ + pBufTmp = (PUCHAR)&eid_ptr->Octet[0]; + + offset = (eid_ptr->Eid == IE_WPA2) ? 2 : 6; + + /* Check group cipher */ + if (MeshCheckGroupCipher(pAd, pBufTmp + offset, RsnEid)) + { + /* skip group cipher, then point to pairwise-cipher-count */ + offset += 4; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("MeshValidateRSNIE, the group cipher isn't supported\n")); + return FALSE; + } + + /* Store pairwise-cipher-count */ + NdisMoveMemory(&Count, pBufTmp + offset, sizeof(USHORT)); +#ifdef RT_BIG_ENDIAN + Count = SWAP16(Count); +#endif + + if (Count > 0) + { + /* skip pairwise-cipher-count, then point to pairwise-cipher-suite-list */ + offset += sizeof(USHORT); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("MeshValidateRSNIE, the count of piarwise-cipher is invalid(%d)\n", Count)); + return FALSE; + } + + /* clear this flag */ + isValid = FALSE; + while (Count > 0) + { + if ((isValid == FALSE) && (MeshCheckPairwiseCipher(pAd, pBufTmp + offset, RsnEid))) + { + isValid = TRUE; + } + + offset += 4; + Count--; + } + + if (!isValid) + { + DBGPRINT(RT_DEBUG_ERROR, ("MeshValidateRSNIE, the pairwise cipher isn't supported\n")); + return FALSE; + } + + /* Store AKM-suite-count */ + NdisMoveMemory(&Count, pBufTmp + offset, sizeof(USHORT)); +#ifdef RT_BIG_ENDIAN + Count = SWAP16(Count); +#endif + + if (Count > 0) + { + /* skip AKM-suite-count, then pointer to AKM-suite-list */ + offset += sizeof(USHORT); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("MeshValidateRSNIE, the count of AKM-suite is invalid(%d)\n", Count)); + return FALSE; + } + + /* clear this flag */ + isValid = FALSE; + while (Count > 0) + { + if ((isValid == FALSE) && (MeshCheckAKMSuite(pAd, pBufTmp + offset, RsnEid))) + { + isValid = TRUE; + } + + offset += 4; + Count--; + } + + if (!isValid) + { + DBGPRINT(RT_DEBUG_ERROR, ("MeshValidateRSNIE, the AKM suite isn't supported\n")); + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("MeshValidateRSNIE is completed \n")); + + /* Check if the remaining length is larger than the size of RSN capability(2-bytes). */ + if (eid_ptr->Len - offset >= 2) + { + /* skip RSN capability(2-bytes) */ + offset += sizeof(USHORT); + } + + *PureRsnLen = offset; /* the length is the RSNIE except elementID, length and PMKID */ + + if (eid_ptr->Len - offset >= 2) + { + NdisMoveMemory(&Count, pBufTmp + offset, sizeof(USHORT)); +#ifdef RT_BIG_ENDIAN + Count = SWAP16(Count); +#endif + offset += sizeof(USHORT); + + if (Count == 2 && (eid_ptr->Len - offset == (2*LEN_PMKID))) + *PmkIdLen = 2*LEN_PMKID; + else if (Count == 1 && (eid_ptr->Len - offset == LEN_PMKID)) + *PmkIdLen = LEN_PMKID; + else + *PmkIdLen = 0; + + if (*PmkIdLen > 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("MeshValidateRSNIE, %d PMKID exist and its len is %d \n", Count, (eid_ptr->Len - offset))); + } + } + + return TRUE; +} + +/* + ========================================================================== + Description: + Check sanity of group cipher selector + Return: + TRUE if match + FALSE otherwise + ========================================================================== +*/ +BOOLEAN MeshCheckGroupCipher( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN UCHAR Eid) +{ + + /* WPA and WPA2 format not the same in RSN_IE */ + if (Eid == IE_WPA2) + { + /* skip version(2-bytes) */ + if (NdisEqualMemory(pData, &pAd->MeshTab.RSN_IE[2], 4)) + return TRUE; + } + else if (Eid == IE_WPA) + { + /* skip OUI(4-bytes) and version(2-bytes) */ + if (NdisEqualMemory(pData, &pAd->MeshTab.RSN_IE[6], 4)) + return TRUE; + } + + return FALSE; +} + +/* + ========================================================================== + Description: + Check sanity of unicast cipher selector. + Return: + TRUE if match + FALSE otherwise + ========================================================================== +*/ +BOOLEAN MeshCheckPairwiseCipher( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN UCHAR Eid) +{ + PUCHAR pTmp; + USHORT Count; + + pTmp = &pAd->MeshTab.RSN_IE[0]; + + if(Eid == IE_WPA2) + /* 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)); +#ifdef RT_BIG_ENDIAN + Count = SWAP16(Count); +#endif + pTmp += sizeof(USHORT);/*pointer to unicast cipher */ + + while (Count > 0) + { + if(RTMPEqualMemory(pData, pTmp, 4)) + return TRUE; + else + { + pTmp += 4; + Count--; + } + } + return FALSE;/* do not match the unicast cipher */ + +} + + + +/* + ========================================================================== + Description: + Check invalidity of authentication method selection. + Return: + TRUE if match + FALSE otherwise + ========================================================================== +*/ +BOOLEAN MeshCheckAKMSuite( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN UCHAR Eid) +{ + PUCHAR pTmp; + USHORT Count; + + pTmp = &pAd->MeshTab.RSN_IE[0]; + + if(Eid == IE_WPA2) + /* 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)); +#ifdef RT_BIG_ENDIAN + Count = SWAP16(Count); +#endif + 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)); +#ifdef RT_BIG_ENDIAN + Count = SWAP16(Count); +#endif + pTmp += sizeof(USHORT);/*pointer to AKM cipher */ + + while (Count > 0) + { + if(RTMPEqualMemory(pData, pTmp, 4)) + return TRUE; + else + { + pTmp += 4; + Count--; + } + } + return FALSE;/* do not match the AKM */ + +} + +UINT16 MeshValidateOpenAndCfnPeerLinkMsg( + IN PRTMP_ADAPTER pAd, + IN UCHAR state, + IN PMESH_LINK_ENTRY pMeshLinkEntry, + IN PUCHAR pRcvdMscIe, + IN PUCHAR pRcvdMsaIe, + IN UCHAR RcvdMsaIeLen, + IN PUCHAR pRcvdRsnIe, + IN UCHAR RcvdRsnIeLen, + IN UCHAR pure_rsn_len, + IN UCHAR pmkid_len) +{ + if (!RTMPEqualMemory(pRcvdMscIe, (PUCHAR)&pMeshLinkEntry->RcvdMscIe, sizeof(MESH_SECURITY_CAPABILITY_IE))) + { + DBGPRINT(RT_DEBUG_ERROR, ("The MSCIE is different between peer link open and confirm frame \n")); + return MESH_SECURITY_FAILED_VERIFICATION; + } + + if (!RTMPEqualMemory(pRcvdMsaIe, pMeshLinkEntry->RcvdMsaIe, sizeof(MESH_HANDSHAKE_CONTROL))) + { + DBGPRINT(RT_DEBUG_ERROR, ("The Handshake Control field of MSAIE is different between peer link open and confirm frame \n")); + return MESH_SECURITY_FAILED_VERIFICATION; + } + + if (pAd->MeshTab.AuthMode >= Ndis802_11AuthModeWPA) + { + if (pure_rsn_len != pMeshLinkEntry->RcvdRSNIE_Len || + !RTMPEqualMemory(pRcvdRsnIe + 2, pMeshLinkEntry->RcvdRSNIE, pure_rsn_len)) + { + DBGPRINT(RT_DEBUG_ERROR, ("The RSNIE is different between candidate MP's link open and confirm frame \n")); + return MESH_SECURITY_FAILED_VERIFICATION; + } + + if (pmkid_len > 0 && pMeshLinkEntry->RcvdPMKID_Len > 0) + { + UCHAR pmkid_offset = RcvdRsnIeLen - pmkid_len; + + if (pmkid_len != pMeshLinkEntry->RcvdPMKID_Len || + !NdisEqualMemory(pRcvdRsnIe + pmkid_offset, pMeshLinkEntry->RcvdPMKID, pmkid_len)) + { + DBGPRINT(RT_DEBUG_ERROR, ("The result of Key Selection is different between candidate MP's link open and confirm frame\n")); + hex_dump("Receive PMKID ", pRcvdRsnIe + pmkid_offset, pmkid_len); + hex_dump("Desired PMKID ", pMeshLinkEntry->RcvdPMKID, pMeshLinkEntry->RcvdPMKID_Len); + return MESH_SECURITY_FAILED_VERIFICATION; + + } + } + else if (pmkid_len == 0 && pMeshLinkEntry->RcvdPMKID_Len == 0) + { + ; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("The PMKID is different between candidate MP's link open and confirm frame\n")); + return MESH_SECURITY_FAILED_VERIFICATION; + } + + if (!pMeshLinkEntry->bValidLocalMpAsSelector) + { + UCHAR akm_offset = 0, cipher_offset = 0; + + akm_offset = sizeof(MESH_HANDSHAKE_CONTROL) + MAC_ADDR_LEN; + + cipher_offset = sizeof(MESH_HANDSHAKE_CONTROL) + MAC_ADDR_LEN + LEN_OUI_SUITE; + + if (!RTMPEqualMemory(pRcvdMsaIe + akm_offset, &pMeshLinkEntry->RcvdMsaIe[akm_offset], LEN_OUI_SUITE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("The Selected AKM Suite of MSAIE is different between peer link open and confirm frame \n")); + return MESH_SECURITY_FAILED_VERIFICATION; + } + + if (!RTMPEqualMemory(pRcvdMsaIe + cipher_offset, &pMeshLinkEntry->RcvdMsaIe[cipher_offset], LEN_OUI_SUITE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("The Selected Pairwise Cipher Suite of MSAIE is different between peer link open and confirm frame \n")); + return MESH_SECURITY_FAILED_VERIFICATION; + } + } + + } + + { + UCHAR LocalMaAddr[MAC_ADDR_LEN]; + UCHAR PeerMaAddr[MAC_ADDR_LEN]; + + if (pMeshLinkEntry->bValidLocalMpAsAuthenticator) + NdisMoveMemory(LocalMaAddr, pAd->MeshTab.CurrentAddress, MAC_ADDR_LEN); + else + NdisMoveMemory(LocalMaAddr, pMeshLinkEntry->PeerMacAddr, MAC_ADDR_LEN); + + if (state == SUBTYPE_PEER_LINK_CONFIRM) + NdisMoveMemory(PeerMaAddr, pRcvdMsaIe + 1, MAC_ADDR_LEN); + else + NdisMoveMemory(PeerMaAddr, &pMeshLinkEntry->RcvdMsaIe[1], MAC_ADDR_LEN); + + if (!NdisEqualMemory(LocalMaAddr, PeerMaAddr, MAC_ADDR_LEN)) + { + DBGPRINT(RT_DEBUG_ERROR, ("The MA-ID of MSAIE doesn't match \n")); + return MESH_SECURITY_FAILED_VERIFICATION; + } + } + + + return MLME_SUCCESS; +} + +UINT16 MeshCheckPeerMsaIeCipherValidity( + IN PRTMP_ADAPTER pAd, + IN UCHAR state, + IN PMESH_LINK_ENTRY pMeshLinkEntry, + IN PUCHAR pRcvdMsaIe) +{ + if (pAd->MeshTab.AuthMode >= Ndis802_11AuthModeWPA) + { + UCHAR akm_offset = 0, cipher_offset = 0; + + akm_offset = sizeof(MESH_HANDSHAKE_CONTROL) + MAC_ADDR_LEN; + + cipher_offset = akm_offset + LEN_OUI_SUITE; + + if (((state == SUBTYPE_PEER_LINK_OPEN) && (!pMeshLinkEntry->bValidLocalMpAsSelector)) || + (state == SUBTYPE_PEER_LINK_CONFIRM)) + { + UCHAR RsnEid = IE_WPA; + + if (pAd->MeshTab.AuthMode == Ndis802_11AuthModeWPA2PSK || pAd->MeshTab.AuthMode == Ndis802_11AuthModeWPA2) + RsnEid = IE_WPA2; + + if (!MeshCheckPairwiseCipher(pAd, &pRcvdMsaIe[cipher_offset], RsnEid)) + { + DBGPRINT(RT_DEBUG_ERROR, ("The Selected Pairwise Cipher isn't supported by local MP\n")); + return MESH_SECURITY_ROLE_NEGOTIATION_DIFFERS; + } + + if (!MeshCheckAKMSuite(pAd, &pRcvdMsaIe[akm_offset], RsnEid)) + { + DBGPRINT(RT_DEBUG_ERROR, ("The Selected AKM isn't supported by local MP \n")); + return MESH_SECURITY_ROLE_NEGOTIATION_DIFFERS; + } + + /* verify peer AKM and pairwise-cipher OK, update them to local MSAIE */ + if (state == SUBTYPE_PEER_LINK_OPEN) + NdisMoveMemory(&pMeshLinkEntry->LocalMsaIe[akm_offset], &pRcvdMsaIe[akm_offset], 2*LEN_OUI_SUITE); + + } + + if ((state == SUBTYPE_PEER_LINK_CONFIRM) && (pMeshLinkEntry->bValidLocalMpAsSelector)) + { + if (!NdisEqualMemory(&pRcvdMsaIe[akm_offset], &pMeshLinkEntry->LocalMsaIe[akm_offset], LEN_OUI_SUITE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("The Selected AKM in P.L. confirm frame isn't supported by local Selector MP \n")); + return MESH_SECURITY_FAILED_VERIFICATION; + } + + if (!NdisEqualMemory(&pRcvdMsaIe[cipher_offset], &pMeshLinkEntry->LocalMsaIe[cipher_offset], LEN_OUI_SUITE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("The Selected Pairwise Cipher in P.L. confirm frame isn't supported by local Selector MP \n")); + return MESH_SECURITY_FAILED_VERIFICATION; + } + } + } + + return MLME_SUCCESS; + +} + +BOOLEAN MeshPathRequestSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT UINT8 *pFlag, + OUT UINT8 *pHopCount, + OUT UINT8 *pTTL, + OUT UINT32 *pID, + OUT PUCHAR pOrigMac, + OUT UINT32 *pOrigDsn, + OUT PUCHAR pProxyMac, + OUT UINT32 *pLifeTime, + OUT UINT32 *pMetric, + OUT UINT8 *pDestCount, + OUT PMESH_DEST_ENTRY pDestEntry) +{ + PEID_STRUCT eid_ptr; + UINT8 VarOffset = 0; + UINT8 EntryCount = 0; + MESH_PREQ_FLAG PreqFlag; + + eid_ptr = (PEID_STRUCT)pMsg; + + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pMsg + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_MESH_PREQ: + { + NdisMoveMemory(pFlag, eid_ptr->Octet, 1); + VarOffset += 1; + NdisMoveMemory(pHopCount, eid_ptr->Octet + VarOffset, 1); + VarOffset += 1; + NdisMoveMemory(pTTL, eid_ptr->Octet + VarOffset, 1); + VarOffset += 1; + NdisMoveMemory(pID, eid_ptr->Octet + VarOffset, 4); + VarOffset += 4; + *pID = le2cpu32(*pID); + NdisMoveMemory(pOrigMac, eid_ptr->Octet + VarOffset, MAC_ADDR_LEN); + VarOffset += MAC_ADDR_LEN; + NdisMoveMemory(pOrigDsn, eid_ptr->Octet + VarOffset, 4); + VarOffset += 4; + *pOrigDsn = le2cpu32(*pOrigDsn); + PreqFlag = (MESH_PREQ_FLAG)(*pFlag); + if (PreqFlag.field.AE == 1) + { + NdisMoveMemory(pProxyMac, eid_ptr->Octet + VarOffset, MAC_ADDR_LEN); + VarOffset += MAC_ADDR_LEN; + } + NdisMoveMemory(pLifeTime, eid_ptr->Octet + VarOffset, 4); + VarOffset += 4; + *pLifeTime = le2cpu32(*pLifeTime); + NdisMoveMemory(pMetric, eid_ptr->Octet + VarOffset, 4); + VarOffset += 4; + *pMetric = le2cpu32(*pMetric); + NdisMoveMemory(pDestCount, eid_ptr->Octet + VarOffset, 1); + VarOffset += 1; + EntryCount = (*pDestCount); + if (EntryCount >= 1) + NdisMoveMemory(pDestEntry, eid_ptr->Octet + VarOffset, 11*EntryCount); + } + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return TRUE; +} + +BOOLEAN MeshPathResponseSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT UINT8 *pFlag, + OUT UINT8 *pHopCount, + OUT UINT8 *pTTL, + OUT PUCHAR pDestMac, + OUT UINT32 *pDesDsn, + OUT PUCHAR pProxyMac, + OUT UINT32 *pLifeTime, + OUT UINT32 *pMetric, + OUT PUCHAR pOrigMac, + OUT UINT32 *pOrigDsn, + OUT UINT8 *pDependMPCount, + OUT PMESH_DEPENDENT_ENTRY pDependEntry) +{ + PEID_STRUCT eid_ptr; + UINT8 VarOffset = 0; + UINT8 EntryCount = 0; + MESH_PREP_FLAG PrepFlag; + + eid_ptr = (PEID_STRUCT)pMsg; + + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pMsg + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_MESH_PREP: + { + NdisMoveMemory(pFlag, eid_ptr->Octet, 1); + VarOffset += 1; + NdisMoveMemory(pHopCount, eid_ptr->Octet + VarOffset, 1); + VarOffset += 1; + NdisMoveMemory(pTTL, eid_ptr->Octet + VarOffset, 1); + VarOffset += 1; + NdisMoveMemory(pDestMac, eid_ptr->Octet + VarOffset, MAC_ADDR_LEN); + VarOffset += MAC_ADDR_LEN; + NdisMoveMemory(pDesDsn, eid_ptr->Octet + VarOffset, 4); + VarOffset += 4; + *pDesDsn = le2cpu32(*pDesDsn); + PrepFlag = (MESH_PREP_FLAG)(*pFlag); + if (PrepFlag.field.AE == 1) + { + NdisMoveMemory(pProxyMac, eid_ptr->Octet + VarOffset, MAC_ADDR_LEN); + VarOffset += MAC_ADDR_LEN; + } + NdisMoveMemory(pLifeTime, eid_ptr->Octet + VarOffset, 4); + VarOffset += 4; + *pLifeTime = le2cpu32(*pLifeTime); + NdisMoveMemory(pMetric, eid_ptr->Octet + VarOffset, 4); + VarOffset += 4; + *pMetric = le2cpu32(*pMetric); + NdisMoveMemory(pOrigMac, eid_ptr->Octet + VarOffset, MAC_ADDR_LEN); + VarOffset += MAC_ADDR_LEN; + NdisMoveMemory(pOrigDsn, eid_ptr->Octet + VarOffset, 4); + VarOffset += 4; + *pOrigDsn = le2cpu32(*pOrigDsn); + NdisMoveMemory(pDependMPCount, eid_ptr->Octet + VarOffset, 1); + VarOffset += 1; + EntryCount = (*pDependMPCount); + if (EntryCount >= 1) + NdisMoveMemory(pDependEntry, eid_ptr->Octet + VarOffset, 10*EntryCount); + } + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return TRUE; +} + +BOOLEAN MeshPathErrorSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT UINT8 *pFlag, + OUT UINT8 *pDestNum, + OUT PMESH_PERR_ENTRY pErrorEntry) +{ + PEID_STRUCT eid_ptr; + UINT8 VarOffset = 0; + UINT8 EntryCount = 0; + + eid_ptr = (PEID_STRUCT)pMsg; + + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pMsg + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_MESH_PREP: + { + NdisMoveMemory(pFlag, eid_ptr->Octet, 1); + VarOffset += 1; + NdisMoveMemory(pDestNum, eid_ptr->Octet + VarOffset, 1); + VarOffset += 1; + EntryCount = (*pDestNum); + if (EntryCount >= 1) + NdisMoveMemory(pErrorEntry, eid_ptr->Octet + VarOffset, 10*EntryCount); + } + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return TRUE; +} + +BOOLEAN MeshLinkMetricReportSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUINT32 pLinkMetric) +{ + PEID_STRUCT eid_ptr; + UINT32 LinkMetric; + + eid_ptr = (PEID_STRUCT)pMsg; + + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pMsg + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_MESH_LINK_METRIC_REPORT: + { + if (eid_ptr->Len == 4) + { + NdisMoveMemory(&LinkMetric, eid_ptr->Octet, eid_ptr->Len); + *pLinkMetric = le2cpu32(LinkMetric); + } + } + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return TRUE; +} + +#endif /* MESH_SUPPORT */ diff --git a/mt7620/src/common/mesh_tlv.c b/mt7620/src/common/mesh_tlv.c new file mode 100644 index 0000000..70b69b3 --- /dev/null +++ b/mt7620/src/common/mesh_tlv.c @@ -0,0 +1,1008 @@ +/* + *************************************************************************** + * 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: + mesh_tlv.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi 2007-06-25 For mesh (802.11s) support. +*/ +#ifdef MESH_SUPPORT + + +#include "rt_config.h" + +/* Mesh IEs */ +UCHAR MeshIdIE = IE_MESH_ID; +UCHAR MeshConfigurationIE = IE_MESH_CONFIGURATION; +UCHAR MeshLinkMetricReportIE = IE_MESH_LINK_METRIC_REPORT; +UCHAR MeshChSwitchAnnounIE = IE_MESH_CHANNEL_SWITCH_ANNOUNCEMENT; +UCHAR MeshPeerLinkMngIE = IE_MESH_PEER_LINK_MANAGEMENT; +UCHAR VendorSpecificIE = IE_VENDOR_SPECIFIC; +UCHAR MeshMSCIE = IE_MESH_MSCIE; +UCHAR MeshMSAIE = IE_MESH_MSAIE; + +/* Mesh OUIs */ +UCHAR MeshOUI[3] = {0x00, 0x0f, 0xac}; + +UINT8 LenPeerLinkMngIE[3] = { + 3, /* Peer Link Open */ + 5, /* Peer Link confirm */ + 7, /* Peer Link close */ +}; + +VOID MeshHeaderInit( + IN PRTMP_ADAPTER pAd, + OUT PHEADER_802_11 pMeshHdr, + IN PUCHAR Addr1, + IN PUCHAR Addr2, + IN PUCHAR Addr3) +{ + NdisZeroMemory(pMeshHdr, sizeof(HEADER_802_11)); + + pMeshHdr->FC.Type = BTYPE_MESH; + pMeshHdr->FC.SubType = SUBTYPE_MULTIHOP; + pMeshHdr->FC.FrDs = 0; + pMeshHdr->FC.ToDs = 0; + + COPY_MAC_ADDR(pMeshHdr->Addr1, Addr1); + COPY_MAC_ADDR(pMeshHdr->Addr2, Addr2); + COPY_MAC_ADDR(pMeshHdr->Addr3, Addr3); + + return; +} + +VOID InsertMeshHeader( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 MeshFlag, + IN UINT8 TTL, + IN UINT32 MeshSeq, + IN PUCHAR Addr4, + IN PUCHAR Addr5, + IN PUCHAR Addr6) +{ + ULONG TempLen; + PMESH_FLAG pMeshFlagBuf = (PMESH_FLAG)&MeshFlag; + UINT32 MeshSeqBuf; + + MeshSeqBuf = cpu2le32(MeshSeq); + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &MeshFlag, + 1, &TTL, + 4, &MeshSeqBuf, + END_OF_ARGS); + *pFrameLen = *pFrameLen + TempLen; + pFrameBuf += TempLen; + + if (Addr4 && (pMeshFlagBuf->field.AE & 0x01)) + { + MakeOutgoingFrame( pFrameBuf, &TempLen, + MAC_ADDR_LEN, Addr4, + END_OF_ARGS); + *pFrameLen = *pFrameLen + TempLen; + pFrameBuf += TempLen; + } + + if (Addr5 && Addr6 && (pMeshFlagBuf->field.AE & 0x02)) + { + MakeOutgoingFrame( pFrameBuf, &TempLen, + MAC_ADDR_LEN, Addr5, + MAC_ADDR_LEN, Addr6, + END_OF_ARGS); + *pFrameLen = *pFrameLen + TempLen; + } + + return; +} + +VOID InsertMeshActField( + 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; +} + +VOID InsertCapabilityInfo( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT16 CapabilityInfo) +{ + ULONG TempLen; + + CapabilityInfo = cpu2le16(CapabilityInfo); + MakeOutgoingFrame( pFrameBuf, &TempLen, + 2, &CapabilityInfo, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +VOID 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; +} + +VOID 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; +} + +VOID InsertAID( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT16 Aid) +{ + ULONG TempLen; + + Aid = cpu2le16(Aid); + MakeOutgoingFrame( pFrameBuf, &TempLen, + 2, &Aid, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +VOID InsertSupRateIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + ULONG TempLen; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &SupRateIe, + 1, &pAd->CommonCfg.SupRateLen, + pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRate, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +VOID InsertExtRateIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + ULONG TempLen; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &ExtRateIe, + 1, &pAd->CommonCfg.ExtRateLen, + pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +VOID InsertMeshConfigurationIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN BOOLEAN AcptLink) +{ + ULONG TempLen; + UCHAR Len = 19; + UCHAR Ver = MESH_VERSION; + MESH_CAPABILITY MeshCapInfo; + UINT32 CPI = cpu2le32(pAd->MeshTab.CPI); + + if (!pAd->MeshTab.dev) + return; + + /*if(!MESH_ON(pAd)) */ + /* return; */ + + MeshCapInfo.word = cpu2le16(pAd->MeshTab.MeshCapability.word); + /* Force accept the link when Peer-Link-Open/Peer-Link-Confirm. */ + if (AcptLink == TRUE) + MeshCapInfo.field.AcceptPeerLinks = 1; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &MeshConfigurationIE, + 1, &Len, + 1, &Ver, + 3, &MeshOUI, + 1, (PUCHAR)&pAd->MeshTab.PathProtocolId, + 3, &MeshOUI, + 1, (PUCHAR)&pAd->MeshTab.PathMetricId, + 3, &MeshOUI, + 1, (PUCHAR)&pAd->MeshTab.ContgesionCtrlId, + 4, (PUCHAR)&CPI, + 2, (PUCHAR)&MeshCapInfo.word, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + + +VOID InsertMeshIdIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + ULONG TempLen; + UCHAR MeshIdLen = pAd->MeshTab.MeshIdLen; + + if (!pAd->MeshTab.dev) + return; + + /*if(!MESH_ON(pAd)) */ + /* return; */ + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &MeshIdIE, + 1, &MeshIdLen, + MeshIdLen, (PUCHAR)pAd->MeshTab.MeshId, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + + +VOID InsertMSCIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + ULONG TempLen; + UCHAR MCSIE_Len = sizeof(MESH_SECURITY_CAPABILITY_IE); + MESH_SECURITY_CONFIGURATION MeshSecConfig; + + if (!pAd->MeshTab.dev) + return; + + /*if(!MESH_ON(pAd)) */ + /* return; */ + + MeshSecConfig.word = 0; + if (pAd->MeshTab.bKeyholderDone) + MeshSecConfig.field.MeshAuthenticator = 1; + if ((pAd->MeshTab.bKeyholderDone) && (pAd->MeshTab.bConnectedToMKD)) + MeshSecConfig.field.ConnectedToMKD = 1; + MeshSecConfig.field.DefaultRole = 1; + + pAd->MeshTab.LocalMSCIE.MeshSecurityConfig.word = MeshSecConfig.word; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &MeshMSCIE, + 1, &MCSIE_Len, + MCSIE_Len, &pAd->MeshTab.LocalMSCIE, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +VOID InsertMSAIE( + IN PRTMP_ADAPTER pAd, + IN UCHAR LinkIdx, + IN UCHAR state, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + ULONG TempLen; + UCHAR Buf[MESH_MAX_MSAIE_LEN]; + UCHAR len; + + if (!pAd->MeshTab.dev) + return; + + /*if(!MESH_ON(pAd)) */ + /* return; */ + + /* clear the local MP's MSAIE field */ + NdisZeroMemory(Buf, MESH_MAX_MSAIE_LEN); + len = 0; + + /* Copy content from Local MP's MSAIE */ + NdisMoveMemory(Buf, + pAd->MeshTab.MeshLink[LinkIdx].Entry.LocalMsaIe, + pAd->MeshTab.MeshLink[LinkIdx].Entry.LocalMsaIeLen); + len += pAd->MeshTab.MeshLink[LinkIdx].Entry.LocalMsaIeLen; + + /* Zero this MA-ID field in peer link open frame */ + if (state == SUBTYPE_PEER_LINK_OPEN) + { + PMSA_HANDSHAKE_IE pLocalMsaIE; + + pLocalMsaIE = (PMSA_HANDSHAKE_IE)Buf; + NdisZeroMemory(pLocalMsaIE->MA_ID, MAC_ADDR_LEN); + } + + /* Fill in Optional Parameter */ + if (!pAd->MeshTab.EasyMeshSecurity) + { + /* Optional Parameter - MKD-ID */ + if (state == SUBTYPE_PEER_LINK_CONFIRM) + { + + + + } + + + /* Optional Parameter - Key Holder Transport List */ + if (state == SUBTYPE_PEER_LINK_CONFIRM) + { + + + + } + + + /* Optional Parameter - PMK-MKDName */ + /* PMK-MKDName shall be present if the RSNIE in this message contains a PMKMAName */ + /* (sender) value in the PMKID list field in P.L. open frame. */ + if ((state == SUBTYPE_PEER_LINK_OPEN) && (pAd->MeshTab.PMKID_Len > 0)) + { + + + } + + /* Optional Parameter - MKD-NAS_ID */ + if (state == SUBTYPE_PEER_LINK_CONFIRM) + { + + + + } + + + } + + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &MeshMSAIE, + 1, &len, + len, Buf, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + + +VOID InsertRSNIE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + ULONG TempLen; + UCHAR total_len; + USHORT count = 0; + UCHAR PmkMaName[LEN_PMKID]; + UCHAR rsn_ie = Wpa2Ie; + + total_len = pAd->MeshTab.RSNIE_Len; + + if (pAd->MeshTab.AuthMode == Ndis802_11AuthModeWPANone) + rsn_ie = WpaIe; + + /* If the local MP isn't an MKD and it had completed its Initial MSA, */ + /* insert the PMKMAName(sender) into PMKID list */ + /* PMK-MAName(sender), the identifier of the currently-valid PMK-MA belonging to the key */ + /* hierarchy created by the local MP during a prior Initial MSA Authentication, that may be used to */ + /* secure a link with the peer MP. This entry shall be omitted if no currently valid PMK-MA exists, */ + /* or if the local MP requests Initial MSA Authentication. */ + if (!(pAd->MeshTab.OpMode & MESH_MKD) && pAd->MeshTab.bInitialMsaDone && pAd->MeshTab.PMKID_Len == LEN_PMKID) + { + count = 1; + total_len += (2+ LEN_PMKID); /* PMKID-Count(2) + one-PMKID */ + } + + /* PMK-MAName(receiver), the identifier of a PMK-MA belonging to the key hierarchy created */ + /* by the peer MP during its Initial MSA Authentication. */ + /* This entry is included only if a PMKMAName(sender) is included, */ + /* and only if the MA function of the local MP has cached the identified */ + /* PMK-MA that may be used to secure a link with the peer MP. */ + if (count > 0 && (pAddr != NULL) && pAd->MeshTab.bKeyholderDone) + { + PMAC_TABLE_ENTRY pEntry = NULL; + UCHAR idx; + + if((pEntry = MeshTableLookup(pAd, pAddr, TRUE)) != NULL) + { + idx = pEntry->MatchMeshTabIdx; + + if ((pAd->MeshTab.MeshLink[idx].Entry.bInitialMsaLink == TRUE) && + (pAd->MeshTab.LocalMpInitialMsaLink != (idx + 1))) + { + count += 1; + total_len += LEN_PMKID; + NdisMoveMemory(PmkMaName, pAd->MeshTab.MeshLink[idx].Entry.PMK_MA_NAME, LEN_PMKID); + } + } + } + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &rsn_ie, + 1, &total_len, + pAd->MeshTab.RSNIE_Len, pAd->MeshTab.RSN_IE, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + if (count == 2) + { +#ifdef RT_BIG_ENDIAN + count = SWAP16(count); +#endif + + pFrameBuf += TempLen; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 2, &count, + LEN_PMKID, pAd->MeshTab.PMKID, + LEN_PMKID, PmkMaName, + END_OF_ARGS); + *pFrameLen = *pFrameLen + TempLen; + + + } + else if (count == 1) + { +#ifdef RT_BIG_ENDIAN + count = SWAP16(count); +#endif + + pFrameBuf += TempLen; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 2, &count, + LEN_PMKID, pAd->MeshTab.PMKID, + END_OF_ARGS); + *pFrameLen = *pFrameLen + TempLen; + } + + + return; +} + +VOID InsertMeshPeerLinkMngIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 SubType, + IN UINT16 LocalLinkId, + IN UINT16 PeerLinkId, + IN UINT16 ReasonCode) +{ + ULONG TempLen; + UINT8 Len; + + if (!pAd->MeshTab.dev) + return; + + Len = LenPeerLinkMngIE[SubType]; + LocalLinkId = cpu2le16(LocalLinkId); + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &MeshPeerLinkMngIE, + 1, &Len, + 1, &SubType, + 2, (PUCHAR)&LocalLinkId, + END_OF_ARGS); + *pFrameLen = *pFrameLen + TempLen; + pFrameBuf += TempLen; + + /* Peer Link Id is not presetn for the peer link open, */ + /* is present for the peer link confirm and may be present */ + /* for Peer Link Close. */ + if (SubType != SUBTYPE_PEER_LINK_OPEN) + { + PeerLinkId = cpu2le16(PeerLinkId); + MakeOutgoingFrame( pFrameBuf, &TempLen, + 2, (PUCHAR)&PeerLinkId, + END_OF_ARGS); + *pFrameLen = *pFrameLen + TempLen; + pFrameBuf += TempLen; + } + + /* reason code field is not resent for Peer Link Open and Peer Link Confirm. */ + if (SubType == SUBTYPE_PEER_LINK_CLOSE) + { + ReasonCode = cpu2le16(ReasonCode); + MakeOutgoingFrame( pFrameBuf, &TempLen, + 2, (PUCHAR)&ReasonCode, + END_OF_ARGS); + *pFrameLen = *pFrameLen + TempLen; + } + + return; +} + +VOID InsertMeshPathRequestIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 MeshPreqFlag, + IN UCHAR HopCount, + IN UCHAR TTL, + IN ULONG ReqID, + IN PUCHAR pOrigAddr, + IN ULONG OrigDsn, + IN PUCHAR pOrigProxyAddr, + IN ULONG LifeTime, + IN ULONG Metrics, + IN UCHAR DestCount, + IN MESH_DEST_ENTRY MeshDestEntry) +{ + ULONG TempLen; + UCHAR MeshPreqLen = 26; + UCHAR MeshPathRequestIE = IE_MESH_PREQ; + UCHAR ProxyAddrLen = 0; + + if (!pAd->MeshTab.dev) + return; + + if(!MESH_ON(pAd)) + return; + + if (pOrigProxyAddr) + { + ProxyAddrLen = MAC_ADDR_LEN; + MeshPreqLen += MAC_ADDR_LEN; + } + else + { + ProxyAddrLen = 0; + } + + MeshPreqLen += (DestCount * 11); + + ReqID = cpu2le32(ReqID); + OrigDsn = cpu2le32(OrigDsn); + LifeTime = cpu2le32(LifeTime); + Metrics = cpu2le32(Metrics); + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &MeshPathRequestIE, + 1, &MeshPreqLen, + 1, &MeshPreqFlag, + 1, &HopCount, + 1, &TTL, + 4, &ReqID, + MAC_ADDR_LEN, pOrigAddr, + 4, &OrigDsn, + ProxyAddrLen, pOrigProxyAddr, + 4, &LifeTime, + 4, &Metrics, + 1, &DestCount, + 11, &MeshDestEntry, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +VOID InsertMeshPathResponseIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 MeshPrepFlag, + IN UCHAR HopCount, + IN UCHAR TTL, + IN PUCHAR pDestAddr, + IN ULONG DestSeq, + IN PUCHAR pDestProxyAddr, + IN ULONG LifeTime, + IN ULONG Metrics, + IN PUCHAR pOrigAddr, + IN ULONG OrigSeq) +{ + ULONG TempLen; + UCHAR MeshPrepLen = 31; + UCHAR MeshPathResponseIE = IE_MESH_PREP; + UCHAR ProxyAddrLen = 0; + + + if (!pAd->MeshTab.dev) + return; + + if(!MESH_ON(pAd)) + return; + + if (pDestProxyAddr) + { + ProxyAddrLen = MAC_ADDR_LEN; + MeshPrepLen += MAC_ADDR_LEN; + } + else + { + ProxyAddrLen = 0; + } + + DestSeq = cpu2le32(DestSeq); + LifeTime = cpu2le32(LifeTime); + Metrics = cpu2le32(Metrics); + OrigSeq = cpu2le32(OrigSeq); + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &MeshPathResponseIE, + 1, &MeshPrepLen, + 1, &MeshPrepFlag, + 1, &HopCount, + 1, &TTL, + MAC_ADDR_LEN, pDestAddr, + 4, &DestSeq, + ProxyAddrLen, pDestProxyAddr, + 4, &LifeTime, + 4, &Metrics, + MAC_ADDR_LEN, pOrigAddr, + 4, &OrigSeq, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +VOID InsertMeshPathErrorIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UCHAR DestCount, + IN PMESH_PERR_ENTRY pMeshPerrEntry) +{ + ULONG TempLen; + UCHAR MeshPerrLen = 2; + UCHAR MeshPathErrorIE = IE_MESH_PERR; + UCHAR MeshPerrFlag = 0; + + if (!pAd->MeshTab.dev) + return; + + if(!MESH_ON(pAd)) + return; + + MeshPerrLen += (DestCount * 10); + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &MeshPathErrorIE, + 1, &MeshPerrLen, + 1, &MeshPerrFlag, + 1, &DestCount, + (10*DestCount), pMeshPerrEntry, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +VOID InsertMeshProxyUpdateIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 ProxyFlags, + IN UINT8 ProxySeq, + IN PUCHAR pProxyMPAddr, + IN USHORT ProxiedCount, + IN PUCHAR pMeshProxiedEntry) +{ + ULONG TempLen; + UCHAR IeLen = 12; + UCHAR MeshProxyUpdateIE = IE_MESH_PU; + + if (!pAd->MeshTab.dev) + return; + + if(!MESH_ON(pAd)) + return; + + IeLen += (ProxiedCount * 6); + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &MeshProxyUpdateIE, + 1, &IeLen, + 1, &ProxyFlags, + 1, &ProxySeq, + MAC_ADDR_LEN, pProxyMPAddr, + 2, &ProxiedCount, + (MAC_ADDR_LEN*ProxiedCount), pMeshProxiedEntry, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +VOID InsertMeshProxyUpdateConfirmationIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 ProxyConfirmFlagFlags, + IN UINT8 ProxySeq, + IN PUCHAR pMeshProxiedEntry) +{ + ULONG TempLen; + UCHAR IeLen = 10; + UCHAR MeshProxyUpdateIE = IE_MESH_PU; + UINT8 MeshProxyUpdateConfirmFlag = 0; + + if (!pAd->MeshTab.dev) + return; + + if(!MESH_ON(pAd)) + return; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &MeshProxyUpdateIE, + 1, &IeLen, + 1, &MeshProxyUpdateConfirmFlag, + 1, &ProxySeq, + MAC_ADDR_LEN, pMeshProxiedEntry, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +VOID InsertMeshHostNameIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + ULONG TempLen; + UCHAR Len; + UCHAR HostNameLen; + + if (!pAd->MeshTab.dev) + return; + + HostNameLen = strlen((PSTRING) pAd->MeshTab.HostName); + Len = sizeof(MeshOUI) + HostNameLen; + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &VendorSpecificIE, + 1, &Len, + 3, &MeshOUI, + HostNameLen, (PUCHAR)&pAd->MeshTab.HostName, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +VOID InsertMeshCongestionNotofocationIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUCHAR pPeerMac, + IN UCHAR SwitchOn) +{ + ULONG TempLen; + UCHAR Len = 7; + UCHAR MeshMultiPathNotice = IE_MESH_MULITI_PATH_NOTICE_IE; + UCHAR Flag; + + if (!pAd->MeshTab.dev) + return; + + Flag = (SwitchOn == FALSE) ? 0x00 : 0x01; + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &MeshMultiPathNotice, + 1, &Len, + 1, &Flag, + MAC_ADDR_LEN, pPeerMac, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +VOID InsertMeshChSwAnnIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 ChSwMode, + IN UINT8 NewCh, + IN UINT32 NewCPI, + IN UINT8 ChSwCnt, + IN PUCHAR pMeshSA) +{ + ULONG TempLen; + UCHAR Len = 13; + UCHAR MeshChSwAnnIE = IE_MESH_CHANNEL_SWITCH_ANNOUNCEMENT; + + if (!pAd->MeshTab.dev) + return; + + NewCPI = cpu2le32(NewCPI); + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &MeshChSwAnnIE, + 1, &Len, + 1, &ChSwMode, + 1, &NewCh, + 4, &NewCPI, + 1, &ChSwCnt, + MAC_ADDR_LEN, pMeshSA, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +#ifdef DOT11_N_SUPPORT +VOID InsertHtCapIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PHT_CAPABILITY_IE pHtCapability) +{ + ULONG TempLen; + 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(pFrameBuf, &TempLen, + 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(pFrameBuf, &TempLen, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, + END_OF_ARGS); +#endif + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +VOID InsertAddHtInfoIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PADD_HT_INFO_IE pAddHTInfo) +{ + ULONG TempLen; + UCHAR HtLen; + +#ifdef RT_BIG_ENDIAN + ADD_HT_INFO_IE addHTInfoTmp; +#endif + + HtLen = sizeof(ADD_HT_INFO_IE); + +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &AddHtInfoIe, + 1, &HtLen, + HtLen, pAddHTInfo, + END_OF_ARGS); +#else + NdisMoveMemory(&addHTInfoTmp, pAddHTInfo, HtLen); + *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); + *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &AddHtInfoIe, + 1, &HtLen, + HtLen, &addHTInfoTmp, + END_OF_ARGS); +#endif + *pFrameLen = *pFrameLen + TempLen; + + return; +} +#endif /* DOT11_N_SUPPORT */ + +VOID InsertLinkMetricReportIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT32 LinkMetric) +{ + ULONG TempLen; + UCHAR Len = 4; + UCHAR IEId = IE_MESH_LINK_METRIC_REPORT; + UINT32 LinkMetricValue; + + if (!pAd->MeshTab.dev) + return; + + LinkMetricValue = cpu2le32(LinkMetric); + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &IEId, + 1, &Len, + Len, (PUCHAR)&LinkMetricValue, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +#endif /* MESH_SUPPORT */ diff --git a/mt7620/src/common/misc.c b/mt7620/src/common/misc.c new file mode 100644 index 0000000..72ca956 --- /dev/null +++ b/mt7620/src/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/mt7620/src/common/mlme.c b/mt7620/src/common/mlme.c new file mode 100644 index 0000000..7469657 --- /dev/null +++ b/mt7620/src/common/mlme.c @@ -0,0 +1,7115 @@ +/* + *************************************************************************** + * 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 + -------- ---------- ---------------------------------------------- + John Chang 2004-08-25 Modify from RT2500 code base + John Chang 2004-09-06 modified for RT2600 +*/ + +#include "rt_config.h" +#include + + +UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96}; + +UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43}; +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 */ +#ifdef DOT11_N_SUPPORT +UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c}; +#endif /* DOT11_N_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef WAC_SUPPORT +extern UCHAR SAMSUNG_OUI[]; +extern UCHAR SAMSUNG_OUI_TYPE; +#endif /* WAC_SUPPORT */ +#ifdef CONFIG_APSTA_MIXED_SUPPORT +UINT32 CW_MAX_IN_BITS; +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ + + + + +extern UCHAR OfdmRateToRxwiMCS[]; +/* 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 INF_AMAZON_SE +UINT16 MaxBulkOutsSizeLimit[5][4] = +{ + /* Priority high -> low*/ + { 24576, 2048, 2048, 2048 }, /* 0 AC */ + { 24576, 2048, 2048, 2048 }, /* 1 AC */ + { 24576, 2048, 2048, 2048 }, /* 2 ACs*/ + { 24576, 6144, 2048, 2048 }, /* 3 ACs*/ + { 24576, 6144, 4096, 2048 } /* 4 ACs*/ +}; + +VOID SoftwareFlowControl( + IN PRTMP_ADAPTER pAd) +{ + + BOOLEAN ResetBulkOutSize=FALSE; + UCHAR i=0,RunningQueueNo=0,QueIdx=0,HighWorkingAcCount=0; + UINT PacketsInQueueSize=0; + UCHAR Priority[]={1,0,2,3}; + + for (i=0;iTxContext[i].CurWritePosition>=pAd->TxContext[i].NextBulkOutPosition) + { + PacketsInQueueSize=pAd->TxContext[i].CurWritePosition-pAd->TxContext[i].NextBulkOutPosition; + } + else + { + PacketsInQueueSize=MAX_TXBULK_SIZE-pAd->TxContext[i].NextBulkOutPosition+pAd->TxContext[i].CurWritePosition; + } + + if (pAd->BulkOutDataSizeCount[i]>20480 || PacketsInQueueSize>6144) + { + RunningQueueNo++; + pAd->BulkOutDataFlag[i]=TRUE; + } + else + pAd->BulkOutDataFlag[i]=FALSE; + + pAd->BulkOutDataSizeCount[i]=0; + } + + if (RunningQueueNo>pAd->LastRunningQueueNo) + { + DBGPRINT(RT_DEBUG_INFO,("SoftwareFlowControl reset %d > %d \n",RunningQueueNo,pAd->LastRunningQueueNo)); + +ResetBulkOutSize=TRUE; + pAd->RunningQueueNoCount=0; + pAd->LastRunningQueueNo=RunningQueueNo; + } + else if (RunningQueueNo==pAd->LastRunningQueueNo) + { +pAd->RunningQueueNoCount=0; + } + else if (RunningQueueNoLastRunningQueueNo) + { + DBGPRINT(RT_DEBUG_INFO,("SoftwareFlowControl reset %d < %d \n",RunningQueueNo,pAd->LastRunningQueueNo)); + pAd->RunningQueueNoCount++; + if (pAd->RunningQueueNoCount>=6) + { + ResetBulkOutSize=TRUE; + pAd->RunningQueueNoCount=0; + pAd->LastRunningQueueNo=RunningQueueNo; + } + } + + if (ResetBulkOutSize==TRUE) + { + for (QueIdx=0;QueIdxBulkOutDataFlag[i]==TRUE && Priority[i]>Priority[QueIdx]) + HighWorkingAcCount++; + + } + pAd->BulkOutDataSizeLimit[QueIdx]=MaxBulkOutsSizeLimit[RunningQueueNo][HighWorkingAcCount]; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Reset bulkout size AC0(BE):%7d AC1(BK):%7d AC2(VI):%7d AC3(VO):%7d %d\n",pAd->BulkOutDataSizeLimit[0] + ,pAd->BulkOutDataSizeLimit[1] + ,pAd->BulkOutDataSizeLimit[2] + ,pAd->BulkOutDataSizeLimit[3] + ,RunningQueueNo)); + } + +} +#endif /* INF_AMAZON_SE */ + +/* + ========================================================================== + 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( + IN PRTMP_ADAPTER pAd) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + + DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n")); + + do + { + Status = MlmeQueueInit(pAd, &pAd->Mlme.Queue); + 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 */ + + + + /* 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 PCIE_PS_SUPPORT + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + /* only PCIe cards need these two timers*/ + RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE); + } +#endif /* PCIE_PS_SUPPORT */ + + 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) + { + /* 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); + +#ifdef APCLI_SUPPORT + /* 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 */ + } + +#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 MESH_SUPPORT + ASSERT(MESH_CTRL_FUNC_SIZE == MESH_CTRL_MAX_EVENTS * MESH_CTRL_MAX_STATES); + MeshCtrlStateMachineInit(pAd, &pAd->Mlme.MeshCtrlMachine, pAd->Mlme.MeshCtrlFunc); + + ASSERT(MESH_LINK_MNG_FUNC_SIZE == MESH_LINK_MNG_MAX_EVENTS * MESH_LINK_MNG_MAX_STATES); + MeshLinkMngStateMachineInit(pAd, &pAd->Mlme.MeshLinkMngMachine, pAd->Mlme.MeshLinkMngFunc); +#endif /* MESH_SUPPORT */ + + 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 P2P_SUPPORT + /* P2P Ctrl State Machine */ + ASSERT(P2P_CTRL_FUNC_SIZE == P2P_CTRL_MAX_EVENTS * P2P_CTRL_MAX_STATES); + P2PCtrlStateMachineInit(pAd, &pAd->P2pCfg.P2PCtrlMachine, pAd->P2pCfg.P2PCtrlFunc); + + /* P2P Discovery State Machine */ + ASSERT(P2P_DISC_FUNC_SIZE == P2P_DISC_MAX_EVENTS * P2P_DISC_MAX_STATES); + P2PDiscoveryStateMachineInit(pAd, &pAd->P2pCfg.P2PDiscMachine, pAd->P2pCfg.P2PDiscFunc); + + /* P2P Group Formation State Machine */ + ASSERT(P2P_GO_FORM_FUNC_SIZE == P2P_GO_NEGO_MAX_EVENTS * P2P_GO_FORM_MAX_STATES); + P2PGoFormationStateMachineInit(pAd, &pAd->P2pCfg.P2PGoFormMachine, pAd->P2pCfg.P2PGoFormFunc); + + /* P2P Action Frame State Machine */ + ASSERT(P2P_ACTION_FUNC_SIZE == MAX_P2P_MSG * MAX_P2P_STATE); + P2PStateMachineInit(pAd, &pAd->P2pCfg.P2PActionMachine, pAd->P2pCfg.P2PActionFunc); + + /* P2P CTWindows timer */ + RTMPInitTimer(pAd, &pAd->P2pCfg.P2pCTWindowTimer, GET_TIMER_FUNCTION(P2PCTWindowTimer), pAd, FALSE); + /* P2P SwNOA timer */ + RTMPInitTimer(pAd, &pAd->P2pCfg.P2pSwNoATimer, GET_TIMER_FUNCTION(P2pSwNoATimeOut), pAd, FALSE); + /* P2P Presence Absent timer */ + RTMPInitTimer(pAd, &pAd->P2pCfg.P2pPreAbsenTimer, GET_TIMER_FUNCTION(P2pPreAbsenTimeOut), pAd, FALSE); + /* P2P WSC Timer */ + RTMPInitTimer(pAd, &pAd->P2pCfg.P2pWscTimer, GET_TIMER_FUNCTION(P2pWscTimeOut), pAd, FALSE); + /* P2P Re-Transmit Action Frame Timer */ + RTMPInitTimer(pAd, &pAd->P2pCfg.P2pReSendTimer, GET_TIMER_FUNCTION(P2pReSendTimeOut), pAd, FALSE); + /* P2P CLIENT Re-Connect Timer */ + RTMPInitTimer(pAd, &pAd->P2pCfg.P2pCliReConnectTimer, GET_TIMER_FUNCTION(P2pCliReConnectTimeOut), pAd, FALSE); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(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); +#ifdef APCLI_SUPPORT + /* 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 */ + + /* Init APSD periodic timer */ + RTMPInitTimer(pAd, &pAd->Mlme.APSDPeriodicTimer, GET_TIMER_FUNCTION(APSDPeriodicExec), pAd, TRUE); + RTMPSetTimer(&pAd->Mlme.APSDPeriodicTimer, 50); + } +#endif /* CONFIG_STA_SUPPORT */ +#endif /* P2P_SUPPORT */ + + } while (FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n")); + + return Status; +} + + +/* + ========================================================================== + 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 MlmeHandler will run. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeHandler( + IN PRTMP_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)) + { + 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)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num)); + break; + } + +#ifdef RALINK_ATE + if(ATE_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now in MlmeHandler\n")); + break; + } +#endif /* RALINK_ATE */ + + /*From message type, determine which state machine I should drive*/ + if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) + { + + /* 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 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); +/*#ifdef KTHREAD_SUPPORT*/ +/* WAKE_UP(&(pAd->wscTask));*/ +/*#else*/ +/* RTMP_SEM_EVENT_UP(&(pAd->wscTask.taskSema));*/ +/*#endif*/ + 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 MESH_SUPPORT + case MESH_CTRL_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.MeshCtrlMachine, Elem, + pAd->MeshTab.CtrlCurrentState); + break; + + case MESH_LINK_MNG_STATE_MACHINE: + if (VALID_MESH_LINK_ID(Elem->Priv)) + StateMachinePerformAction(pAd, &pAd->Mlme.MeshLinkMngMachine, Elem, + pAd->MeshTab.MeshLink[Elem->Priv].CurrentState); + break; +#endif /* MESH_SUPPORT */ + +#ifdef P2P_SUPPORT + case P2P_CTRL_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->P2pCfg.P2PCtrlMachine, Elem, + pAd->P2pCfg.CtrlCurrentState); + break; + case P2P_DISC_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->P2pCfg.P2PDiscMachine, Elem, + pAd->P2pCfg.DiscCurrentState); + break; + case P2P_GO_FORM_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->P2pCfg.P2PGoFormMachine, Elem, + pAd->P2pCfg.GoFormCurrentState); + break; + case P2P_ACTION_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->P2pCfg.P2PActionMachine, Elem, + pAd->P2pCfg.ActionState); + break; +#endif /* P2P_SUPPORT */ + default: + DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine)); + break; + } /* end of switch*/ + + /* free MLME element*/ + Elem->Occupied = FALSE; + Elem->MsgLen = 0; + + } + else { + DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n")); + } + } + + NdisAcquireSpinLock(&pAd->Mlme.TaskLock); + pAd->Mlme.bRunning = FALSE; + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); +} + +/* + ========================================================================== + 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( + IN PRTMP_ADAPTER pAd) +{ + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\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 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) + { +#ifdef APCLI_SUPPORT + UCHAR i; +#endif /* APCLI_SUPPORT */ + + RTMPCancelTimer(&pAd->Mlme.APSDPeriodicTimer, &Cancelled); + + if (pAd->ApCfg.ApQuickResponeForRateUpTimerRunning == TRUE) + RTMPCancelTimer(&pAd->ApCfg.ApQuickResponeForRateUpTimer, &Cancelled); + +#ifdef APCLI_SUPPORT + for (i = 0; i < MAX_APCLI_NUM; i++) + { + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[i].ApCliMlmeAux.ProbeTimer, &Cancelled); + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[i].ApCliMlmeAux.ApCliAssocTimer, &Cancelled); + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[i].ApCliMlmeAux.ApCliAuthTimer, &Cancelled); + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[i].ApCliMlmeAux.WpaDisassocAndBlockAssocTimer, &Cancelled); + +#ifdef WSC_AP_SUPPORT + if (pAd->ApCfg.ApCliTab[i].WscControl.WscProfileRetryTimerRunning) + { + pAd->ApCfg.ApCliTab[i].WscControl.WscProfileRetryTimerRunning = FALSE; + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[i].WscControl.WscProfileRetryTimer, &Cancelled); + } +#endif /* WSC_AP_SUPPORT */ + } +#endif /* APCLI_SUPPORT */ + RTMPCancelTimer(&pAd->MlmeAux.APScanTimer, &Cancelled); + } + +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef MESH_SUPPORT + MeshHalt(pAd); +#endif /* MESH_SUPPORT */ + +#ifdef P2P_SUPPORT + /* P2P CTWindows timer */ + RTMPCancelTimer(&pAd->P2pCfg.P2pCTWindowTimer, &Cancelled); + /* P2P SwNOA timer */ + RTMPCancelTimer(&pAd->P2pCfg.P2pSwNoATimer, &Cancelled); + /* P2P Presence Absent timer */ + RTMPCancelTimer(&pAd->P2pCfg.P2pPreAbsenTimer, &Cancelled); + + if (pAd->P2pCfg.bP2pCliReConnectTimerRunning) + { + pAd->P2pCfg.bP2pCliReConnectTimerRunning = FALSE; + RTMPCancelTimer(&pAd->P2pCfg.P2pCliReConnectTimer, &Cancelled); + } + + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + RTMPCancelTimer(&pAd->Mlme.APSDPeriodicTimer, &Cancelled); + UCHAR i; + for (i = 0; i < MAX_APCLI_NUM; i++) + { + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[i].ApCliMlmeAux.ProbeTimer, &Cancelled); + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[i].ApCliMlmeAux.ApCliAssocTimer, &Cancelled); + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[i].ApCliMlmeAux.ApCliAuthTimer, &Cancelled); + } + +#ifdef WSC_AP_SUPPORT + if (pAd->ApCfg.ApCliTab[BSS0].WscControl.WscProfileRetryTimerRunning) + { + pAd->ApCfg.ApCliTab[BSS0].WscControl.WscProfileRetryTimerRunning = FALSE; + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[BSS0].WscControl.WscProfileRetryTimer, &Cancelled); + } +#endif /* WSC_AP_SUPPORT */ + RTMPCancelTimer(&pAd->MlmeAux.APScanTimer, &Cancelled); + } +#endif /* P2P_SUPPORT */ + + 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) + if (pAd->WOW_Cfg.bEnable == FALSE) +#endif /* WOW_SUPPORT */ + if (pChipOps->AsicHaltAction) + pChipOps->AsicHaltAction(pAd); + } + + RTMPusecDelay(5000); /* 5 msec to gurantee Ant Diversity timer canceled*/ + + MlmeQueueDestroy(&pAd->Mlme.Queue); + NdisFreeSpinLock(&pAd->Mlme.TaskLock); + + DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n")); +} + +VOID MlmeResetRalinkCounters( + IN PRTMP_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; + PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext; + + /* No More 0x84 MCU CMD from v.30 FW*/ + + +#ifdef MICROWAVE_OVEN_SUPPORT + //printk("MO_Cfg.bEnable=%d \n", pAd->CommonCfg.MO_Cfg.bEnable); + if (pAd->CommonCfg.MO_Cfg.bEnable) + { + UINT8 stage = pAd->CommonCfg.MO_Cfg.nPeriod_Cnt%10; + + if (stage == MO_MEAS_PERIOD) + { + //printk("Microwave measure... \n"); + AsicMeasureFalseCCA(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) + AsicMitigateMicrowave(pAd); + } + pAd->CommonCfg.MO_Cfg.nPeriod_Cnt++; + } +#endif /* MICROWAVE_OVEN_SUPPORT */ + +#ifdef INF_AMAZON_SE + SoftwareFlowControl(pAd); +#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); + /* Update extra information*/ + pAd->ExtraInfo = EXTRA_INFO_CLEAR; + } + else + { + MlmeRadioOff(pAd); + /* Update extra information*/ + pAd->ExtraInfo = HW_RADIO_OFF; + } + } + } + } + } +#endif /* RTMP_MAC_PCI */ + + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + RTMP_MLME_PRE_SANITY_CHECK(pAd); + } + + +#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; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* Do nothing if monitor mode is on*/ + if (MONITOR_ON(pAd)) + return; + + if (pAd->Mlme.PeriodicRound & 0x1) + { + /* This is the fix for wifi 11n extension channel overlapping test case. for 2860D*/ + if (((pAd->MACVersion & 0xffff) == 0x0101) && + (STA_TGN_WIFI_ON(pAd)) && + (pAd->CommonCfg.IOTestParm.bToggle == FALSE)) + + { + RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf); + pAd->CommonCfg.IOTestParm.bToggle = TRUE; + } + else if ((STA_TGN_WIFI_ON(pAd)) && + ((pAd->MACVersion & 0xffff) == 0x0101)) + { + RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f); + pAd->CommonCfg.IOTestParm.bToggle = FALSE; + } + } + } +#endif /* CONFIG_STA_SUPPORT */ + + pAd->bUpdateBcnCntDone = FALSE; + +/* RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);*/ + pAd->Mlme.PeriodicRound ++; + pAd->Mlme.GPIORound++; + + + /* by default, execute every 500ms */ + if ((pAd->ra_interval) && + ((pAd->Mlme.PeriodicRound % (pAd->ra_interval / 100)) == 0) && + 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 MESH_SUPPORT + || MESH_ON(pAd) +#endif /* MESH_SUPPORT */ +#ifdef P2P_SUPPORT + || P2P_GO_ON(pAd) || P2P_CLI_ON(pAd) +#endif /* P2P_SUPPORT */ + ) + && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))) + MlmeDynamicTxRateSwitching(pAd); + } +#endif /* CONFIG_STA_SUPPORT */ + } + +#ifdef DFS_SUPPORT +#ifdef CONFIG_AP_SUPPORT +#endif /* CONFIG_AP_SUPPORT */ +#endif /* DFS_SUPPORT */ + + + + /* Normal 1 second Mlme PeriodicExec.*/ + if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0) + { + pAd->Mlme.OneSecPeriodicRound ++; + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +#ifdef APCLI_CERT_SUPPORT + if (pAd->bApCliCertTest == 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 */ + + + /*ORIBATimerTimeout(pAd);*/ + 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); + +#ifdef DYNAMIC_VGA_SUPPORT + if ((pAd->CommonCfg.MO_Cfg.bDyncVGAEnable) && (pAd->bCalibrationDone)) + { + if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0) + { + UCHAR BbpReg = 0; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &BbpReg); + + DBGPRINT(RT_DEBUG_TRACE, + ("one second False CCA=%d, fixed R66 at 0x%x\n", pAd->RalinkCounters.OneSecFalseCCACnt, BbpReg)); + + if (pAd->RalinkCounters.OneSecFalseCCACnt > pAd->CommonCfg.MO_Cfg.nFalseCCATh) + { + if (BbpReg < (pAd->CommonCfg.MO_Cfg.Stored_BBP_R66 + 0x10)) + { + BbpReg += 4; + AsicBBPWriteWithRxChain(pAd, BBP_R66, BbpReg, RX_CHAIN_ALL); + } + } + else if (pAd->RalinkCounters.OneSecFalseCCACnt < pAd->CommonCfg.MO_Cfg.nLowFalseCCATh) + { + if (BbpReg > pAd->CommonCfg.MO_Cfg.Stored_BBP_R66) + { + BbpReg -= 4; + AsicBBPWriteWithRxChain(pAd, BBP_R66, BbpReg, RX_CHAIN_ALL); + } + } + } + } +#endif /* DYNAMIC_VGA_SUPPORT */ + + + +#ifdef DOT11_N_SUPPORT + /* Need statistics after read counter. So put after NICUpdateRawCounters*/ + ORIBATimerTimeout(pAd); +#endif /* DOT11_N_SUPPORT */ + + /* if MGMT RING is full more than twice within 1 second, we consider there's*/ + /* a hardware problem stucking the TX path. In this case, try a hardware reset*/ + /* to recover the system*/ + /* if (pAd->RalinkCounters.MgmtRingFullCount >= 2)*/ + /* RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HARDWARE_ERROR);*/ + /* 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 VCORECAL_SUPPORT + { + if ((pAd->Mlme.OneSecPeriodicRound % 10) == 0) + 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_AP_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 */ + ) + pAd->macwd ++; + else + pAd->macwd = 0; + + if ((pAd->macwd > 1) && (pAd->bEnableMacWD == TRUE)) + { + 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) + { +#ifdef DOT11Z_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 /* DOT11Z_TDLS_SUPPORT */ + STAMlmePeriodicExec(pAd); + } +#endif /* CONFIG_STA_SUPPORT */ + + + + 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); + { + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC); + } + + DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n")); + } + } + } +#endif /* CONFIG_STA_SUPPORT */ + + RTMP_MLME_HANDLER(pAd); + } + + if (IS_RT6352(pAd) && (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) + { + INT32 TemperatureDiff = 0; + + pAd->CommonCfg.bEnTemperatureTrack = FALSE; + + TemperatureDiff = ((pAd->CurrTemperature - pAd->TemperatureRef25C) * 19) - pAd->DoCalibrationTemperature; + +#ifdef RT6352_EP_SUPPORT + if ((TemperatureDiff >= 400) || (TemperatureDiff <= -400)) + { + RT6352_ReCalibration(pAd); + pAd->DoCalibrationTemperature = (pAd->CurrTemperature - pAd->TemperatureRef25C) * 19; + } +#endif /* RT6352_EP_SUPPORT */ + } + } + else +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + { +#ifdef RTMP_TEMPERATURE_CALIBRATION + UCHAR bbpval; + CHAR BBPR49; + INT32 TemperatureDiff = 0; + + 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; + + TemperatureDiff = ((pAd->CurrTemperature - pAd->TemperatureRef25C) * 19) - pAd->DoCalibrationTemperature; + +#ifdef RT6352_EP_SUPPORT + if ((TemperatureDiff >= 400) || (TemperatureDiff <= -400)) + { + RT6352_ReCalibration(pAd); + pAd->DoCalibrationTemperature = (pAd->CurrTemperature - pAd->TemperatureRef25C) * 19; + } +#endif /* RT6352_EP_SUPPORT */ + } +#endif /* RTMP_TEMPERATURE_CALIBRATION */ + } + } + +#ifdef WSC_INCLUDED + WSC_HDR_BTN_MR_HANDLE(pAd); +#endif /* WSC_INCLUDED */ + + +#ifdef P2P_SUPPORT + if (P2P_INF_ON(pAd)) + P2pPeriodicExec(SystemSpecific1, FunctionContext, SystemSpecific2, SystemSpecific3); +#endif /* P2P_SUPPORT */ + + 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( + IN PUCHAR pSsid, + IN 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( + PRTMP_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.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); + /*MlmeHandler(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); + + 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); + + DBGPRINT_RAW(RT_DEBUG_TRACE,("Write EthCloneMac to ASIC: =%02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->CurrentAddress[0], pAd->CurrentAddress[1], pAd->CurrentAddress[2], + pAd->CurrentAddress[3], pAd->CurrentAddress[4], pAd->CurrentAddress[5])); + + 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 P2P_SUPPORT + if (NdisEqualMemory(ZERO_MAC_ADDR, pAd->P2pCfg.ConnectingMAC, MAC_ADDR_LEN) == FALSE) + { + UCHAR p2pindex; + p2pindex = P2pGroupTabSearch(pAd, pAd->P2pCfg.ConnectingMAC); + if (p2pindex != P2P_NOT_FOUND) + { + if (pAd->P2pTable.Client[p2pindex].P2pClientState > P2PSTATE_DISCOVERY_UNKNOWN) + bCheckBeaconLost = FALSE; + } + } +#endif /* P2P_SUPPORT */ + + 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); + } + + /* + 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; + + +#ifdef P2P_SUPPORT + /* MAC table maintenance */ + if ((pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE == 0) && P2P_GO_ON(pAd)) + { + /* one second timer */ + P2PMacTableMaintenance(pAd); + +#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 */ + } +#endif /* 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 (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.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) && + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2)) + pAd->StaCfg.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);*/ + 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)); + + + /* 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 MESH_SUPPORT + if (MESH_ON(pAd)) + goto SKIP_AUTO_SCAN_CONN; +#endif /* MESH_SUPPORT */ + +#ifdef P2P_SUPPORT + if (P2P_GO_ON(pAd) || P2P_CLI_ON(pAd)) + goto SKIP_AUTO_SCAN_CONN; +#endif /* P2P_SUPPORT */ + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.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_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.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 */ + +#ifdef MESH_SUPPORT + if(MESH_ON(pAd)) + { + LONG idx; + /* period update Neighbor table.*/ + NeighborTableUpdate(pAd); + /* update Mesh Link*/ + MeshLinkTableMaintenace(pAd); + /* update Mesh multipath entry.*/ + for (idx = 0; idx < MAX_MESH_LINKS; idx ++) + { + if (PeerLinkValidCheck(pAd, idx)) + MultipathEntryMaintain(pAd, idx); + } + } +#endif /* MESH_SUPPORT */ + +#ifdef P2P_SUPPORT + if (P2P_CLI_ON(pAd)) + { + if (pAd->Mlme.OneSecPeriodicRound % 2 == 0) + ApCliIfMonitor(pAd); + + if (pAd->Mlme.OneSecPeriodicRound % 2 == 1) + ApCliIfUp(pAd); + + { + INT loop; + ULONG Now32; + NdisGetSystemUpTime(&Now32); + for (loop = 0; loop < MAX_APCLI_NUM; loop++) + { + PAPCLI_STRUCT 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)))) + { + ULONG BPtoJiffies; + LONG timeDiff; + + 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); + } + } + } + } +#endif /* P2P_SUPPORT */ + +#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) + /*&& ((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); + 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.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; + } + } +} + +/* IRQL = DISPATCH_LEVEL*/ +VOID MlmeAutoScan( + IN PRTMP_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); + } +} + +/* IRQL = DISPATCH_LEVEL*/ +VOID MlmeAutoReconnectLastSSID( + IN PRTMP_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", + pAd->MlmeAux.Bssid[0], + pAd->MlmeAux.Bssid[1], + pAd->MlmeAux.Bssid[2], + pAd->MlmeAux.Bssid[3], + pAd->MlmeAux.Bssid[4], + pAd->MlmeAux.Bssid[5])); + + 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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd) +{ + USHORT i; + BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab; + BSS_ENTRY *pBss; + + 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*/ + 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*/ + + 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, ("<== 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( + IN PRTMP_ADAPTER pAd, + IN 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->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); + } + + } +} + +/* IRQL = PASSIVE_LEVEL*/ +/* IRQL = DISPATCH_LEVEL*/ +VOID MlmeSetPsmBit( + IN PRTMP_ADAPTER pAd, + IN USHORT psm) +{ +#ifdef DOT11Z_TDLS_SUPPORT + USHORT PsmOld = pAd->StaCfg.Psm; +#endif /* DOT11Z_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->MatchAPCLITabIdx < MAX_APCLI_NUM)) + LastBeaconRxTime = pAd->ApCfg.ApCliTab[pMacEntry->MatchAPCLITabIdx].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 */ + + +} + + +/* IRQL = DISPATCH_LEVEL*/ +VOID MlmeSetTxPreamble( + IN PRTMP_ADAPTER pAd, + IN USHORT TxPreamble) +{ + AUTO_RSP_CFG_STRUC csr4; + + + /* Always use Long preamble before verifiation short preamble functionality works well.*/ + /* Todo: remove the following line if short preamble functionality works*/ + + /*TxPreamble = Rt802_11PreambleLong;*/ + + RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word); + if (TxPreamble == Rt802_11PreambleLong) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n")); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + csr4.field.AutoResponderPreamble = 0; + } + else + { + /* NOTE: 1Mbps should always use long preamble*/ + DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n")); + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + csr4.field.AutoResponderPreamble = 1; + } + + RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word); +} + +/* + ========================================================================== + Description: + Update basic rate bitmap + ========================================================================== + */ + +VOID UpdateBasicRateBitmap( + IN PRTMP_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 == PHY_11A)*/ + 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; + } /* End of if */ + + if (pAdapter->CommonCfg.BasicRateBitmap > 4095) + { + /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */ + return; + } /* End of if */ + + 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 P2P_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_P2P_GO) + { + UCHAR idx = apidx - MIN_NET_DEVICE_FOR_P2P_GO; + + pHtPhy = &pAd->ApCfg.MBSSID[idx].HTPhyMode; + pMaxHtPhy = &pAd->ApCfg.MBSSID[idx].MaxHTPhyMode; + pMinHtPhy = &pAd->ApCfg.MBSSID[idx].MinHTPhyMode; + + auto_rate_cur_p = &pAd->ApCfg.MBSSID[idx].bAutoTxRateSwitch; + HtMcs = pAd->ApCfg.MBSSID[idx].DesiredTransmitSetting.field.MCS; + break; + } +#endif /* P2P_SUPPORT */ +#ifdef MESH_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_MESH) + { + pHtPhy = &pAd->MeshTab.HTPhyMode; + pMaxHtPhy = &pAd->MeshTab.MaxHTPhyMode; + pMinHtPhy = &pAd->MeshTab.MinHTPhyMode; + + auto_rate_cur_p = &pAd->MeshTab.bAutoTxRateSwitch; + HtMcs = pAd->MeshTab.DesiredTransmitSetting.field.MCS; + break; + } +#endif /* MESH_SUPPORT */ +#ifdef APCLI_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_APCLI) + { + UCHAR idx = apidx - MIN_NET_DEVICE_FOR_APCLI; + + if (idx < MAX_APCLI_NUM) + { + pHtPhy = &pAd->ApCfg.ApCliTab[idx].HTPhyMode; + pMaxHtPhy = &pAd->ApCfg.ApCliTab[idx].MaxHTPhyMode; + pMinHtPhy = &pAd->ApCfg.ApCliTab[idx].MinHTPhyMode; + + auto_rate_cur_p = &pAd->ApCfg.ApCliTab[idx].bAutoTxRateSwitch; + HtMcs = pAd->ApCfg.ApCliTab[idx].DesiredTransmitSetting.field.MCS; + break; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeUpdateTxRates: 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) + { + pHtPhy = &pAd->WdsTab.WdsEntry[idx].HTPhyMode; + pMaxHtPhy = &pAd->WdsTab.WdsEntry[idx].MaxHTPhyMode; + pMinHtPhy = &pAd->WdsTab.WdsEntry[idx].MinHTPhyMode; + + auto_rate_cur_p = &pAd->WdsTab.WdsEntry[idx].bAutoTxRateSwitch; + HtMcs = pAd->WdsTab.WdsEntry[idx].DesiredTransmitSetting.field.MCS; + break; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeUpdateTxRates: invalid apidx(%d)\n", apidx)); + return; + } + } +#endif /* WDS_SUPPORT */ + + if ((apidx < pAd->ApCfg.BssidNum) && + (apidx < MAX_MBSSID_NUM(pAd)) && + (apidx < HW_BEACON_MAX_NUM)) + { + pHtPhy = &pAd->ApCfg.MBSSID[apidx].HTPhyMode; + pMaxHtPhy = &pAd->ApCfg.MBSSID[apidx].MaxHTPhyMode; + pMinHtPhy = &pAd->ApCfg.MBSSID[apidx].MinHTPhyMode; + + auto_rate_cur_p = &pAd->ApCfg.MBSSID[apidx].bAutoTxRateSwitch; + HtMcs = pAd->ApCfg.MBSSID[apidx].DesiredTransmitSetting.field.MCS; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeUpdateTxRates: invalid apidx(%d)\n", apidx)); + } + break; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pHtPhy = &pAd->StaCfg.HTPhyMode; + pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode; + pMinHtPhy = &pAd->StaCfg.MinHTPhyMode; + + auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch; + HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS; + + if ((pAd->StaCfg.BssType == BSS_ADHOC) && + (pAd->CommonCfg.PhyMode == PHY_11B) && + (MaxDesire > RATE_11)) + { + MaxDesire = RATE_11; + } + break; + } +#endif /* CONFIG_STA_SUPPORT */ + } while(FALSE); + + + 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) + { + /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);*/ + /*pAd->CommonCfg.bAutoTxRateSwitch = FALSE;*/ + *auto_rate_cur_p = FALSE; + } + else + { + /*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */ + /*pAd->CommonCfg.bAutoTxRateSwitch = TRUE;*/ + *auto_rate_cur_p = TRUE; + } + + if (HtMcs != MCS_AUTO) + { + /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);*/ + /*pAd->CommonCfg.bAutoTxRateSwitch = FALSE;*/ + *auto_rate_cur_p = FALSE; + } + else + { + /*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */ + /*pAd->CommonCfg.bAutoTxRateSwitch = TRUE;*/ + *auto_rate_cur_p = TRUE; + } + +#ifdef CONFIG_STA_SUPPORT + if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA) +#ifdef P2P_SUPPORT + && (apidx == MIN_NET_DEVICE_FOR_MBSSID) +#endif /* P2P_SUPPORT */ + ) + { + 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,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", 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; + /*pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;*/ + /*pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;*/ + + /* 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 */ +#ifdef P2P_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_APCLI) + pMaxHtPhy->field.MCS = MaxDesire; +#endif /* P2P_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 */ + +#ifdef P2P_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_APCLI) + pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[MaxDesire]; +#endif /* P2P_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 + { + switch (pAd->CommonCfg.PhyMode) + { + case PHY_11BG_MIXED: + case PHY_11B: +#ifdef DOT11_N_SUPPORT + case PHY_11BGN_MIXED: +#endif /* DOT11_N_SUPPORT */ + pAd->CommonCfg.MlmeRate = RATE_1; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; + pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1; + +/*#ifdef WIFI_TEST */ + pAd->CommonCfg.RtsRate = RATE_11; +/*#else*/ +/* pAd->CommonCfg.RtsRate = RATE_1;*/ +/*#endif*/ + break; + case PHY_11G: + case PHY_11A: +#ifdef DOT11_N_SUPPORT + case PHY_11AGN_MIXED: + case PHY_11GN_MIXED: + case PHY_11N_2_4G: + case PHY_11AN_MIXED: + case PHY_11N_5G: +#endif /* DOT11_N_SUPPORT */ + 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]; + break; + case PHY_11ABG_MIXED: +#ifdef DOT11_N_SUPPORT + case PHY_11ABGN_MIXED: +#endif /* DOT11_N_SUPPORT */ + if (pAd->CommonCfg.Channel <= 14) + { + pAd->CommonCfg.MlmeRate = RATE_1; + pAd->CommonCfg.RtsRate = RATE_1; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; + pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1; + } + 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]; + } + break; + default: /* error*/ + pAd->CommonCfg.MlmeRate = RATE_6; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + pAd->CommonCfg.RtsRate = RATE_1; + break; + } + + /* Keep Basic Mlme Rate.*/ + pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word; + if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM) + pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24]; + 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, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n", + 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, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n", + RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap)); + DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n", + 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( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx) +{ + UCHAR StbcMcs; /*j, StbcMcs, bitmask;*/ + CHAR i; /* 3*3*/ + RT_HT_CAPABILITY *pRtHtCap = NULL; + RT_HT_PHY_INFO *pActiveHtPhy = NULL; + ULONG BasicMCS; + UCHAR j, bitmask; + PRT_HT_PHY_INFO pDesireHtPhy = NULL; + PHTTRANSMIT_SETTING pHtPhy = NULL; + PHTTRANSMIT_SETTING pMaxHtPhy = NULL; + PHTTRANSMIT_SETTING pMinHtPhy = NULL; + BOOLEAN *auto_rate_cur_p; + + DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n")); + + auto_rate_cur_p = NULL; + + do + { +#ifdef CONFIG_AP_SUPPORT +#ifdef P2P_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_P2P_GO) + { + UCHAR idx = apidx - MIN_NET_DEVICE_FOR_P2P_GO; + + pDesireHtPhy = &pAd->ApCfg.MBSSID[idx].DesiredHtPhyInfo; + pActiveHtPhy = &pAd->ApCfg.MBSSID[idx].DesiredHtPhyInfo; + pHtPhy = &pAd->ApCfg.MBSSID[idx].HTPhyMode; + pMaxHtPhy = &pAd->ApCfg.MBSSID[idx].MaxHTPhyMode; + pMinHtPhy = &pAd->ApCfg.MBSSID[idx].MinHTPhyMode; + + auto_rate_cur_p = &pAd->ApCfg.MBSSID[idx].bAutoTxRateSwitch; + break; + } +#endif /* P2P_SUPPORT */ +#ifdef MESH_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_MESH) + { + pDesireHtPhy = &pAd->MeshTab.DesiredHtPhyInfo; + pActiveHtPhy = &pAd->MeshTab.DesiredHtPhyInfo; + pHtPhy = &pAd->MeshTab.HTPhyMode; + pMaxHtPhy = &pAd->MeshTab.MaxHTPhyMode; + pMinHtPhy = &pAd->MeshTab.MinHTPhyMode; + + auto_rate_cur_p = &pAd->MeshTab.bAutoTxRateSwitch; + break; + } +#endif /* MESH_SUPPORT */ + +#ifdef APCLI_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_APCLI) + { + UCHAR idx = apidx - MIN_NET_DEVICE_FOR_APCLI; + + if (idx < MAX_APCLI_NUM) + { + pDesireHtPhy = &pAd->ApCfg.ApCliTab[idx].DesiredHtPhyInfo; + pActiveHtPhy = &pAd->ApCfg.ApCliTab[idx].DesiredHtPhyInfo; + pHtPhy = &pAd->ApCfg.ApCliTab[idx].HTPhyMode; + pMaxHtPhy = &pAd->ApCfg.ApCliTab[idx].MaxHTPhyMode; + pMinHtPhy = &pAd->ApCfg.ApCliTab[idx].MinHTPhyMode; + + auto_rate_cur_p = &pAd->ApCfg.ApCliTab[idx].bAutoTxRateSwitch; + break; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeUpdateHtTxRates: 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) + { + pDesireHtPhy = &pAd->WdsTab.WdsEntry[idx].DesiredHtPhyInfo; + pActiveHtPhy = &pAd->WdsTab.WdsEntry[idx].DesiredHtPhyInfo; + pHtPhy = &pAd->WdsTab.WdsEntry[idx].HTPhyMode; + pMaxHtPhy = &pAd->WdsTab.WdsEntry[idx].MaxHTPhyMode; + pMinHtPhy = &pAd->WdsTab.WdsEntry[idx].MinHTPhyMode; + + auto_rate_cur_p = &pAd->WdsTab.WdsEntry[idx].bAutoTxRateSwitch; + break; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeUpdateHtTxRates: invalid apidx(%d)\n", apidx)); + return; + } + } +#endif /* WDS_SUPPORT */ + + if ((apidx < pAd->ApCfg.BssidNum) && (apidx < HW_BEACON_MAX_NUM)) + { + pDesireHtPhy = &pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo; + pActiveHtPhy = &pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo; + pHtPhy = &pAd->ApCfg.MBSSID[apidx].HTPhyMode; + pMaxHtPhy = &pAd->ApCfg.MBSSID[apidx].MaxHTPhyMode; + pMinHtPhy = &pAd->ApCfg.MBSSID[apidx].MinHTPhyMode; + + auto_rate_cur_p = &pAd->ApCfg.MBSSID[apidx].bAutoTxRateSwitch; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeUpdateHtTxRates: invalid apidx(%d)\n", apidx)); + } + break; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo; + pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo; + pHtPhy = &pAd->StaCfg.HTPhyMode; + pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode; + pMinHtPhy = &pAd->StaCfg.MinHTPhyMode; + + auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch; + break; + } +#endif /* CONFIG_STA_SUPPORT */ + } while (FALSE); + + +#ifdef CONFIG_STA_SUPPORT + if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA) +#ifdef P2P_SUPPORT + && (apidx == BSS0) +#endif /* P2P_SUPPORT */ + ) + { + 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; + } + + for (i=23; i>=0; i--) /* 3*3*/ + { + j = i/8; + bitmask = (1<<(i-(j*8))); + + if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask)) + { + pMaxHtPhy->field.MCS = i; + break; + } + + if (i==0) + break; + } + + /* 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) +#ifdef P2P_SUPPORT + && (apidx == BSS0) +#endif /* P2P_SUPPORT */ + ) + { + if (pDesireHtPhy->MCSSet[4] != 0) + { + pMaxHtPhy->field.MCS = 32; + pMinHtPhy->field.MCS = 32; + DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS)); + } + + for (i=23; (CHAR)i >= 0; i--) /* 3*3*/ + { + 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, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", 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,("MlmeUpdateHtTxRates<=== \n")); +} + + +VOID BATableInit( + IN PRTMP_ADAPTER pAd, + IN 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( + IN RTMP_ADAPTER *pAd) +{ + int i; + + for(i=0; iBATable.BARecEntry[i].RxReRingLock); + } + NdisFreeSpinLock(&pAd->BATabLock); +} +#endif /* DOT11_N_SUPPORT */ + +/* IRQL = DISPATCH_LEVEL*/ +VOID MlmeRadioOff( + IN PRTMP_ADAPTER pAd) +{ + RTMP_MLME_RADIO_OFF(pAd); +} + +/* IRQL = DISPATCH_LEVEL*/ +VOID MlmeRadioOn( + IN PRTMP_ADAPTER pAd) +{ + RTMP_MLME_RADIO_ON(pAd); +} + +/* +=========================================================================================== + bss_table.c +=========================================================================================== +*/ + + +/*! \brief initialize BSS table + * \param p_tab pointer to the table + * \return none + * \pre + * \post + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + */ +VOID BssTableInit( + IN 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( + IN BSS_TABLE *Tab, + IN PUCHAR pBssid, + 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)) + { + return i; + } + } + return (ULONG)BSS_NOT_FOUND; +} + +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( + IN BSS_TABLE *Tab, + IN PUCHAR pSsid, + IN 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; +} + + +/* IRQL = DISPATCH_LEVEL*/ +VOID BssTableDeleteEntry( + IN OUT BSS_TABLE *Tab, + IN PUCHAR pBssid, + IN 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 + + IRQL = DISPATCH_LEVEL + + */ +VOID BssEntrySet( + IN PRTMP_ADAPTER pAd, + OUT BSS_ENTRY *pBss, + IN PUCHAR pBssid, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR BssType, + IN USHORT BeaconPeriod, + IN PCF_PARM pCfParm, + IN USHORT AtimWin, + IN USHORT CapabilityInfo, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN HT_CAPABILITY_IE *pHtCapability, + IN ADD_HT_INFO_IE *pAddHtInfo, /* AP might use this additional ht info IE */ + IN UCHAR HtCapabilityLen, + IN UCHAR AddHtInfoLen, + IN UCHAR NewExtChanOffset, + IN UCHAR Channel, + IN CHAR Rssi, + IN LARGE_INTEGER TimeStamp, + IN UCHAR CkipFlag, + IN PEDCA_PARM pEdcaParm, + IN PQOS_CAPABILITY_PARM pQosCapability, + IN PQBSS_LOAD_PARM pQbssLoad, + IN USHORT LengthVIE, + IN PNDIS_802_11_VARIABLE_IEs pVIE) +{ + COPY_MAC_ADDR(pBss->Bssid, pBssid); + /* Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID*/ + pBss->Hidden = 1; + 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) + { + NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pBss->Ssid, Ssid, SsidLen); + pBss->SsidLen = 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 = BssType; + pBss->BeaconPeriod = BeaconPeriod; + if (BssType == BSS_INFRA) + { + if (pCfParm->bValid) + { + pBss->CfpCount = pCfParm->CfpCount; + pBss->CfpPeriod = pCfParm->CfpPeriod; + pBss->CfpMaxDuration = pCfParm->CfpMaxDuration; + pBss->CfpDurRemaining = pCfParm->CfpDurRemaining; + } + } + else + { + pBss->AtimWin = AtimWin; + } + + NdisGetSystemUpTime(&pBss->LastBeaconRxTime); + pBss->CapabilityInfo = 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(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES); + if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES) + NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen); + else + NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES); + pBss->SupRateLen = SupRateLen; + ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES); + if (ExtRateLen > MAX_LEN_OF_SUPPORTED_RATES) + ExtRateLen = MAX_LEN_OF_SUPPORTED_RATES; + NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen); + pBss->NewExtChanOffset = NewExtChanOffset; + pBss->ExtRateLen = ExtRateLen; + pBss->Channel = Channel; + pBss->CentralChannel = Channel; + pBss->Rssi = Rssi; + /* Update CkipFlag. if not exists, the value is 0x0*/ + pBss->CkipFlag = CkipFlag; + + /* New for microsoft Fixed IEs*/ + NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8); + pBss->FixIEs.BeaconInterval = BeaconPeriod; + pBss->FixIEs.Capabilities = CapabilityInfo; + + /* 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 DOT11_N_SUPPORT + if (HtCapabilityLen> 0) + { + pBss->HtCapabilityLen = HtCapabilityLen; + NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen); + if (AddHtInfoLen > 0) + { + pBss->AddHtInfoLen = AddHtInfoLen; + NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen); + + if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40)) + { + pBss->CentralChannel = pAddHtInfo->ControlChan - 2; + } + else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40)) + { + pBss->CentralChannel = pAddHtInfo->ControlChan + 2; + } + } + } +#endif /* DOT11_N_SUPPORT */ + + BssCipherParse(pBss); + + /* new for QOS*/ + if (pEdcaParm) + NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM)); + else + pBss->EdcaParm.bValid = FALSE; + if (pQosCapability) + NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM)); + else + pBss->QosCapability.bValid = FALSE; + if (pQbssLoad) + NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, 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 */ + pEid = (PEID_STRUCT) pVIE; + while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE) + { +#define WPS_AP 0x01 + switch(pEid->Eid) + { + case IE_WPA: +#ifdef WAC_SUPPORT +#define WAC_AP 0x04 + if (NdisEqualMemory(pEid->Octet, SAMSUNG_OUI, 3)) + { +#define WAC_DEVICE_ADVERTISE_ID 0x00 +#define WAC_DEVICE_INFORMATION_ID 0x03 + UCHAR oui_type = 0; + BOOLEAN bWAC_Enable = FALSE; + CHAR device_info[5]; + + oui_type = pEid->Octet[3]; + DBGPRINT(RT_DEBUG_WARN, ("%s: Samsung OUI Type = 0x%02X\n", __FUNCTION__, oui_type)); + if (oui_type == SAMSUNG_OUI_TYPE) + { + WAC_ParseAttr(WAC_DEVICE_ADVERTISE_ID, pEid->Octet+4, pEid->Len-4, &bWAC_Enable, 1); + if (bWAC_Enable) + pBss->WpsAP |= WAC_AP; + } +#ifdef WAC_QOS_PRIORITY + pBss->DeviceType = 0xFF; + pBss->bForcePriority = FALSE; + if (WAC_ParseAttr(WAC_DEVICE_INFORMATION_ID, pEid->Octet+4, pEid->Len-4, &device_info[0], 5)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: WAC Device Information: %d, %d, %d, %d, %d\n", __FUNCTION__, device_info[0], device_info[1], device_info[2], device_info[3], device_info[4])); + pBss->DeviceType = (CHAR) device_info[3]; + } + + if (bWAC_Enable) + { + pBss->bForcePriority = TRUE; + } +#endif /* WAC_QOS_PRIORITY */ + } +#endif /* WAC_SUPPORT */ + 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 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 */ + } + 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 PUCHAR pBssid, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR BssType, + IN USHORT BeaconPeriod, + IN CF_PARM *CfParm, + IN USHORT AtimWin, + IN USHORT CapabilityInfo, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN HT_CAPABILITY_IE *pHtCapability, + IN ADD_HT_INFO_IE *pAddHtInfo, /* AP might use this additional ht info IE */ + IN UCHAR HtCapabilityLen, + IN UCHAR AddHtInfoLen, + IN UCHAR NewExtChanOffset, + IN UCHAR ChannelNo, + IN CHAR Rssi, + IN LARGE_INTEGER TimeStamp, + IN UCHAR CkipFlag, + IN PEDCA_PARM pEdcaParm, + IN PQOS_CAPABILITY_PARM pQosCapability, + IN PQBSS_LOAD_PARM pQbssLoad, + IN USHORT LengthVIE, + IN PNDIS_802_11_VARIABLE_IEs pVIE) +{ + ULONG Idx; +#ifdef APCLI_SUPPORT + BOOLEAN bInsert = FALSE; + PAPCLI_STRUCT pApCliEntry = NULL; + UCHAR i; +#endif /* APCLI_SUPPORT */ + + /*Idx = BssTableSearchWithSSID(Tab, pBssid, (UCHAR *)Ssid, SsidLen, ChannelNo);*/ + Idx = BssTableSearch(Tab, pBssid, ChannelNo); + 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 < MAX_APCLI_NUM; i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + if (MAC_ADDR_EQUAL(pApCliEntry->ApCliMlmeAux.Bssid, pBssid) + || SSID_EQUAL(pApCliEntry->ApCliMlmeAux.Ssid, pApCliEntry->ApCliMlmeAux.SsidLen, Ssid, 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, pBssid) || + SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen) +#ifdef APCLI_SUPPORT + || bInsert +#endif /* APCLI_SUPPORT */ + ) + { + Idx = Tab->BssOverlapNr; + NdisZeroMemory(&(Tab->BssEntry[Idx]), sizeof(BSS_ENTRY)); + BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin, + CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen, + NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE); + Tab->BssOverlapNr = Tab->BssOverlapNr + 1; + Tab->BssOverlapNr = Tab->BssOverlapNr % MAX_LEN_OF_BSS_TABLE; + } + return Idx; + } + else + { + return BSS_NOT_FOUND; + } + } + Idx = Tab->BssNr; + BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin, + CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen, + NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE); + Tab->BssNr++; + } + else + { + BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin, + CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen, + NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE); + } + + return Idx; +} + +#if defined(CONFIG_STA_SUPPORT) || defined(APCLI_SUPPORT) +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 +VOID TriEventInit( + IN PRTMP_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 PRTMP_ADAPTER pAd, + OUT TRIGGER_EVENT_TAB *Tab, + IN PUCHAR 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 ++; + } + } + else if (pHtCapability->HtCapInfo.Forty_Mhz_Intolerant) + { + /* Event B. My BSS beacon has Intolerant40 bit set*/ + Tab->EventBCountDown = pAd->CommonCfg.Dot11BssWidthChanTranDelay; + } + + return 0; +} +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ +#endif /* defined(CONFIG_STA_SUPPORT) || defined(APCLI_SUPPORT) */ + +#ifdef CONFIG_STA_SUPPORT +/* IRQL = DISPATCH_LEVEL*/ +VOID BssTableSsidSort( + IN PRTMP_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 */ + 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.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) && + ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) + { + 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 == PHY_11GN_MIXED) && + ((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 (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + { + /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode*/ + if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux)) + /* None matched*/ + continue; + + /* Check cipher suite, AP must have more secured cipher than station setting*/ + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.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 (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher) + continue; + + /* check group cipher*/ + if ((pAd->StaCfg.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 ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && + (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) && + (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux)) + continue; + } + else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.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 (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher) + continue; + + /* check group cipher*/ + if ((pAd->StaCfg.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 ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && + (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) && + (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux)) + continue; + } +#ifdef WAPI_SUPPORT + else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWAICERT) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWAIPSK)) + { + /* check cipher algorithm*/ + if ((pAd->StaCfg.WepStatus != pInBss->WAPI.GroupCipher) || + (pAd->StaCfg.WepStatus != pInBss->WAPI.PairCipher)) + continue; + } +#endif /* WAPI_SUPPORT */ + } + /* Bss Type matched, SSID matched. */ + /* We will check wepstatus for qualification Bss*/ + else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) + { + DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.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) && + ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) + { + 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 == PHY_11GN_MIXED) && + ((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 (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + { + /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode*/ + if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux)) + /* None matched*/ + continue; + + /* Check cipher suite, AP must have more secured cipher than station setting*/ + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.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 (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher) + continue; + + /* check group cipher*/ + if (pAd->StaCfg.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 ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && + (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) && + (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux)) + continue; + } + else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.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 (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher) + continue; + + /* check group cipher*/ + if (pAd->StaCfg.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 ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && + (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) && + (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux)) + continue; + } +#ifdef WAPI_SUPPORT + else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWAICERT) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWAIPSK)) + { + /* check cipher algorithm*/ + if ((pAd->StaCfg.WepStatus != pInBss->WAPI.GroupCipher) || + (pAd->StaCfg.WepStatus != pInBss->WAPI.PairCipher)) + continue; + } +#endif /* WAPI_SUPPORT */ + } + /* Bss Type matched, SSID matched. */ + /* We will check wepstatus for qualification Bss*/ + else if (pAd->StaCfg.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) */ + + +/* IRQL = DISPATCH_LEVEL*/ +VOID BssTableSortByRssi( + IN OUT BSS_TABLE *OutTab, + IN BOOLEAN isInverseOrder) +{ + INT i, j; +/* BSS_ENTRY TmpBss;*/ + 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( + IN OUT PBSS_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; + + /* 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_11Encryption2Enabled; + break; + case 4: + pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled; + 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_11Encryption1Enabled; + break; + case 2: + TmpCipher = Ndis802_11Encryption2Enabled; + break; + case 4: + TmpCipher = Ndis802_11Encryption3Enabled; + 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_11Encryption2Enabled; + break; + case 4: + pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled; + 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_11Encryption1Enabled; + break; + case 2: + TmpCipher = Ndis802_11Encryption2Enabled; + break; + case 4: + TmpCipher = Ndis802_11Encryption3Enabled; + 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: + /* Set AP support WPA-enterprise mode*/ + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeWPA2; + else + pBss->AuthModeAux = Ndis802_11AuthModeWPA2; + break; + case 2: + /* Set AP support WPA-PSK mode*/ + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeWPA2PSK; + else + pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK; + + + 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); + } +} + +/* ===========================================================================================*/ +/* mac_table.c*/ +/* ===========================================================================================*/ + +/*! \brief generates a random mac address value for IBSS BSSID + * \param Addr the bssid location + * \return none + * \pre + * \post + */ +VOID MacAddrRandomBssid( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR 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 + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + */ +VOID MgtMacHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN PUCHAR pDA, +#ifdef P2P_SUPPORT + IN PUCHAR pSA, +#endif /* P2P_SUPPORT */ + IN PUCHAR pBssid) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + + pHdr80211->FC.Type = BTYPE_MGMT; + pHdr80211->FC.SubType = SubType; +/* if (SubType == SUBTYPE_ACK) sample, no use, it will conflict with ACTION frame sub type*/ +/* pHdr80211->FC.Type = BTYPE_CNTL;*/ + pHdr80211->FC.ToDs = ToDs; + COPY_MAC_ADDR(pHdr80211->Addr1, pDA); +#ifdef 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 PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN PUCHAR pAddr1, + IN PUCHAR pAddr2, + IN PUCHAR pAddr3) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + + pHdr80211->FC.Type = BTYPE_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); +} + + +/* ===========================================================================================*/ +/* mem_mgmt.c*/ +/* ===========================================================================================*/ + +/*!*************************************************************************** + * 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( + OUT UCHAR *Buffer, + OUT 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; +} + +/* ===========================================================================================*/ +/* mlme_queue.c*/ +/* ===========================================================================================*/ + +/*! \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 PRTMP_ADAPTER pAd, + IN MLME_QUEUE *Queue) +{ + INT i; + + NdisAllocateSpinLock(pAd, &Queue->Lock); + + Queue->Num = 0; + Queue->Head = 0; + Queue->Tail = 0; + + 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); + } + + 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 + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + */ +BOOLEAN MlmeEnqueue( + IN PRTMP_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; + 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; +} + +/*! \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 + + IRQL = DISPATCH_LEVEL + + */ +BOOLEAN MlmeEnqueueForRecv( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN ULONG TimeStampHigh, + IN ULONG TimeStampLow, + IN UCHAR Rssi0, + IN UCHAR Rssi1, + IN UCHAR Rssi2, + 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; + 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(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n")); + return FALSE; + } + + /* First check the size, it MUST not exceed the mlme queue size*/ + if (MsgLen > MGMT_DMA_BUFFER_SIZE) + { + DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen)); + return FALSE; + } + + if (MlmeQueueFull(Queue, 0)) + { + return FALSE; + } + +#ifdef CONFIG_AP_SUPPORT +#ifdef P2P_SUPPORT + if (OpMode == OPMODE_AP) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { +#ifdef P2P_SUPPORT + if (P2P_CLI_ON(pAd)) + { + if (pFrame->Hdr.FC.SubType == SUBTYPE_PROBE_REQ) + return FALSE; + } +#endif /* 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 < MAX_APCLI_NUM; i++) + { + if (MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[i].ApCliMlmeAux.Bssid, pFrame->Hdr.Addr2)) + { + bToApCli = TRUE; + ApCliIdx = i; + break; + } + } + + if (!MAC_ADDR_EQUAL(pFrame->Hdr.Addr1, pAd->CurrentAddress) && +#ifdef P2P_SUPPORT + !P2P_GO_ON(pAd) && +#endif /* P2P_SUPPORT */ + 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(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d, STA-%02x:%02x:%02x:%02x:%02x:%02x\n", + pFrame->Hdr.FC.SubType, pFrame->Hdr.Addr2[0], pFrame->Hdr.Addr2[1], pFrame->Hdr.Addr2[2], + pFrame->Hdr.Addr2[3], pFrame->Hdr.Addr2[4], pFrame->Hdr.Addr2[5])); + return FALSE; + + } while (FALSE); +#else + if (!APMsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) + { + DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType)); + return FALSE; + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT +#ifdef 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(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType)); + return FALSE; + } + } +#endif /* CONFIG_STA_SUPPORT */ + + /* OK, we got all the informations, it is time to put things into queue*/ + + NdisAcquireSpinLock(&(Queue->Lock)); + Tail = Queue->Tail; + 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; + Queue->Entry[Tail].Signal = Signal; + Queue->Entry[Tail].Wcid = (UCHAR)Wcid; + Queue->Entry[Tail].OpMode = (ULONG)OpMode; + 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 */ + + Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel; + + 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 PRTMP_ADAPTER pAd, + IN ULONG eventID, + IN LONG senderID, + IN ULONG Machine, + IN ULONG MsgType, + IN ULONG MsgLen, + IN VOID *Msg) +{ + INT Tail; + /*ULONG IrqFlags;*/ + 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; + 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 + + IRQL = DISPATCH_LEVEL + + */ +BOOLEAN MlmeDequeue( + IN 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_MLME_QUEUE) + { + Queue->Head = 0; + } + NdisReleaseSpinLock(&(Queue->Lock)); + return TRUE; +} + +/* IRQL = DISPATCH_LEVEL*/ +VOID MlmeRestartStateMachine( + IN PRTMP_ADAPTER pAd) +{ +#ifdef RTMP_MAC_PCI + MLME_QUEUE_ELEM *Elem = NULL; +#endif /* RTMP_MAC_PCI */ +#ifdef CONFIG_STA_SUPPORT + BOOLEAN Cancelled; +#ifdef P2P_SUPPORT + PAPCLI_STRUCT pApCliEntry = NULL; +#endif /* P2P_SUPPORT */ +#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); + + /* 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*/ +#ifdef P2P_SUPPORT + pApCliEntry = &pAd->ApCfg.ApCliTab[BSS0]; + + if (!P2P_GO_ON(pAd) && (pApCliEntry->Valid == FALSE)) +#endif /* P2P_SUPPORT */ + { + 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( + IN MLME_QUEUE *Queue) +{ + BOOLEAN Ans; + + NdisAcquireSpinLock(&(Queue->Lock)); + Ans = (Queue->Num == 0); + NdisReleaseSpinLock(&(Queue->Lock)); + + return Ans; +} + +/*! \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( + IN MLME_QUEUE *Queue, + IN 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); + NdisReleaseSpinLock(&(Queue->Lock)); + + return Ans; +} + +/*! \brief The destructor of MLME Queue + * \param + * \return + * \pre + * \post + * \note Clear Mlme Queue, Set Queue->Num to Zero. + + IRQL = PASSIVE_LEVEL + + */ +VOID MlmeQueueDestroy( + IN MLME_QUEUE *pQueue) +{ + NdisAcquireSpinLock(&(pQueue->Lock)); + pQueue->Num = 0; + pQueue->Head = 0; + pQueue->Tail = 0; + NdisReleaseSpinLock(&(pQueue->Lock)); + NdisFreeSpinLock(&(pQueue->Lock)); +} + + +/*! \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( + IN PRTMP_ADAPTER pAd, + IN PFRAME_802_11 pFrame, + OUT INT *Machine, + OUT 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 == BTYPE_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) + { + 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; + /* 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 */ + +/* ===========================================================================================*/ +/* state_machine.c*/ +/* ===========================================================================================*/ + +/*! \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 + + IRQL = DISPATCH_LEVEL + + */ +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( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +UCHAR RandomByte( + IN PRTMP_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( + IN PRTMP_ADAPTER pAd) +{ + UINT32 a,b; + UCHAR value, value1 = 0, value2 = 0, value3 = 0, value4 = 0, value5 = 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; + + /*R50~R54: RSSI or SNR related*/ + 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 value^value1^value2^value3^value4^value5^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( + IN PRTMP_ADAPTER pAd, + IN OUT UCHAR SupRate[], + IN OUT UCHAR *SupRateLen) +{ + UCHAR RateIdx, i, j; + UCHAR NewRate[12], NewRateLen; + + NewRateLen = 0; + + if (pAd->CommonCfg.PhyMode == PHY_11B) + 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( + IN PRTMP_ADAPTER pAd, + IN UCHAR CentralChannel, + IN UCHAR Channel) +{ + UCHAR k; + UCHAR UpperChannel = 0, LowerChannel = 0; + UCHAR NoEffectChannelinList = 0; + + /* Find upper and lower channel according to 40MHz current operation. */ + if (CentralChannel < Channel) + { + UpperChannel = Channel; + if (CentralChannel > 2) + LowerChannel = CentralChannel - 2; + else + return FALSE; + } + else if (CentralChannel > Channel) + { + UpperChannel = CentralChannel + 2; + LowerChannel = Channel; + } + + 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 PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN HT_CAPABILITY_IE *pHtCapability, + IN ADD_HT_INFO_IE *pAddHtInfo) +{ + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + return FALSE; + + /* If use AMSDU, set flag.*/ + if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable) + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED); + /* Save Peer Capability*/ + if (pHtCapability->HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE); + if (pHtCapability->HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE); + if (pHtCapability->HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE); + if (pHtCapability->HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE); + if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) + { + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE); + } + + if (Wcid < MAX_LEN_OF_MAC_TABLE) + { + pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity; + } + + /* Will check ChannelWidth for MCSSet[4] below*/ + pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00; + pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1; + switch (pAd->CommonCfg.RxStream) + { + case 1: + pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00; + pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00; + pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; + break; + case 2: + pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00; + pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; + break; + case 3: + pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; + 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 = pHtCapability->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) & (pHtCapability->HtCapInfo.ShortGIfor20); + pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40); + pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC); + pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC); + pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor; + pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity; + pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC; + pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC; + if (pAd->CommonCfg.bRdg) + { + pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->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*/ + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + setETxBFCap(pAd, &pAd->MlmeAux.HtCapability.TxBFCap); +#endif /* TXBF_SUPPORT */ + + COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability); + return TRUE; +} +#endif /* DOT11_N_SUPPORT */ +#endif /* CONFIG_STA_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( + IN PRTMP_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 PHY_11B: + ProperMlmeRate = RATE_11; + MinimumRate = RATE_1; + break; + case PHY_11BG_MIXED: +#ifdef DOT11_N_SUPPORT + case PHY_11ABGN_MIXED: + case PHY_11BGN_MIXED: +#endif /* DOT11_N_SUPPORT */ + if ((pAd->MlmeAux.SupRateLen == 4) && + (pAd->MlmeAux.ExtRateLen == 0)) + /* B only AP*/ + ProperMlmeRate = RATE_11; + else + ProperMlmeRate = RATE_24; + + if (pAd->MlmeAux.Channel <= 14) + MinimumRate = RATE_1; + else + MinimumRate = RATE_6; + break; + case PHY_11A: +#ifdef DOT11_N_SUPPORT + case PHY_11N_2_4G: /* rt2860 need to check mlmerate for 802.11n*/ + case PHY_11GN_MIXED: + case PHY_11AGN_MIXED: + case PHY_11AN_MIXED: + case PHY_11N_5G: +#endif /* DOT11_N_SUPPORT */ + ProperMlmeRate = RATE_24; + MinimumRate = RATE_6; + break; + case PHY_11ABG_MIXED: + ProperMlmeRate = RATE_24; + if (pAd->MlmeAux.Channel <= 14) + MinimumRate = RATE_1; + else + MinimumRate = RATE_6; + break; + default: /* error*/ + ProperMlmeRate = RATE_1; + MinimumRate = RATE_1; + break; + } + + 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, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word)); +} + + +CHAR RTMPAvgRssi( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi0, + IN CHAR Rssi1, + IN 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( + IN PRTMP_ADAPTER pAd, + IN CHAR Snr0, + IN 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: + 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( + IN PRTMP_ADAPTER pAd, + INOUT PUCHAR pRefFreqOffset) +{ + BOOLEAN RetVal = TRUE; +#ifdef RTMP_RW_RF_SUPPORT + 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; +#else + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Error in tuning frequency offset !!\n", __FUNCTION__)); +#endif + + return RetVal; + +} + +/* + ======================================================================== + Routine Description: + Periodic evaluate antenna link status + + Arguments: + pAd - Adapter pointer + + Return Value: + None + + ======================================================================== +*/ +VOID AsicEvaluateRxAnt( + IN PRTMP_ADAPTER pAd) +{ +#ifdef CONFIG_STA_SUPPORT + UCHAR BBPR3 = 0; +#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 | + 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; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); + BBPR3 &= (~0x18); + if(pAd->Antenna.field.RxPath == 3) + { + BBPR3 |= (0x10); + } + else if(pAd->Antenna.field.RxPath == 2) + { + BBPR3 |= (0x8); + } + else if(pAd->Antenna.field.RxPath == 1) + { + BBPR3 |= (0x0); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); +#ifdef RTMP_MAC_PCI + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pAd->StaCfg.BBPR3 = BBPR3; +#endif /* RTMP_MAC_PCI */ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) +#ifdef MESH_SUPPORT + || MESH_ON(pAd) +#endif /* MESH_SUPPORT */ +#ifdef P2P_SUPPORT + || P2P_GO_ON(pAd) || P2P_CLI_ON(pAd) +#endif /* P2P_SUPPORT */ + ) + { + 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 + UCHAR BBPR3 = 0; + 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; + } + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); + BBPR3 &= (~0x18); + if(pAd->Mlme.RealRxPath == 3) + { + BBPR3 |= (0x10); + } + else if(pAd->Mlme.RealRxPath == 2) + { + BBPR3 |= (0x8); + } + else if(pAd->Mlme.RealRxPath == 1) + { + BBPR3 |= (0x0); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); +#ifdef RTMP_MAC_PCI + pAd->StaCfg.BBPR3 = BBPR3; +#endif /* RTMP_MAC_PCI */ + } +#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; + }*/ +} + +/* + ======================================================================== + Routine Description: + Set/reset MAC registers according to bPiggyBack parameter + + Arguments: + pAd - Adapter pointer + bPiggyBack - Enable / Disable Piggy-Back + + Return Value: + None + + ======================================================================== +*/ +VOID RTMPSetPiggyBack( + IN PRTMP_ADAPTER pAd, + IN 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); +} + +/* + ======================================================================== + Routine Description: + check if this entry need to switch rate automatically + + Arguments: + pAd + pEntry + + Return Value: + TURE + FALSE + + ======================================================================== +*/ +BOOLEAN RTMPCheckEntryEnableAutoRateSwitch( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry) +{ + BOOLEAN result = TRUE; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + if (pEntry) + { + if (IS_ENTRY_CLIENT(pEntry)) + result = pAd->ApCfg.MBSSID[pEntry->apidx].bAutoTxRateSwitch; +#ifdef WDS_SUPPORT + else if (IS_ENTRY_WDS(pEntry)) + result = pAd->WdsTab.WdsEntry[pEntry->MatchWDSTabIdx].bAutoTxRateSwitch; +#endif /* WDS_SUPPORT */ +#ifdef APCLI_SUPPORT + else if (IS_ENTRY_APCLI(pEntry)) + result = pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].bAutoTxRateSwitch; +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* only associated STA counts*/ +#ifdef P2P_SUPPORT + if (pEntry && IS_P2P_GO_ENTRY(pEntry)) + result = pAd->ApCfg.MBSSID[pEntry->apidx].bAutoTxRateSwitch; + else if (pEntry && IS_ENTRY_APCLI(pEntry)) + result = pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].bAutoTxRateSwitch; + else +#endif /* P2P_SUPPORT */ + if ((pEntry && IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) +#ifdef QOS_DLS_SUPPORT + || (pEntry && IS_ENTRY_DLS(pEntry)) +#endif /* QOS_DLS_SUPPORT */ +#ifdef DOT11Z_TDLS_SUPPORT + || (pEntry && IS_ENTRY_TDLS(pEntry)) +#endif /* DOT11Z_TDLS_SUPPORT */ + ) + { + result = pAd->StaCfg.bAutoTxRateSwitch; + } + else + result = FALSE; + } +#endif /* CONFIG_STA_SUPPORT */ + + +#ifdef MESH_SUPPORT + if ((pEntry != NULL) && IS_ENTRY_MESH(pEntry)) + result = pAd->MeshTab.bAutoTxRateSwitch; +#endif /* MESH_SUPPORT */ + + return result; +} + + +BOOLEAN RTMPAutoRateSwitchCheck( + IN PRTMP_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].bAutoTxRateSwitch) + return TRUE; + } +#ifdef WDS_SUPPORT + for (apidx = 0; apidx < MAX_WDS_ENTRY; apidx++) + { + if (pAd->WdsTab.WdsEntry[apidx].bAutoTxRateSwitch) + return TRUE; + } +#endif /* WDS_SUPPORT */ +#ifdef APCLI_SUPPORT + for (apidx = 0; apidx < MAX_APCLI_NUM; apidx++) + { + if (pAd->ApCfg.ApCliTab[apidx].bAutoTxRateSwitch) + return TRUE; + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pAd->StaCfg.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( + IN PRTMP_ADAPTER pAd, + IN PMAC_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].DesiredTransmitSetting.field.FixedTxMode; +#ifdef WDS_SUPPORT + else if (IS_ENTRY_WDS(pEntry)) + tx_mode = (UCHAR)pAd->WdsTab.WdsEntry[pEntry->MatchWDSTabIdx].DesiredTransmitSetting.field.FixedTxMode; +#endif /* WDS_SUPPORT */ +#ifdef APCLI_SUPPORT + else if (IS_ENTRY_APCLI(pEntry)) + tx_mode = (UCHAR)pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].DesiredTransmitSetting.field.FixedTxMode; +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef P2P_SUPPORT + if (IS_P2P_GO_ENTRY(pEntry)) + tx_mode = (UCHAR)pAd->ApCfg.MBSSID[pEntry->apidx].DesiredTransmitSetting.field.FixedTxMode; + else if (IS_ENTRY_APCLI(pEntry)) + tx_mode = (UCHAR)pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].DesiredTransmitSetting.field.FixedTxMode; + else +#endif /* P2P_SUPPORT */ + tx_mode = (UCHAR)pAd->StaCfg.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, + PMAC_TABLE_ENTRY pEntry) +{ + HTTRANSMIT_SETTING TransmitSetting; + + if (fixed_tx_mode == FIXED_TXMODE_HT) + return; + + TransmitSetting.word = 0; + + TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE; + TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS; + + 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->Aid, GetPhyMode(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( + IN PRTMP_ADAPTER pAd) +{ + UCHAR OrigR66Value = 0, R66;/*, R66UpperBound = 0x30, R66LowerBound = 0x30;*/ + CHAR Rssi; +#ifdef RT2883 + UCHAR byteValue = 0; +#endif /* RT2883 */ + + /* 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) +#ifdef MESH_SUPPORT + || MESH_ON(pAd) +#endif /* MESH_SUPPORT */ + ) + && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) +#ifdef RTMP_MAC_PCI + && (pAd->bPCIclkOff == FALSE) +#endif /* RTMP_MAC_PCI */ + ) + { + AsicBBPReadWithRxChain(pAd, BBP_R66, &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( + IN PRTMP_ADAPTER pAd, + IN UCHAR BandWidth) +{ + RTMP_CHIP_ASIC_AGC_INIT(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( + IN PRTMP_ADAPTER pAd, + IN UINT32 ChanNum, + IN 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; /* same property */ + /* End of if */ + + break; + } /* End of if */ + } /* End of for */ + + return FALSE; +} + + + + +/* End of mlme.c */ + diff --git a/mt7620/src/common/netif_block.c b/mt7620/src/common/netif_block.c new file mode 100644 index 0000000..e8c0010 --- /dev/null +++ b/mt7620/src/common/netif_block.c @@ -0,0 +1,140 @@ +#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; + UCHAR IfIdx = 0; + BOOLEAN valid = FALSE; + + +#ifdef P2P_SUPPORT + if (RTMP_GET_PACKET_NET_DEVICE(pPacket) >= MIN_NET_DEVICE_FOR_P2P_GO) + { + IfIdx = (RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_P2P_GO) % MAX_P2P_NUM; + NetDev = pAd->ApCfg.MBSSID[IfIdx].MSSIDDev; + } + else +#endif /* P2P_SUPPORT */ +#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].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].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].MSSIDDev; + } + 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].bWmmCapable == TRUE) ? FALSE : TRUE; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + { +#ifdef P2P_SUPPORT + if (RTMP_GET_PACKET_NET_DEVICE(pPacket) >= MIN_NET_DEVICE_FOR_P2P_GO) + valid = (pAd->ApCfg.MBSSID[IfIdx].bWmmCapable == TRUE) ? FALSE : TRUE; + else +#endif /* P2P_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/mt7620/src/common/p2p.c b/mt7620/src/common/p2p.c new file mode 100644 index 0000000..62a6899 --- /dev/null +++ b/mt7620/src/common/p2p.c @@ -0,0 +1,5804 @@ +/* + *************************************************************************** + * 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: + p2p.c + + Abstract: + Peer to peer is also called Wifi Direct. P2P is a Task Group of WFA. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Jan Lee 2009-10-05 created for Peer-to-Peer(Wifi Direct) +*/ +#include "rt_config.h" + +/* Vendor Specific OUI for P2P defined by WFA. */ +UCHAR P2POUIBYTE[4] = {0x50, 0x6f, 0x9a, 0x9}; /* spec. 1.14 OUI */ +extern UCHAR ZERO_MAC_ADDR[]; +extern UCHAR STA_Wsc_Pri_Dev_Type[]; + +UCHAR WILDP2PSSID[7] = {'D', 'I', 'R', 'E', 'C', 'T','-'}; +UCHAR WILDP2PSSIDLEN = 7; +UCHAR WIFIDIRECT_OUI[] = {0x50, 0x6f, 0x9a, 0x09}; /* spec. 1.14 OUI */ +/* UCHAR DEFAULTWPAPSKEY[8] = {0x33, 0x35, 0x33, 0x34, 0x33, 0x36, 0x31, 0x34};*/ +/* Like to key in 12345678 */ +UCHAR DEFAULTWPAPSKEY[8] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}; + +extern INT Set_P2p_OpMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +extern INT Set_AP_WscSsid_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +extern INT Set_AP_WscConfMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +extern INT Set_AP_WscConfStatus_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +extern INT Set_AP_WscMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +extern INT Set_AP_WscGetConf_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +extern INT Set_AP_WscPinCode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +extern INT Set_P2pCli_WscSsid_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +extern INT Set_P2pCli_Ssid_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +extern INT Set_P2pCli_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +/* + ========================================================================== + Description: + Called once when the card is being initialized. + + Parameters: + + Note: + + ========================================================================== + */ + +#include "rt_config.h" +#include "p2p.h" + +VOID P2pCfgInit( + + IN PRTMP_ADAPTER pAd) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + pP2PCtrl->P2p_OpMode = P2P_CONCURRENT; + + pP2PCtrl->bKeepSlient = FALSE; + pP2PCtrl->NoAIndex = MAX_P2P_GROUP_SIZE; + pP2PCtrl->ListenChannel = 1; + pP2PCtrl->GroupChannel = 1; + pP2PCtrl->GroupOpChannel = 1; + P2pSetListenIntBias(pAd, 3); + pP2PCtrl->DeviceNameLen = 10; + pP2PCtrl->DeviceName[0] = 'R'; + pP2PCtrl->DeviceName[1] = 'a'; + pP2PCtrl->DeviceName[2] = 'l'; + pP2PCtrl->DeviceName[3] = 'i'; + pP2PCtrl->DeviceName[4] = 'n'; + pP2PCtrl->DeviceName[5] = 'k'; + pP2PCtrl->DeviceName[6] = '-'; + pP2PCtrl->DeviceName[7] = 'P'; + pP2PCtrl->DeviceName[8] = 0x32; + pP2PCtrl->DeviceName[9] = 'P'; + + /*pP2PCtrl->P2PDiscoProvState = P2P_DISABLE; */ + pP2PCtrl->P2PConnectState = P2P_CONNECT_IDLE; + /* Set Dpid to "not specified". it means, GUI doesn't set for connection yet. */ + pP2PCtrl->Dpid = DEV_PASS_ID_NOSPEC; + pP2PCtrl->P2pManagedParm.APP2pManageability = 0xff; + pP2PCtrl->P2pManagedParm.ICSStatus = ICS_STATUS_DISABLED; + P2pGroupTabInit(pAd); + P2pCrednTabClean(pAd); + P2pScanChannelDefault(pAd); + RTMPZeroMemory(pAd->P2pCfg.SSID, MAX_LEN_OF_SSID); + RTMPMoveMemory(pAd->P2pCfg.SSID, WILDP2PSSID, WILDP2PSSIDLEN); + /*RTMPMoveMemory(pAd->P2pCfg.Bssid, pAd->P2pCfg.CurrentAddress, MAC_ADDR_LEN); */ + pP2PCtrl->SSIDLen = WILDP2PSSIDLEN; + pP2PCtrl->GONoASchedule.bValid = FALSE; + pP2PCtrl->GONoASchedule.bInAwake = TRUE; + pP2PCtrl->GONoASchedule.bWMMPSInAbsent = FALSE; /* Set to FALSE if changes state to Awake */ + pP2PCtrl->GONoASchedule.Token = 0; + pP2PCtrl->GoIntentIdx = 0; + pP2PCtrl->Rule = P2P_IS_DEVICE; + pP2PCtrl->WscMode = WSC_PIN_MODE; + pP2PCtrl->DefaultConfigMethod = P2P_REG_CM_DISPLAY; + pP2PCtrl->bExtListen = FALSE; + pP2PCtrl->bIntraBss = FALSE; + pP2PCtrl->ExtListenInterval = P2P_EXT_LISTEN_INTERVAL; + pP2PCtrl->ExtListenPeriod = P2P_EXT_LISTEN_PERIOD; + pP2PCtrl->GONoASchedule.Count = 0; + pP2PCtrl->GONoASchedule.Duration = 0; + pP2PCtrl->GONoASchedule.Interval = 0; + pP2PCtrl->DevDiscPeriod = P2P_SCAN_PERIOD; + /* P2P WSC_IR default value */ + pP2PCtrl->DevInfo.Version = WSC_VERSION; + pP2PCtrl->bConfiguredAP = TRUE; + pP2PCtrl->DevInfo.RfBand |= WSC_RFBAND_24GHZ; /* 2.4G */ + NdisMoveMemory(&pP2PCtrl->DevInfo.PriDeviceType, &STA_Wsc_Pri_Dev_Type[0], 8); + WscGenerateUUID(pAd, &pP2PCtrl->Wsc_Uuid_E[0], &pP2PCtrl->Wsc_Uuid_Str[0], 0, FALSE); + NdisMoveMemory(&pP2PCtrl->DevInfo.Uuid[0], &pP2PCtrl->Wsc_Uuid_E[0], UUID_LEN_HEX); + + + pP2PCtrl->bSigmaEnabled = FALSE; + pP2PCtrl->bP2pCliPmEnable = FALSE; + pP2PCtrl->bLowRateQoSNULL = FALSE; + pP2PCtrl->bP2pCliReConnect = FALSE; + pP2PCtrl->bStopAuthRsp = TRUE; + pP2PCtrl->bP2pReSendTimerRunning = FALSE; + pP2PCtrl->DevDiscPeriod = P2P_SCAN_PERIOD; + pP2PCtrl->bPeriodicListen = TRUE; + pP2PCtrl->bConfirmByUI = FALSE; + + pP2PCtrl->bProvAutoRsp = TRUE; + pP2PCtrl->P2pProvIndex = 0xFF; + pP2PCtrl->P2pProvUserNotify = 0; + pP2PCtrl->pGoNegoRspOutBuffer = NULL; + pP2PCtrl->bSentProbeRSP = FALSE; + /* + Bit[31] : Software Based NoA implementation + Bit[23] : Opps, not use. + Bit[22] : Service Discovey, not use. + Bit[21] : Extent Listen + Bit[20] : Client Discovery + Bit[16:19] : OpChannel, not use + Bit[15] : IntraBss + Bit[12:14] : Config Method, not use. + Bit[8:11] : Default Channel, not use. + Bit[4:7] : GO Intent, not use. + Bit[3] : Invite + Bit[2] : Persistent, not use. + Bit[1] : Managed + Bit[0] : Enable, not use. + */ + pP2PCtrl->P2pControl.word = 0x80108008; + + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: \n", __FUNCTION__)); +} + +/* + ========================================================================== + Description: + Periodic Routine for P2P. + + Parameters: + + Note: + + ========================================================================== + */ +VOID P2pPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext; + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + ULONG BssIdx = BSS_NOT_FOUND; + + if ((pP2PCtrl->P2pCounter.bListen) && (pP2PCtrl->P2pCounter.ListenInterval > 0)) + pP2PCtrl->P2pCounter.ListenInterval--; /* update Listen interval */ + + if (pP2PCtrl->P2pCounter.NextScanRound > 0) + pP2PCtrl->P2pCounter.NextScanRound--; /* update Next Scan Round */ + + if (pP2PCtrl->P2pCounter.CounterAftrScanButton > 0) + pP2PCtrl->P2pCounter.CounterAftrScanButton--; /* update Device Discovery period */ + + if (pP2PCtrl->P2pCounter.CounterAftrSetEvent != 0xffffffff) + pP2PCtrl->P2pCounter.CounterAftrSetEvent++; + + if (pP2PCtrl->P2pCounter.ClientConnectedCounter > 0) + pP2PCtrl->P2pCounter.ClientConnectedCounter--; + + if (pP2PCtrl->P2pCounter.ManageAPEnReconCounter > 0) + pP2PCtrl->P2pCounter.ManageAPEnReconCounter--; + + DBGPRINT(RT_DEBUG_INFO, ("%s : Counter100ms[%ld] CounterAftScanButton[%ld] ClientConnCnt[%ld] MngAPEnReconnCnt[%ld] DisableRetryGrpFormCnt[%ld] NextScanRound[%ld]\n", + __FUNCTION__, pP2PCtrl->P2pCounter.Counter100ms, pP2PCtrl->P2pCounter.CounterAftrScanButton, pP2PCtrl->P2pCounter.ClientConnectedCounter, + pP2PCtrl->P2pCounter.CounterAftrSetEvent, pP2PCtrl->P2pCounter.DisableRetryGrpFormCounter, pP2PCtrl->P2pCounter.NextScanRound)); + + /* Scan period expired. Return to listen state. Only do once. So check value equal. */ + if ((pP2PCtrl->P2pCounter.bStartScan == TRUE) && (pAd->P2pCfg.P2pCounter.CounterAftrScanButton == 0)) + P2PDevDiscTimerExec(pAd, 0); + /* Check whether to start a P2P scan /search process. */ + if ((pP2PCtrl->P2pCounter.bListen) && (pP2PCtrl->P2pCounter.ListenInterval == 0)) + P2PListenTimerExec(pAd, 0); + if ((pP2PCtrl->P2pCounter.bNextScan == TRUE) && (pP2PCtrl->P2pCounter.NextScanRound == 0)) + P2PNextScanTimerExec(pAd, 0); + + if (pAd->P2pCfg.P2pCounter.UserAccept > 0) + { + pAd->P2pCfg.P2pCounter.UserAccept--; + } + + if ((pP2PCtrl->bProvAutoRsp == FALSE) && (pP2PCtrl->P2pProvIndex != P2P_NOT_FOUND) ) + { + if (pP2PCtrl->P2pCounter.UserAccept == 0) + { + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + pP2PCtrl->P2pProvUserNotify = 0; + pP2PCtrl->P2pProvIndex = P2P_NOT_FOUND; + } + } + + /* ====================================> */ + /* P2P connect state maintain */ + if (((pP2PCtrl->P2PConnectState == P2P_DO_GO_SCAN_BEGIN) + || (pP2PCtrl->P2PConnectState == P2P_DO_GO_NEG_DONE_CLIENT) + || (pP2PCtrl->P2PConnectState == P2P_DO_GO_SCAN_OP_BEGIN)) + && (pP2PCtrl->P2pCounter.Counter100ms == pP2PCtrl->P2pCounter.NextScanRound)) + { + DBGPRINT(RT_DEBUG_ERROR, ("P2P P2pPeriodicExec Scan Begin NextScanRound = %ld \n", pP2PCtrl->P2pCounter.NextScanRound)); + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID_LIST_SCAN, + 0, + "", + 0); + + MlmeHandler(pAd); + pP2PCtrl->P2pCounter.Counter100ms = 0; + pP2PCtrl->P2pCounter.NextScanRound = (RandomByte(pAd) % P2P_RANDOM_WPS_BASE) + 4; + } + else if ((pAd->P2pCfg.P2PConnectState == P2P_DO_GO_SCAN_DONE) + || (pAd->P2pCfg.P2PConnectState == P2P_DO_GO_SCAN_OP_DONE)) + { + /* if(pP2PCtrl->PortSubtype != PORTSUBTYPE_P2PGO) */ + if (!P2P_GO_ON(pAd)) + { + DBGPRINT(RT_DEBUG_ERROR, ("P2PConnectState[%s] : Do BssTableSearch\n", decodeP2PState(pP2PCtrl->P2PConnectState))); + /* BssIdx = BssTableSearch(pAd, &pAd->ScanTab, pAd->P2pCfg.Bssid, pAd->StaCfg.WscControl.WscAPChannel); */ + BssIdx = BssTableSearch(&pAd->ScanTab, pAd->P2pCfg.Bssid, pAd->MlmeAux.Channel); + } + /* Since can't find the target AP in the list. + Go back to scan state again to scan the target AP. */ + if (BssIdx == BSS_NOT_FOUND) + { + pP2PCtrl->P2PConnectState = P2P_DO_GO_SCAN_BEGIN; + pP2PCtrl->P2pCounter.Counter100ms = 0; + pP2PCtrl->P2pCounter.NextScanRound = 10; /* start scan after 1 s */ + DBGPRINT(RT_DEBUG_ERROR, ("CNTL - Nr= %d. Channel = %d. BSSID not found. %02x:%02x:%02x:%02x:%02x:%02x.\n", pAd->ScanTab.BssNr, pAd->MlmeAux.Channel /*pAd->StaCfg.WscControl.WscAPChannel*/, PRINT_MAC(pP2PCtrl->Bssid))); + DBGPRINT(RT_DEBUG_ERROR, ("CNTL - BSSID not found. Goback to %s \n", decodeP2PState(pP2PCtrl->P2PConnectState))); + return; + } + else if (pAd->ScanTab.BssEntry[BssIdx].SsidLen < 9) + { + pP2PCtrl->P2PConnectState = P2P_DO_GO_SCAN_BEGIN; + pP2PCtrl->P2pCounter.Counter100ms = 0; + pP2PCtrl->P2pCounter.NextScanRound = 5; /* start scan after 500ms */ + DBGPRINT(RT_DEBUG_ERROR, ("CNTL -Nr= %d. Channel = %d. SSID is %c%c%c%c%c%c \n", pAd->ScanTab.BssNr, pAd->MlmeAux.Channel /*pAd->StaCfg.WscControl.WscAPChannel*/, pAd->P2pCfg.SSID[0], pAd->P2pCfg.Bssid[1],pAd->P2pCfg.SSID[2],pAd->P2pCfg.SSID[3],pAd->P2pCfg.SSID[4],pAd->P2pCfg.SSID[5])); + DBGPRINT(RT_DEBUG_ERROR, ("CNTL - Goback to %s \n", decodeP2PState(pAd->P2pCfg.P2PConnectState))); + return; + } + + /* Now copy the scanned SSID to my CommonCfg.Ssid */ + RTMPMoveMemory(pP2PCtrl->PortCfg.Ssid, pAd->ScanTab.BssEntry[BssIdx].Ssid,32); + pP2PCtrl->PortCfg.SsidLen = pAd->ScanTab.BssEntry[BssIdx].SsidLen; + DBGPRINT(RT_DEBUG_ERROR, ("P2P P2pPeriodicExec P2P_DO_GO_SCAN_DONE. Find BssIdx = %ld\n", BssIdx)); + DBGPRINT(RT_DEBUG_ERROR, ("Change P2PConnectState[%s -> %s]\n", decodeP2PState(pP2PCtrl->P2PConnectState), decodeP2PState(P2P_DO_WPS_ENROLLEE))); + pP2PCtrl->P2PConnectState = P2P_DO_WPS_ENROLLEE; + } + /* <<==================================== */ + P2pGroupMaintain(pAd); + + /* P2P_ANY_IN_FORMATION_AS_GO means I am AutoGO. AutoGo also need to do scan. So don't return here. */ + if (IS_P2P_CONNECTING(pAd) && (pP2PCtrl->P2PConnectState != P2P_ANY_IN_FORMATION_AS_GO)) + { + return; + } + + /* <<==================================== */ + + /* Maintain listen state when in Concurrent mode. STA+P2P + check if need to resume NoA Schedule. */ +} + +BOOLEAN P2pResetNoATimer( + IN PRTMP_ADAPTER pAd, + IN ULONG DiffTimeInus) +{ + ULONG GPDiff; + /*ULONG Value;*/ + 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; + if (GPDiff > 0) + { + GPDiff++; + RTMPSetTimer(&pAd->P2pCfg.P2pSwNoATimer, GPDiff); + /* Increase timer tick counter. */ + pAd->P2pCfg.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->P2pCfg.GONoASchedule.bInAwake == FALSE) + { + if (GPDiff > 10) + { + RTMPSetTimer(&pAd->P2pCfg.P2pPreAbsenTimer, (GPDiff - 10)); + } + } + } + } + else + { + brc = P2pSetGP(pAd, DiffTimeInus); + } + return brc; + +} + + +/* + ========================================================================== + Description: + Start P2P Search State + + Parameters: + + Note: + + ========================================================================== + */ +VOID P2pScan( + IN PRTMP_ADAPTER pAd) +{ + BOOLEAN Cancelled; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + /* Stop Scan and resume */ + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); + pAd->MlmeAux.Channel = 0; + ScanNextChannel(pAd, OPMODE_STA); + } + + P2pGotoIdle(pAd); + P2pGroupTabInit(pAd); + P2PInitDevDiscTimer(pAd, 0); + P2PInitNextScanTimer(pAd, 0); + /* Set P2P Device Discovery Timer */ + P2PSetDevDiscTimer(pAd, 0); + P2PSetNextScanTimer(pAd, 10); +} + +/* + ========================================================================== + Description: + Stop connect command to connect with current MAC becuase the connect process already bagan. + + Parameters: + + Note: + + ========================================================================== + */ +VOID P2pStopConnectThis( + IN PRTMP_ADAPTER pAd) +{ + RTMPZeroMemory(&pAd->P2pCfg.ConnectingMAC[0], MAC_ADDR_LEN); +} + +/* + ========================================================================== + Description: + Set parameter stop P2P Search State when P2P has started Group Formation. + + Parameters: + + Note: + + ========================================================================== + */ +VOID P2pStopScan( + IN PRTMP_ADAPTER pAd) +{ + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_INFO, ("<---- P2P - P2pStopScan @channel = %d.\n", pAd->MlmeAux.Channel)); + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + /* Stop Scan and resume */ + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); + pAd->MlmeAux.Channel = 0; + ScanNextChannel(pAd, OPMODE_STA); + } + + /* Set scan channel to Last one to stop Scan Phase. Because SCannextchannel will use channel to judge if it should stop scan. */ + P2PInitDevDiscTimer(pAd, 0); + P2PInitListenTimer(pAd, 0); + P2PInitNextScanTimer(pAd, 0); + P2pGotoIdle(pAd); + /* update P2P Ctrl State Machine status. */ + MlmeEnqueue(pAd, P2P_CTRL_STATE_MACHINE, P2P_CTRL_DISC_CANL_EVT, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); + +#ifdef DPA_S + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_DISCOVER_CANCEL, NULL, NULL, 0); +#endif /* DPA_S */ + DBGPRINT(RT_DEBUG_INFO, ("----> P2P - P2pStopScan @channel = %d.\n", pAd->MlmeAux.Channel)); +} + +/* + ========================================================================== + Description: + Goto Idle state. Update necessary parameters. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pGotoIdle( + IN PRTMP_ADAPTER pAd) +{ + /* pAd->P2pCfg.P2PDiscoProvState = P2P_ENABLE_LISTEN_ONLY; */ + pAd->P2pCfg.P2pCounter.Counter100ms = 0; + /* Set a randon period to start next Listen State. */ + /* pAd->P2pCfg.P2pCounter.NextScanRound = (RandomByte(pAd) % P2P_RANDOM_BASE) + P2P_RANDOM_BIAS; */ + + pAd->P2pCfg.CtrlCurrentState = P2P_CTRL_IDLE; + pAd->P2pCfg.DiscCurrentState = P2P_DISC_IDLE; + pAd->P2pCfg.GoFormCurrentState = P2P_GO_FORM_IDLE; +} + + +/* + ========================================================================== + Description: + Goto Scan/Search state. Update necessary parameters. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pGotoScan( + IN PRTMP_ADAPTER pAd) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + /* Reset 100ms Counter to zero. */ + pAd->P2pCfg.P2pCounter.Counter100ms = 0; + /* Set a short time to start next search State for the 1st time. */ + pAd->P2pCfg.P2pCounter.NextScanRound = 5; + + DBGPRINT(RT_DEBUG_ERROR, ("P2pGotoScan! Set pP2PCtrl->NextScanRound = %ld Here!!!\n", pP2PCtrl->P2pCounter.NextScanRound)); +} + +/* + ========================================================================== + Description: + When I am GO, start a P2P NoA schedule. + + Parameters: + S - pointer to the association state machine + Note: + The state machine looks like the following as name implies its function + ========================================================================== + */ +VOID P2pGOStartNoA( + IN PRTMP_ADAPTER pAd) +{ + ULONG Value; + ULONG TimeTillTbtt; + ULONG temp; + + pAd->P2pCfg.GONoASchedule.Token++; + pAd->P2pCfg.GONoASchedule.bValid = TRUE; + /* Start Time */ + RTMP_IO_READ32(pAd, TSF_TIMER_DW1, &pAd->P2pCfg.GONoASchedule.TsfHighByte); + DBGPRINT(RT_DEBUG_TRACE,("P2pGOStartNoA parameter.!!!!HighByte = %lx \n", pAd->P2pCfg.GONoASchedule.TsfHighByte)); + RTMP_IO_READ32(pAd, TBTT_TIMER, &TimeTillTbtt); + TimeTillTbtt = TimeTillTbtt&0x1ffff; + DBGPRINT(RT_DEBUG_TRACE,(" .!!!!TimeTillTbtt = %ld \n", TimeTillTbtt)); + + RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &Value); + DBGPRINT(RT_DEBUG_TRACE,(" .!!!!Current Tsf LSB = = %ld \n", Value)); + temp = TimeTillTbtt*64+Value; + DBGPRINT(RT_DEBUG_TRACE,(" .!!!!Tsf LSB + TimeTillTbtt= %ld \n", temp)); + /* Wait five beacon 0x7d00 for 5 beacon interval. 0x6400 is set to 25%*beacon interval */ + pAd->P2pCfg.GONoASchedule.StartTime = Value + TimeTillTbtt*64 + 512000 + 25600; + pAd->P2pCfg.GONoASchedule.NextTargetTimePoint = Value + TimeTillTbtt*64 + 512000 + 25600 + pAd->P2pCfg.GONoASchedule.Duration; + pAd->P2pCfg.GONoASchedule.ThreToWrapAround = pAd->P2pCfg.GONoASchedule.StartTime + 0x7fffffff; + P2pSetGP(pAd, (TimeTillTbtt*64 + 512000 + 25600)); + temp = Value + TimeTillTbtt*64 + 0x7D000 + 0x6400; + DBGPRINT(RT_DEBUG_TRACE,(" .!!!!Expect Starttime= %ld. ThreToWrapAround = %ld. \n", temp, pAd->P2pCfg.GONoASchedule.ThreToWrapAround)); + temp = temp - Value; + DBGPRINT(RT_DEBUG_TRACE,(" .!!!!more = %ld to start time \n", temp)); + pAd->P2pCfg.GONoASchedule.bInAwake = TRUE; + +} + +VOID P2pStopNoA( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pMacClient) +{ + ULONG Value; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE,("P2pStopNoA.!!!! \n")); + + RTMPCancelTimer(&pAd->P2pCfg.P2pPreAbsenTimer, &Cancelled); + pAd->P2pCfg.bKeepSlient = FALSE; + pAd->P2pCfg.bPreKeepSlient = FALSE; + if (pMacClient != NULL) + { + pMacClient->P2pInfo.NoADesc[0].Count = 0xf3; + pMacClient->P2pInfo.NoADesc[0].bValid = FALSE; + pMacClient->P2pInfo.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->P2pInfo.NoADesc[0].Token--; + } + RTMPCancelTimer(&pAd->P2pCfg.P2pSwNoATimer, &Cancelled); + pAd->P2pCfg.GONoASchedule.bValid = FALSE; + pAd->P2pCfg.GONoASchedule.bInAwake = TRUE; + pAd->P2pCfg.GONoASchedule.bWMMPSInAbsent = FALSE; /* Set to FALSE if changes state to Awake */ + /* If need not resume NoA. Can reset all parameters. */ + if (pAd->P2pCfg.GONoASchedule.bNeedResumeNoA == FALSE) + { + pAd->P2pCfg.GONoASchedule.Count = 1; + pAd->P2pCfg.GONoASchedule.Duration = 0xc800; + pAd->P2pCfg.GONoASchedule.Interval = 0x19000; + } + + RTMP_IO_READ32(pAd, INT_TIMER_EN, &Value); + Value &= (0xfffffffd); + RTMP_IO_WRITE32(pAd, INT_TIMER_EN, Value); + pAd->P2pCfg.GONoASchedule.SwTimerTickCounter = 0; + + /* Set to false again. */ + pAd->P2pCfg.bPreKeepSlient = FALSE; + +} + +VOID P2pStartOpPS( + IN PRTMP_ADAPTER pAd) +{ + if (pAd->P2pCfg.GONoASchedule.bValid == TRUE) + P2pStopNoA(pAd, NULL); + + DBGPRINT(RT_DEBUG_TRACE,("P2P : !! P2pStartOpPS \n")); + pAd->P2pCfg.CTWindows = 0x8a; + /* Wait next beacon period to really start queue packet. */ + pAd->P2pCfg.bKeepSlient = FALSE; + +} + +VOID P2pStopOpPS( + IN PRTMP_ADAPTER pAd) +{ + if (pAd->P2pCfg.GONoASchedule.bValid == FALSE) + pAd->P2pCfg.bKeepSlient = FALSE; + + if (P2P_TEST_BIT(pAd->P2pCfg.CTWindows, P2P_OPPS_BIT)) + pAd->P2pCfg.bFirstTimeCancelOpps = TRUE; + pAd->P2pCfg.CTWindows = 0; +} + +/* + ========================================================================== + 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 P2pPreAbsenTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext; + pAd->P2pCfg.bPreKeepSlient = 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 P2pSwNoATimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext; + P2pGPTimeOutHandle(pAd); +} + +/* + ========================================================================== + Description: + When I am P2P GO / Client , Handle P2P session execute WSC in 30secs. + + Parameters: + S - pointer to the association state machine + Note: + The state machine looks like the following as name implies its function + ========================================================================== + */ +VOID P2pWscTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext; + BOOLEAN Cancelled; + PRT_P2P_CONFIG pP2pCtrl = &pAd->P2pCfg; + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: P2P Execute WSC has expire %dsecs, Stop it!\n", __FUNCTION__, (P2P_WSC_TIMER/1000))); + RTMPCancelTimer(&pP2pCtrl->P2pWscTimer, &Cancelled); + + if (P2P_CLI_ON(pAd)) + { +#ifdef RTMP_MAC_PCI + P2pLinkDown(pAd, P2P_DISCONNECTED); +#endif /* RTMP_MAC_PCI */ + } + else if (P2P_GO_ON(pAd)) + { + UINT32 i, p2pEntryCnt=0; + MAC_TABLE_ENTRY *pEntry; + PWSC_CTRL pWscControl = &pAd->ApCfg.MBSSID[0].WscControl; + + for (i=0; iMacTab.Content[i]; + if (IS_P2P_GO_ENTRY(pEntry) && (pEntry->WpaState == AS_PTKINITDONE)) + p2pEntryCnt++; + } + DBGPRINT(RT_DEBUG_ERROR, ("P2pWscTimeOut - Total= %d. p2pEntry = %d.\n", pAd->MacTab.Size, p2pEntryCnt)); + + if ((p2pEntryCnt == 0) && (pAd->flg_p2p_OpStatusFlags == P2P_GO_UP)) +#ifdef RTMP_MAC_PCI + P2pLinkDown(pAd, P2P_DISCONNECTED); +#endif /* RTMP_MAC_PCI */ + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s:: not P2P GO / CLI on !!\n", __FUNCTION__)); +} + +VOID P2pReSendTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext; + PRT_P2P_CLIENT_ENTRY pP2pEntry = NULL; + BOOLEAN Cancelled; + PRT_P2P_CONFIG pP2pCtrl = &pAd->P2pCfg; + UCHAR BBPValue = 0; + UCHAR p2pindex = P2P_NOT_FOUND; + ULONG FrameLen; + USHORT ConfigMthd; + + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: P2P Send to %02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, PRINT_MAC(pP2pCtrl->ConnectingMAC))); + pP2pCtrl->bP2pReSendTimerRunning = FALSE; + RTMPCancelTimer(&pP2pCtrl->P2pReSendTimer, &Cancelled); + + p2pindex = P2pGroupTabSearch(pAd, pP2pCtrl->ConnectingMAC); + if (p2pindex < MAX_P2P_GROUP_SIZE) + { + pP2pEntry = &pAd->P2pTable.Client[p2pindex]; + pP2pEntry->ReTransmitCnt++; + + if (pP2pEntry->ReTransmitCnt >= 10) + { + DBGPRINT(RT_DEBUG_ERROR, ("ReTransmitCnt limit! stop connect this p2p device!\n")); + P2pStopConnectThis(pAd); + } + + pP2pEntry->GeneralToken++; + switch(pP2pEntry->P2pClientState) + { + case P2PSTATE_SENT_PROVISION_REQ: + if (pP2pCtrl->ConfigMethod == WSC_CONFMET_DISPLAY) + { + DBGPRINT(RT_DEBUG_ERROR, ("Re-Send PROVISION REQ. KEYPAD\n")); + ConfigMthd = WSC_CONFMET_KEYPAD; + } + else if (pP2pCtrl->ConfigMethod == WSC_CONFMET_KEYPAD) + { + DBGPRINT(RT_DEBUG_ERROR, ("Re-Send PROVISION REQ. DISPLAY\n")); + ConfigMthd = WSC_CONFMET_DISPLAY; + } + else if (pP2pCtrl->ConfigMethod == WSC_CONFMET_PBC) + { + DBGPRINT(RT_DEBUG_ERROR, ("Re-Send PROVISION REQ. PBC\n")); + ConfigMthd = WSC_CONFMET_PBC; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Re-Send PROVISION REQ. wrong Config Method(%d)\n", + pP2pCtrl->ConfigMethod)); + return; + } + P2PSendProvisionReq(pAd, ConfigMthd, pP2pEntry->GeneralToken, pP2pEntry->addr, &FrameLen); + break; + case P2PSTATE_SENT_GO_NEG_REQ: + DBGPRINT(RT_DEBUG_ERROR, ("Re-Send GO NEGO REQ.\n")); + P2pStartGroupForm(pAd, pP2pCtrl->ConnectingMAC, p2pindex); + break; + case P2PSTATE_SENT_PROVISION_RSP: + if ( pP2pCtrl->bProvAutoRsp == TRUE ) + break; + + if ( pP2pCtrl->P2pProvUserNotify == 1 ) + { + if ( pP2pEntry->ReTransmitCnt < 9 ) + { + P2PSendProvisionRsp(pAd, pP2pCtrl->P2pProvConfigMethod, pP2pCtrl->P2pProvToken, pP2pCtrl->ConnectingMAC, &FrameLen); + } + else + { + pP2pCtrl->P2pProvUserNotify = 0; + pP2pCtrl->P2pProvIndex = P2P_NOT_FOUND; + pP2pCtrl->P2pProvUserNotify = FALSE; + pAd->P2pCfg.P2pCounter.UserAccept = 0; + } + } + else + { + if ( pP2pEntry->ReTransmitCnt < 2 ) + P2PSendProvisionRsp(pAd, 0, pP2pCtrl->P2pProvToken, pP2pCtrl->ConnectingMAC, &FrameLen); + else + pP2pCtrl->P2pProvUserNotify = 0; + } + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("ReSendTimeout execute with unknown state - %s\n", decodeP2PClientState(pP2pEntry->P2pClientState))); + } + } +} + +VOID P2pCliReConnectTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext; + PRT_P2P_CLIENT_ENTRY pP2pEntry = NULL; + BOOLEAN Cancelled; + PRT_P2P_CONFIG pP2pCtrl = &pAd->P2pCfg; + UCHAR BBPValue = 0; + UCHAR p2pindex = P2P_NOT_FOUND; + ULONG FrameLen; + USHORT ConfigMthd; + + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: P2P Send to %02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, PRINT_MAC(pP2pCtrl->ConnectingMAC))); + pP2pCtrl->bP2pCliReConnectTimerRunning = FALSE; + RTMPCancelTimer(&pP2pCtrl->P2pCliReConnectTimer, &Cancelled); + + /* Tear Down the P2P Connection */ + P2pLinkDown(pAd, P2P_DISCONNECTED); +} + +/* + ========================================================================== + 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 + ========================================================================== + */ +BOOLEAN P2pHandleNoAAttri( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pMacClient, + IN PUCHAR pData) +{ + PP2P_NOA_DESC pNoADesc; + ULONG Value, GPDiff; + UCHAR index; + ULONG NoALen; + ULONG StartTime; + + if (pMacClient == NULL) + return FALSE; + + if ((*pData == SUBID_P2P_NOA)) + { + NoALen = *(pData+1); + if (NoALen == 2) + { + pMacClient->P2pInfo.CTWindow = *(pData+4); + if (pMacClient->P2pInfo.NoADesc[0].bValid == TRUE) + 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->P2pCfg.CTWindows = *(pData+4); + return TRUE; + } + + index = *(pData+3); + pMacClient->P2pInfo.CTWindow = *(pData+4); + /* + Copy 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->P2pCfg.CTWindows = *(pData+4); + pNoADesc = (PP2P_NOA_DESC)(pData+5); + pMacClient->P2pInfo.NoADesc[0].Count = pNoADesc->Count; + pMacClient->P2pInfo.NoADesc[0].Duration = *(PUINT32)&pNoADesc->Duration[0]; + pMacClient->P2pInfo.NoADesc[0].Interval = *(PUINT32)&pNoADesc->Interval[0]; + pMacClient->P2pInfo.NoADesc[0].StartTime = *(PUINT32)&pNoADesc->StartTime[0]; + StartTime = *(PUINT32)&pNoADesc->StartTime[0]; + + if (pMacClient->P2pInfo.NoADesc[0].Token == index) + { + /* The same NoA. Doesn't need to set this NoA again. */ + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE,("P2P : !!!NEW NOA Here =[%d, %d] Count = %d. Duration = %ld \n", pMacClient->P2pInfo.NoADesc[0].Token, index, pNoADesc->Count, pMacClient->P2pInfo.NoADesc[0].Duration)); + DBGPRINT(RT_DEBUG_TRACE,("P2P : !!!NEW NOA Here = CTWindow = %x \n", pMacClient->P2pInfo.CTWindow)); + pMacClient->P2pInfo.NoADesc[0].Token = index; + /*RTMP_IO_FORCE_READ32(pAd, TSF_TIMER_DW0, &Value); */ + Value = pAd->P2pCfg.GONoASchedule.LastBeaconTimeStamp; + DBGPRINT(RT_DEBUG_TRACE,("Interval = %ld. StartTime = %ld. TSF timer Register = %ld\n", pMacClient->P2pInfo.NoADesc[0].Interval, pMacClient->P2pInfo.NoADesc[0].StartTime, Value)); + if ((pMacClient->P2pInfo.NoADesc[0].Duration <= 0x40) || (pMacClient->P2pInfo.NoADesc[0].Interval <= 0x40)) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!!!!Interval or Duration too small. ignore. = %lx return 1\n", Value)); + return FALSE; + } + else if ((pMacClient->P2pInfo.NoADesc[0].Duration >= pMacClient->P2pInfo.NoADesc[0].Interval) + && (pMacClient->P2pInfo.NoADesc[0].Count > 1)) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!!!!Duration > Inveral. return 2\n")); + return FALSE; + } + + /* if Start time point is in the future. */ + pAd->P2pCfg.GONoASchedule.CurrentTargetTimePoint = pMacClient->P2pInfo.NoADesc[0].StartTime; + if (Value < StartTime) + { + GPDiff = pMacClient->P2pInfo.NoADesc[0].StartTime - Value; + pMacClient->P2pInfo.NoADesc[0].NextTargetTimePoint = pMacClient->P2pInfo.NoADesc[0].StartTime + pMacClient->P2pInfo.NoADesc[0].Duration; + pAd->P2pCfg.GONoASchedule.OngoingAwakeTime = pMacClient->P2pInfo.NoADesc[0].NextTargetTimePoint; + pAd->P2pCfg.GONoASchedule.NextTimePointForWMMPSCounting = pMacClient->P2pInfo.NoADesc[0].StartTime; + DBGPRINT(RT_DEBUG_TRACE,("!!!!! GPDiff = %ld = 0x%lx. NextTargetTimePoint = %ld\n", GPDiff, GPDiff, pMacClient->P2pInfo.NoADesc[0].NextTargetTimePoint)); + /* try to set General Timer. */ + pAd->P2pCfg.GONoASchedule.LastBeaconTimeStamp += GPDiff; + if (P2pResetNoATimer(pAd, GPDiff)) + { + DBGPRINT(RT_DEBUG_TRACE,("!!!!!Start NoA 1 GPDiff = %ld \n", GPDiff)); + pMacClient->P2pInfo.NoADesc[0].bValid = TRUE; + pMacClient->P2pInfo.NoADesc[0].bInAwake = TRUE; + pMacClient->P2pInfo.NoADesc[0].Token = index; + return TRUE; + } + } + /* else if Start time point is in the past. */ + else if (Value >= StartTime) + { + do + { + StartTime += pMacClient->P2pInfo.NoADesc[0].Interval; + if ((StartTime > Value) && ((StartTime-Value) > 0x80)) + { + GPDiff = StartTime - Value; + pMacClient->P2pInfo.NoADesc[0].NextTargetTimePoint = StartTime /*+ pMacClient->P2pInfo.NoADesc[0].Interval*/ - pMacClient->P2pInfo.NoADesc[0].Duration; + pAd->P2pCfg.GONoASchedule.OngoingAwakeTime = pMacClient->P2pInfo.NoADesc[0].NextTargetTimePoint; + pAd->P2pCfg.GONoASchedule.LastBeaconTimeStamp += GPDiff; + if (P2pResetNoATimer(pAd, GPDiff)) + { + DBGPRINT(RT_DEBUG_TRACE,("!!!!!Start NoA 2 GPDiff = %ld\n", GPDiff)); + pMacClient->P2pInfo.NoADesc[0].bValid = TRUE; + pMacClient->P2pInfo.NoADesc[0].bInAwake = TRUE; + pMacClient->P2pInfo.NoADesc[0].Token = index; + return TRUE; + } + } + }while(TRUE); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Start time in before ..!!Check \n")); + } + } + return FALSE; + +} + +BOOLEAN P2pSetGP( + IN PRTMP_ADAPTER pAd, + IN ULONG DiffTimeInus) +{ + ULONG GPDiff; + ULONG Value; + + GPDiff = (DiffTimeInus/64) & 0xffff; + if (GPDiff > 0) + { + GPDiff = GPDiff<<16; + RTMP_IO_WRITE32(pAd, INT_TIMER_CFG, GPDiff); + RTMP_IO_READ32(pAd, INT_TIMER_EN, &Value); + Value |= 0x2; + RTMP_IO_WRITE32(pAd, INT_TIMER_EN, Value); + return TRUE; + } + return FALSE; +} + +BOOLEAN P2pAdjustSwNoATimer( + IN PRTMP_ADAPTER pAd, + IN ULONG CurrentTimeStamp, + IN ULONG NextTimePoint) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + 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)); + P2pStopNoA(pAd, &pAd->MacTab.Content[pP2PCtrl->MyGOwcid]); + FakeNoAAttribute[0] = SUBID_P2P_NOA; + NewStartTime = pP2PCtrl->GONoASchedule.StartTime + (pP2PCtrl->GONoASchedule.SwTimerTickCounter - 1)*(pP2PCtrl->GONoASchedule.Interval); + P2PMakeFakeNoATlv(pAd, NewStartTime, &FakeNoAAttribute[0]); + pAd->MacTab.Content[pP2PCtrl->MyGOwcid].P2pInfo.NoADesc[0].Token--; + 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 P2pGPTimeOutHandle( + IN PRTMP_ADAPTER pAd) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + MAC_TABLE_ENTRY *pEntry; + ULONG MacValue; + ULONG Value; + ULONG GPDiff; + ULONG NextDiff; + ULONG 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 (P2P_GO_ON(pAd)) + { + if (pP2PCtrl->GONoASchedule.bValid == TRUE) + { + if ((pP2PCtrl->GONoASchedule.Count > 0) && (pP2PCtrl->GONoASchedule.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 (pP2PCtrl->GONoASchedule.bInAwake == FALSE) + pP2PCtrl->GONoASchedule.Count--; + } + if (pP2PCtrl->GONoASchedule.Count == 0) + { + P2pStopNoA(pAd, NULL); + DBGPRINT(RT_DEBUG_TRACE,("P2pGPTimeOutHandle.!!StopGP. return.1 \n")); + return; + } + + if (pP2PCtrl->GONoASchedule.bInAwake == TRUE) + NextDiff = pP2PCtrl->GONoASchedule.Duration; + else + NextDiff = pP2PCtrl->GONoASchedule.Interval - pP2PCtrl->GONoASchedule.Duration; + + /* Prepare next time. */ + /*RTMP_IO_FORCE_READ32(pAd, TSF_TIMER_DW0, &Value); */ + Value = pAd->P2pCfg.GONoASchedule.LastBeaconTimeStamp; + + /* Check whether we should to renew the NoA because at least 2^31 us should update once according to spec. */ + if (pP2PCtrl->GONoASchedule.ThreToWrapAround > pP2PCtrl->GONoASchedule.StartTime) + { + if (Value > pP2PCtrl->GONoASchedule.ThreToWrapAround) + { + pP2PCtrl->GONoASchedule.bNeedResumeNoA = TRUE; + P2pStopNoA(pAd, NULL); + DBGPRINT(RT_DEBUG_TRACE,("P2pGPTimeOutHandle.!!StopGP. return.3. will resume.\n")); + return; + } + } + else + { + if ((Value > pP2PCtrl->GONoASchedule.ThreToWrapAround) && (Value < pP2PCtrl->GONoASchedule.StartTime)) + { + pP2PCtrl->GONoASchedule.bNeedResumeNoA = TRUE; + P2pStopNoA(pAd, NULL); + DBGPRINT(RT_DEBUG_TRACE,("P2pGPTimeOutHandle.!!StopGP. return.4. will resume. \n")); + return; + } + } + + SavedNextTargetTimePoint = pP2PCtrl->GONoASchedule.NextTargetTimePoint; + if (Value <= pP2PCtrl->GONoASchedule.NextTargetTimePoint) + { + GPDiff = pP2PCtrl->GONoASchedule.NextTargetTimePoint - Value; + pP2PCtrl->GONoASchedule.NextTimePointForWMMPSCounting = pP2PCtrl->GONoASchedule.NextTargetTimePoint; + pP2PCtrl->GONoASchedule.NextTargetTimePoint += NextDiff; + P2pResetNoATimer(pAd, GPDiff); + DBGPRINT(RT_DEBUG_INFO,(" NextTargetTimePoint = %ld. \n", pAd->P2pCfg.GONoASchedule.NextTargetTimePoint)); + DBGPRINT(RT_DEBUG_INFO,(" Value = %ld. GPDiff = %ld.\n", Value, GPDiff)); + } + else + { + /* driver restart NoA due to our GP timer's delay. */ + if (pP2PCtrl->GONoASchedule.Count == 255) + { + pP2PCtrl->GONoASchedule.bNeedResumeNoA = TRUE; + DBGPRINT(RT_DEBUG_TRACE,(" Prepare resume NoA. \n")); + } + P2pStopNoA(pAd, NULL); + DBGPRINT(RT_DEBUG_TRACE,("3 NextTargetTimePoint = %ld. \n", pP2PCtrl->GONoASchedule.NextTargetTimePoint)); + DBGPRINT(RT_DEBUG_TRACE,(" 3 Value = %ld= 0x%lx NextDiff = %ld.\n", Value, Value, NextDiff)); + DBGPRINT(RT_DEBUG_TRACE,("3 P2pGPTimeOutHandle.!!StopGP. return.2 \n")); + return; + } + + if (pP2PCtrl->GONoASchedule.bInAwake == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE,(" ----------------------->>> NoA Go to SLEEP \n")); + pP2PCtrl->GONoASchedule.bWMMPSInAbsent = TRUE; /* Set to FALSE if changes state to absent */ + pP2PCtrl->bKeepSlient = TRUE; + pP2PCtrl->bPreKeepSlient = TRUE; + pP2PCtrl->GONoASchedule.bInAwake = FALSE; + /* roughly check that if duration > 100ms, we should call Pause beacon. */ + if (pP2PCtrl->GONoASchedule.Duration >= 0x19000) + { + P2pPauseBssSync(pAd); + } + + + } + else + { + DBGPRINT(RT_DEBUG_TRACE,(" NoA Wake UP ----------------------->>> \n")); + pP2PCtrl->GONoASchedule.bInAwake = TRUE; + pP2PCtrl->GONoASchedule.bWMMPSInAbsent = FALSE; /* Set to FALSE if changes state to Awake */ + pP2PCtrl->bKeepSlient = FALSE; + pP2PCtrl->bPreKeepSlient = FALSE; + if (pP2PCtrl->GONoASchedule.Duration >= 0x19000) + { + P2pResumeBssSync(pAd); + } + if (IS_SW_NOA_TIMER(pAd) + && (pP2PCtrl->GONoASchedule.Count > 100)) + { + if (TRUE == P2pAdjustSwNoATimer(pAd, Value, SavedNextTargetTimePoint)) + { + /*DBGPRINT(RT_DEBUG_TRACE,("SwBasedNoA : Dequeue here. %d\n", pAd->TxSwNoAMgmtQueue.Number));*/ + /*RTMPDeQueueNoAMgmtPacket(pAd);*/ + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } + } + else + { + /*RTMPDeQueueNoAMgmtPacket(pAd);*/ + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } + } + + } + + } + else if (P2P_CLI_ON(pAd)) + { + if (pP2PCtrl->NoAIndex >= MAX_LEN_OF_MAC_TABLE) + return; + + if (pP2PCtrl->NoAIndex != pP2PCtrl->MyGOwcid) + DBGPRINT(RT_DEBUG_TRACE,("P2pGPTimeOutHandle. !bug, please check driver %d. \n", pP2PCtrl->NoAIndex)); + + pEntry = &pAd->MacTab.Content[pP2PCtrl->NoAIndex]; + if (pEntry->P2pInfo.NoADesc[0].bValid == TRUE) + { + if ((pEntry->P2pInfo.NoADesc[0].Count > 0) && (pEntry->P2pInfo.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->P2pInfo.NoADesc[0].bInAwake == FALSE) + pEntry->P2pInfo.NoADesc[0].Count--; + } + if (pEntry->P2pInfo.NoADesc[0].Count == 0) + { + P2pStopNoA(pAd, pEntry); + DBGPRINT(RT_DEBUG_TRACE,("P2pGPTimeOutHandle. Count down to zero!!StopGP. return.1 \n")); + return; + } + + /* To enter absence period, stop transmission a little bit earlier to leave HW to clean the queue. */ + if (pEntry->P2pInfo.NoADesc[0].bInAwake == FALSE) + NextDiff = pEntry->P2pInfo.NoADesc[0].Duration - 0x200; + else + NextDiff = pEntry->P2pInfo.NoADesc[0].Interval - pEntry->P2pInfo.NoADesc[0].Duration + 0x200; + + /* Prepare next time. */ + MacValue = 0x333; + /*RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &MacValue); */ + MacValue = pAd->P2pCfg.GONoASchedule.LastBeaconTimeStamp; + DBGPRINT(RT_DEBUG_INFO,("2 Tsf Timer = %ld= 0x%lx NextTargetTimePoint = %ld.\n", MacValue, MacValue,pEntry->P2pInfo.NoADesc[0].NextTargetTimePoint)); + SavedNextTargetTimePoint = pEntry->P2pInfo.NoADesc[0].NextTargetTimePoint; + if (MacValue <= pEntry->P2pInfo.NoADesc[0].NextTargetTimePoint) + { + GPDiff = pEntry->P2pInfo.NoADesc[0].NextTargetTimePoint - MacValue; + pAd->P2pCfg.GONoASchedule.NextTimePointForWMMPSCounting = pEntry->P2pInfo.NoADesc[0].NextTargetTimePoint; + pEntry->P2pInfo.NoADesc[0].NextTimePointForWMMPSCounting = pEntry->P2pInfo.NoADesc[0].NextTargetTimePoint; + pEntry->P2pInfo.NoADesc[0].NextTargetTimePoint += NextDiff; + P2pResetNoATimer(pAd, GPDiff); + DBGPRINT(RT_DEBUG_INFO,("3 Continue next NOA NextTargetTimePoint = %lx. \n", pEntry->P2pInfo.NoADesc[0].NextTargetTimePoint)); + DBGPRINT(RT_DEBUG_INFO,("3 Value = %lx. NextDiff = %lx.\n", MacValue, NextDiff)); + } + else + { + P2pStopNoA(pAd, pEntry); + DBGPRINT(RT_DEBUG_TRACE,("4 NOA NextTargetTimePoint = %ld. \n", pEntry->P2pInfo.NoADesc[0].NextTargetTimePoint)); + DBGPRINT(RT_DEBUG_TRACE,("4 Value = %ld = 0x%lx. NextDiff = %ld.\n", MacValue, MacValue, NextDiff)); + return; + } + + if (pEntry->P2pInfo.NoADesc[0].bInAwake == TRUE) + { + pEntry->P2pInfo.NoADesc[0].bInAwake = FALSE; + pP2PCtrl->bKeepSlient = TRUE; + pP2PCtrl->bPreKeepSlient = TRUE; + DBGPRINT(RT_DEBUG_TRACE,("Enter Absence now ======> %d\n", pP2PCtrl->bKeepSlient)); + } + else + { + pEntry->P2pInfo.NoADesc[0].bInAwake = TRUE; + pP2PCtrl->bKeepSlient = FALSE; + pP2PCtrl->bPreKeepSlient = FALSE; + if (IS_SW_NOA_TIMER(pAd) + && (pP2PCtrl->GONoASchedule.Count > 100)) + { + if (TRUE == P2pAdjustSwNoATimer(pAd, Value, SavedNextTargetTimePoint)) + { + /*DBGPRINT(RT_DEBUG_TRACE,("SwBasedNoA : Dequeue here. %d\n", pAd->TxSwNoAMgmtQueue.Number));*/ + /*RTMPDeQueueNoAMgmtPacket(pAd);*/ + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } + } + else + { + /*RTMPDeQueueNoAMgmtPacket(pAd);*/ + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } + DBGPRINT(RT_DEBUG_TRACE,("Enter Awake now ======= %d\n", pAd->P2pCfg.bKeepSlient)); + + } + + } + + } + +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID P2pPauseBssSync( + IN PRTMP_ADAPTER pAd) +{ + /*BCN_TIME_CFG_STRUC csr;*/ + + DBGPRINT(RT_DEBUG_TRACE, ("--->P2pPauseBssSync %s\n", decodeP2PState(pAd->P2pCfg.P2PConnectState))); + AsicDisableSync(pAd); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID P2pResumeBssSync( + IN PRTMP_ADAPTER pAd) +{ + /*BCN_TIME_CFG_STRUC csr;*/ + + DBGPRINT(RT_DEBUG_TRACE, ("--->P2pResumeBssSync %s\n", decodeP2PState(pAd->P2pCfg.P2PConnectState))); + AsicEnableP2PGoSync(pAd); +} + +/* + ========================================================================== + Description: + OppPS CTWindows timer. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2PCTWindowTimer( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext; + PRT_P2P_CONFIG pP2pCtrl = &pAd->P2pCfg; + + if (P2P_TEST_BIT(pP2pCtrl->CTWindows, P2P_OPPS_BIT)) + pP2pCtrl->bKeepSlient = TRUE; +} + +/* + ========================================================================== + Description: + Before reinvoke a persistent group, copy persistent parameter to pAd->P2pCfg.. + + Parameters: + Perstindex : the index for entry in Persistent Table. + Note: + + ========================================================================== + */ +VOID P2pCopyPerstParmToCfg( + IN PRTMP_ADAPTER pAd, + IN UCHAR Perstindex) +{ + +} + +/* + ========================================================================== + Description: + Get Random SSID "DIRECT-xx" + + Parameters: + pSSID : output SSID + pSSIDLen : Length of pSSID + Note: + + ========================================================================== + */ +VOID P2pGetRandomSSID( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pSSID, + OUT PUCHAR pSSIDLen) +{ + UCHAR tmp[52]; + UCHAR i; + //gen a-z , A-Z tmp array! + for(i=0 ; i < 26 ; i++) + { + tmp[i]='a'+i; + tmp[i+26]='A'+i; + } + + NdisMoveMemory(pSSID, "DIRECT-", 7); + pSSID[7] = tmp[RandomByte(pAd)%52]; + pSSID[8] = tmp[RandomByte(pAd)%52]; + NdisMoveMemory((pSSID + 9), pAd->P2pCfg.DeviceName, pAd->P2pCfg.DeviceNameLen); + (*pSSIDLen) = 9 + pAd->P2pCfg.DeviceNameLen; +} + +/* + ========================================================================== + Description: + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pSetListenIntBias( + IN PRTMP_ADAPTER pAd, + IN UCHAR Bias) +{ + pAd->P2pCfg.P2pCounter.ListenIntervalBias = Bias; + if (INFRA_ON(pAd)) + pAd->P2pCfg.P2pCounter.ListenIntervalBias = 1; +} + + +/* + ========================================================================== + Description: + The routine that decide my Rule as GO or Client? + And then do necessary setting : update channel, Bssid, SSID etc. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pSetRule( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index, + IN PUCHAR PeerBssid, + IN UCHAR PeerGOIntentAttri, + IN UCHAR Channel) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PRT_P2P_CLIENT_ENTRY pP2pEntry = &pAd->P2pTable.Client[Index]; + UCHAR RealIntent; + USHORT PeerWscMethod; + + DBGPRINT(RT_DEBUG_ERROR, (" P2pSetRule - Channel = %d. GoIntent = %x\n", Channel, PeerGOIntentAttri)); + RealIntent = PeerGOIntentAttri>>1; + if (RealIntent > pP2PCtrl->GoIntentIdx) + { + pP2pEntry->Rule = P2P_IS_GO; + pP2pEntry->GoIntent = RealIntent; + /* Use peer addr as bssid */ + RTMPMoveMemory(pP2PCtrl->PortCfg.Bssid, PeerBssid, MAC_ADDR_LEN); + RTMPMoveMemory(pP2PCtrl->Bssid, PeerBssid, MAC_ADDR_LEN); + RTMPMoveMemory(pP2PCtrl->SSID, pP2pEntry->Ssid, 32); + pP2PCtrl->SSIDLen = pP2pEntry->SsidLen; + pP2PCtrl->P2PConnectState = P2P_ANY_IN_FORMATION_AS_CLIENT; + + /* + The Operating Channel attribute may be present in the P2P IE. + If Channel is 0, use self configuration. + */ + if (Channel != 0) + pP2PCtrl->GroupOpChannel = Channel; + else + pP2PCtrl->GroupOpChannel = pP2PCtrl->GroupChannel; + + /* Update My WPS Mode. */ + P2P_SetWscRule(pAd, Index, &PeerWscMethod); + DBGPRINT(RT_DEBUG_ERROR, (" P2P - I become Internal Enrollee!! Enrollee. !! GOGOGO\n")); + DBGPRINT(RT_DEBUG_ERROR, (" P2P - I become Internal Enrollee!! Enrollee. !! GOGOGO\n")); + } + else if (RealIntent < pP2PCtrl->GoIntentIdx) + { + pP2pEntry->Rule = P2P_IS_CLIENT; + pP2pEntry->GoIntent = RealIntent; + /* Use my addr as bssid */ + RTMPMoveMemory(pP2PCtrl->Bssid, pP2PCtrl->CurrentAddress, MAC_ADDR_LEN); + RTMPMoveMemory(pP2PCtrl->PortCfg.Bssid, pP2PCtrl->CurrentAddress, MAC_ADDR_LEN); + pP2PCtrl->P2PConnectState = P2P_ANY_IN_FORMATION_AS_GO; + pP2PCtrl->GroupOpChannel = pP2PCtrl->GroupChannel; + + /* Update My WPS Config Method. */ + P2P_SetWscRule(pAd, Index, &PeerWscMethod); + DBGPRINT(RT_DEBUG_ERROR, (" P2P - MyIntent = %d, PeerIntent = %d\n", pP2PCtrl->GoIntentIdx, RealIntent)); + DBGPRINT(RT_DEBUG_ERROR, (" P2P - I become Internal REGISTRA!! REGISTRA. !! GOGOGO\n")); + DBGPRINT(RT_DEBUG_ERROR, (" P2P - I become Internal REGISTRA!! REGISTRA. !! GOGOGO\n")); + } + else if (((PeerGOIntentAttri&1) == 1) && (RealIntent == pP2PCtrl->GoIntentIdx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("P2pSetRule Peer Tie Breaker bit is On. %x \n", RealIntent)); + pP2pEntry->Rule = P2P_IS_GO; + pP2pEntry->GoIntent = RealIntent; + /* Use peer addr as bssid */ + RTMPMoveMemory(pP2PCtrl->PortCfg.Bssid, PeerBssid, MAC_ADDR_LEN); + RTMPMoveMemory(pP2PCtrl->Bssid, PeerBssid, MAC_ADDR_LEN); + RTMPMoveMemory(pP2PCtrl->SSID, pP2pEntry->Ssid, 32); + pP2PCtrl->SSIDLen = pP2pEntry->SsidLen; + pP2PCtrl->P2PConnectState = P2P_ANY_IN_FORMATION_AS_CLIENT; + /* + The Operating Channel attribute may be present in the P2P IE. + If Channel is 0, use self configuration. + */ + if (Channel != 0) + pP2PCtrl->GroupOpChannel = Channel; + else + pP2PCtrl->GroupOpChannel = pP2PCtrl->GroupChannel; + + /* Update My WPS Config Method. */ + P2P_SetWscRule(pAd, Index, &PeerWscMethod); + DBGPRINT(RT_DEBUG_ERROR, (" P2P - I become Internal Enrollee!! Enrollee. !! GOGOGO\n")); + DBGPRINT(RT_DEBUG_ERROR, (" P2P - I become Internal Enrollee!! Enrollee. !! GOGOGO\n")); + } + else if (((PeerGOIntentAttri & 0x1) == 0) && (RealIntent == pP2PCtrl->GoIntentIdx)) + { + DBGPRINT(RT_DEBUG_ERROR, ("P2pSetRule Peer Tie Breaker bit is Off. %x \n", RealIntent)); + pP2pEntry->Rule = P2P_IS_CLIENT; + pP2pEntry->GoIntent = RealIntent; + /* Use my addr as bssid */ + RTMPMoveMemory(pP2PCtrl->Bssid, pP2PCtrl->CurrentAddress, MAC_ADDR_LEN); + RTMPMoveMemory(pP2PCtrl->PortCfg.Bssid, pP2PCtrl->CurrentAddress, MAC_ADDR_LEN); + pP2PCtrl->P2PConnectState = P2P_ANY_IN_FORMATION_AS_GO; + pP2PCtrl->GroupOpChannel = pP2PCtrl->GroupChannel; + + /* Update My WPS Config Method. */ + P2P_SetWscRule(pAd, Index, &PeerWscMethod); + DBGPRINT(RT_DEBUG_ERROR, (" P2P - I become Internal REGISTRA!! REGISTRA. !! GOGOGO\n")); + DBGPRINT(RT_DEBUG_ERROR, (" P2P - I become Internal REGISTRA!! REGISTRA. !! GOGOGO\n")); + } + + DBGPRINT(RT_DEBUG_ERROR, ("P2pSetRule pPort Bssid = %02x %02x %02x %02x %02x %02x \n", pP2PCtrl->PortCfg.Bssid[0], pP2PCtrl->PortCfg.Bssid[1],pP2PCtrl->PortCfg.Bssid[2],pP2PCtrl->PortCfg.Bssid[3],pP2PCtrl->PortCfg.Bssid[4],pP2PCtrl->PortCfg.Bssid[5])); + DBGPRINT(RT_DEBUG_ERROR, ("GroupOpChannel = %d \n",pP2PCtrl->GroupOpChannel)); + DBGPRINT(RT_DEBUG_ERROR, (" P2pSetRule - pP2pEntry->Rule = %s. \n", decodeMyRule(pP2pEntry->Rule))); + +} + +/* + ========================================================================== + Description: + Start Provisionint process. Send out Provision Discovery Request frame. + + Parameters: + Note: + + ========================================================================== + */ +BOOLEAN P2pProvision( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr) +{ + UCHAR p2pindex, Channel; + + DBGPRINT(RT_DEBUG_ERROR, ("P2pProvision = %02x:%02x:%02x:%02x:%02x:%02x. \n", PRINT_MAC(Addr))); + p2pindex = P2pGroupTabSearch(pAd, Addr); + if (p2pindex < MAX_P2P_GROUP_SIZE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Start P2pProvision = %02x:%02x:%02x:%02x:%02x:%02x. \n", PRINT_MAC(Addr))); + pAd->P2pTable.Client[p2pindex].GeneralToken++; + pAd->P2pTable.Client[p2pindex].P2pClientState = P2PSTATE_PROVISION_COMMAND; + + /* Stop Scan and switch to peer's Listen Channel. */ + P2pStopScan(pAd); + Channel = pAd->P2pTable.Client[p2pindex].ListenChannel; + AsicSwitchChannel(pAd, Channel, FALSE); + AsicLockChannel(pAd, Channel); + pAd->P2pCfg.DiscCurrentState = P2P_DISC_SEARCH; + COPY_MAC_ADDR(pAd->P2pCfg.ConnectingMAC, pAd->P2pTable.Client[p2pindex].addr); + return TRUE; + } + return FALSE; + +} + + +/* + ========================================================================== + Description: + Connect to Addr. Include all "Connect" cenario. GO_nego, invite, etc. Addr might be P2P GO, or a P2P Device. + + Parameters: + Note: + + ========================================================================== + */ +BOOLEAN P2pConnect( + IN PRTMP_ADAPTER pAd) +{ + UCHAR Channel, p2pIdx; + + /* Stop Scan and switch to peer's Listen Channel. */ + P2pStopScan(pAd); + p2pIdx = P2pGroupTabSearch(pAd, pAd->P2pCfg.ConnectingMAC); + if (p2pIdx >= MAX_P2P_GROUP_SIZE) + return FALSE; + + Channel = pAd->P2pTable.Client[p2pIdx].ListenChannel; + if (Channel == 0) + Channel = 1; + AsicSwitchChannel(pAd, Channel, FALSE); + AsicLockChannel(pAd, Channel); + pAd->P2pCfg.DiscCurrentState = P2P_DISC_SEARCH; + + DBGPRINT(RT_DEBUG_ERROR, ("P2pConnect = \n")); + DBGPRINT(RT_DEBUG_ERROR, ("Addr = %02x:%02x:%02x:%02x:%02x:%02x. \n", PRINT_MAC(pAd->P2pCfg.ConnectingMAC))); + DBGPRINT(RT_DEBUG_ERROR, ("ListenChannel = %d\n", Channel)); + + return TRUE; +} + +VOID P2pConnectPrepare( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr, + IN UINT32 ConnType) +{ + UCHAR Channel, p2pindex; + + p2pindex = P2pGroupTabSearch(pAd, Addr); + if (p2pindex < MAX_P2P_GROUP_SIZE) + { + pAd->P2pCfg.bConfirmByUI = TRUE; + /* Stop Scan and switch to peer's Listen Channel. */ + P2pStopScan(pAd); + OS_WAIT(200); + + pAd->P2pCfg.bPeriodicListen = FALSE; + + if ((pAd->P2pTable.Client[p2pindex].P2pClientState == P2PSTATE_DISCOVERY_GO)) + Channel = pAd->P2pTable.Client[p2pindex].OpChannel; + else + Channel = pAd->P2pTable.Client[p2pindex].ListenChannel; + + if (INFRA_ON(pAd) || P2P_GO_ON(pAd)) + { + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + UCHAR BBPValue = 0; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + } + } + + AsicSwitchChannel(pAd, Channel, FALSE); + AsicLockChannel(pAd, Channel); + + /* Copy pEntry MAC Address in ConnectinfMAC. */ + pAd->P2pCfg.ConnectingIndex = 0; + COPY_MAC_ADDR(pAd->P2pCfg.ConnectingMAC, pAd->P2pTable.Client[p2pindex].addr); + + /* Set Connecting Timer for Periodic Timer use. */ + pAd->P2pTable.Client[p2pindex].StateCount = 0; + pAd->P2pTable.Client[p2pindex].bValid = TRUE; + + /* Set pEntry Client Status. */ + if ((pAd->P2pTable.Client[p2pindex].P2pClientState == P2PSTATE_DISCOVERY_GO)) + { + COPY_MAC_ADDR(pAd->P2pCfg.ConnectingMAC, pAd->P2pTable.Client[p2pindex].bssid); + pAd->P2pTable.Client[p2pindex].P2pClientState = P2PSTATE_PROVISION_COMMAND; + } + else + pAd->P2pTable.Client[p2pindex].P2pClientState = ConnType; + + DBGPRINT(RT_DEBUG_ERROR, ("P2P Connect Command Type = %s\n", decodeP2PClientState(ConnType))); + P2PPrintP2PEntry(pAd, p2pindex); + + /* Change Discovery State Machine State. */ + pAd->P2pCfg.DiscCurrentState = P2P_DISC_SEARCH; + pAd->P2pCfg.GoFormCurrentState = P2P_GO_FORM_IDLE; + } +} + +/* + ========================================================================== + Description: + Ready to connect to Addr. Include all "Connect" cenario. GO_nego, invite, etc. Addr might be P2P GO, or a P2P Device. + + Parameters: + Note: + + ========================================================================== + */ +BOOLEAN P2pConnectAfterScan( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bBeacon, + IN UCHAR idx) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + BOOLEAN brc = TRUE; + UCHAR index;/*, i; */ + UCHAR GrpIndex = idx; + BOOLEAN bAction = FALSE; + + DBGPRINT(RT_DEBUG_ERROR, (" P2pConnectAfterScan %d. %s \n", pAd->P2pTable.Client[idx].P2pClientState, decodeP2PClientState(pAd->P2pTable.Client[idx].P2pClientState))); + DBGPRINT(RT_DEBUG_ERROR, (" GroupOpChannel = %d \n", pP2PCtrl->GroupOpChannel)); + + if (GrpIndex >= MAX_P2P_GROUP_SIZE) + { + DBGPRINT(RT_DEBUG_TRACE, ("P2pConnectAfterScan Check - Reach Device Limit. return. \n")); + return FALSE; + } + + /* + peer is a P2P GO. + Peer is a P2P Device. Need to have Go Nego procedure first. + Or can reinvoke a persistent + */ + if (pAd->P2pTable.Client[GrpIndex].P2pClientState == P2PSTATE_DISCOVERY) + { + /* Decide connect method when I am in Connect_Idle state. This means I am a P2P Device. */ + if (P2P_CLI_ON(pAd) || (P2P_GO_ON(pAd))) + { + /* Invite Case 1 */ + pAd->P2pTable.Client[GrpIndex].P2pClientState = P2PSTATE_INVITE_COMMAND; + DBGPRINT(RT_DEBUG_TRACE, (" P2pConnectAfterScan - Use Invite %d.\n", GrpIndex)); + bAction = TRUE; + } + else if (IS_P2P_CONNECT_IDLE(pAd)) + { + index = P2pPerstTabSearch(pAd, pAd->P2pTable.Client[GrpIndex].addr, + pAd->P2pTable.Client[GrpIndex].bssid, + pAd->P2pTable.Client[GrpIndex].InterfaceAddr); + DBGPRINT(RT_DEBUG_ERROR, (" P2pConnectAfterScan - Perst index %d. \n", index)); + DBGPRINT(RT_DEBUG_ERROR, (" P2pConnectAfterScan - EnablePresistent %d. \n", + pP2PCtrl->P2pControl.field.EnablePresistent)); + if ((index < MAX_P2P_TABLE_SIZE) && IS_PERSISTENT_ON(pAd)) + { + /* Invite Case 3: */ + pAd->P2pTable.Client[GrpIndex].P2pClientState = P2PSTATE_INVITE_COMMAND; + DBGPRINT(RT_DEBUG_ERROR, (" P2pConnectAfterScan - Use reinvoke Invite %d. \n", index)); + bAction = TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, (" P2pConnectAfterScan - Start From Group Forming \n")); + + /* Start Scan and Then go to Group Forming process. */ + pAd->P2pTable.Client[idx].P2pClientState = P2PSTATE_CONNECT_COMMAND; + bAction = TRUE; + } + } + if (bAction == TRUE) + { + /* Now only support connect to ONE. So set ConnectingIndex to MAX_P2P_GROUP_SIZE to stop connect further MAC. */ + P2pConnectAction(pAd, bBeacon, idx); + } + } + else if ((pAd->P2pTable.Client[GrpIndex].P2pClientState == P2PSTATE_DISCOVERY_GO)) + { + DBGPRINT(RT_DEBUG_TRACE, (" case 1 = peer is go \n")); + P2pStopConnectThis(pAd); + brc = P2pConnectP2pGo(pAd, GrpIndex); + } + /* peer is a P2P client in a P2P Group. */ + else if ((pAd->P2pTable.Client[GrpIndex].P2pClientState == P2PSTATE_DISCOVERY_CLIENT)) + { + DBGPRINT(RT_DEBUG_TRACE, (" case 2 = peer is client \n")); + P2pStopConnectThis(pAd); + P2pConnectP2pClient(pAd,GrpIndex); + } + else + DBGPRINT(RT_DEBUG_TRACE, (" P2pConnectAfterScan - Peer state %s \n", + decodeP2PClientState(pAd->P2pTable.Client[GrpIndex].P2pClientState))); + + return brc; +} + +/* + ========================================================================== + Description: + Prepare to connect to Connecting MAC. ConnectingMAC might contain several MAC address that I can connect to One after one. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pConnectAction( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bBeacon, + IN UCHAR index) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + BOOLEAN bresult = FALSE; + UCHAR perstindex; + + DBGPRINT(RT_DEBUG_ERROR, (" P2pConnectAction %d. %s \n", pAd->P2pTable.Client[index].P2pClientState, decodeP2PClientState(pAd->P2pTable.Client[index].P2pClientState))); + + if (bBeacon == TRUE) + { + DBGPRINT(RT_DEBUG_ERROR, (" P2pConnectAction from bBeacon \n")); + /* Check If ever have a command to connect to this peer. */ + if (pAd->P2pTable.Client[index].P2pClientState == P2PSTATE_CONNECT_COMMAND + ||(pAd->P2pTable.Client[index].P2pClientState == P2PSTATE_INVITE_COMMAND)) + { + pP2PCtrl->P2PConnectState = P2P_ANY_IN_FORMATION_AS_CLIENT; + P2pGoNegoDone(pAd, &pAd->P2pTable.Client[index]); + } + else if (pAd->P2pTable.Client[index].P2pClientState == P2PSTATE_GO_DISCO_COMMAND) + { + bresult = P2pClientDiscovery(pAd, pAd->P2pTable.Client[index].addr, index); + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR, (" P2pConnectAction not from bBeacon \n")); + if ((pAd->P2pTable.Client[index].P2pClientState == P2PSTATE_CONNECT_COMMAND) + || (pAd->P2pTable.Client[index].P2pClientState == P2PSTATE_INVITE_COMMAND)) + { + /* The check sequence must be the same as in where we set P2PSTATE_INVITE_COMMAND in P2PConnect() */ + if ((P2P_GO_ON(pAd)) || (P2P_CLI_ON(pAd))) + { + DBGPRINT(RT_DEBUG_TRACE, (" case 1 \n")); + /* Invite Case 1 : I am Auto GO to invite a P2P Device or when I am P2P Client */ + bresult = P2pInvite(pAd, pAd->P2pTable.Client[index].addr, MAX_P2P_TABLE_SIZE, index); + } + else if (pAd->P2pTable.Client[index].Rule == P2P_IS_GO) + { + + DBGPRINT(RT_DEBUG_TRACE, (" case 2 \n")); + /* directly associate to GO. */ + pP2PCtrl->P2PConnectState = P2P_ANY_IN_FORMATION_AS_CLIENT; + P2pGoNegoDone(pAd, &pAd->P2pTable.Client[index]); + } + else if (IS_P2P_CONNECT_IDLE(pAd)) + { + UCHAR Channel; + P2P_CMD_STRUCT P2pCmd; + UCHAR ClientState = pAd->P2pTable.Client[index].P2pClientState; + DBGPRINT(RT_DEBUG_ERROR, (" case 3 \n")); + /* since I am idle, */ + perstindex = P2pPerstTabSearch(pAd, pAd->P2pTable.Client[index].addr, + pAd->P2pTable.Client[index].bssid, + pAd->P2pTable.Client[index].InterfaceAddr); + if ((perstindex < MAX_P2P_TABLE_SIZE) && (IS_PERSISTENT_ON(pAd))) + { + /* + I have credential, my persistent is enabled, peer 's persistent is enabled. + So use Reinvoke method to start P2P group. + Stop Scan and switch to peer's Listen Channel. + */ + P2pStopScan(pAd); + Channel = pAd->P2pTable.Client[index].ListenChannel; + AsicSwitchChannel(pAd, Channel, FALSE); + AsicLockChannel(pAd, Channel); + + ClientState = P2PSTATE_INVITE_COMMAND; + pAd->P2pCfg.P2PConnectState = P2P_CONNECT_IDLE; + } + else + { + ClientState = P2PSTATE_CONNECT_COMMAND; + } + COPY_MAC_ADDR(&P2pCmd.Addr[0], pAd->P2pTable.Client[index].addr); + P2pCmd.Idx = index; + MlmeEnqueue(pAd, P2P_GO_FORM_STATE_MACHINE, P2P_START_COMMUNICATE_CMD_EVT, sizeof(P2P_CMD_STRUCT), &P2pCmd, ClientState); + RTMP_MLME_HANDLER(pAd); + } + else + DBGPRINT(RT_DEBUG_TRACE, (" case 4 ?????? \n")); + if (bresult == TRUE) + { + /* do nothing */ + } + } + + } + pP2PCtrl->P2pCounter.GoScanBeginCounter100ms = 0; +} + + +/* + ========================================================================== + Description: + Connect to Addr. Addr is already in a P2P Group. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pConnectP2pClient( + IN PRTMP_ADAPTER pAd, + IN UCHAR GrpIndex) +{ + BOOLEAN bGoToScan = FALSE; + UCHAR GoP2pIndex; + + DBGPRINT(RT_DEBUG_TRACE, ("P2pConnect to P2pClient====>. \n")); + + /* Decide connect method when I am in COnnect_Idle state. This means I am a P2P Device. */ + if (IS_P2P_CONNECT_IDLE(pAd)) + { + GoP2pIndex = pAd->P2pTable.Client[GrpIndex].MyGOIndex; + if ((pAd->P2pTable.Client[GrpIndex].DevCapability & DEVCAP_CLIENT_DISCOVER) == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("P2P Client Not support Discoverability %x \n", pAd->P2pTable.Client[GrpIndex].DevCapability)); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("P2P Client CAN Support Discoverability %x \n", pAd->P2pTable.Client[GrpIndex].DevCapability)); + + DBGPRINT(RT_DEBUG_TRACE, ("P2P Client DevCapability %x. GoP2pIndex = %d. \n", pAd->P2pTable.Client[GrpIndex].DevCapability, GoP2pIndex)); + if ((GoP2pIndex < MAX_P2P_GROUP_SIZE) && (pAd->P2pTable.Client[GoP2pIndex].P2pClientState == P2PSTATE_DISCOVERY_GO)) + { + pAd->P2pTable.Client[GrpIndex].P2pClientState = P2PSTATE_CLIENT_DISCO_COMMAND; + pAd->P2pTable.Client[GoP2pIndex].P2pClientState = P2PSTATE_GO_DISCO_COMMAND; + DBGPRINT(RT_DEBUG_TRACE,("P2P GrpIndex %d . GoP2pIndex = %d\n", GrpIndex, GoP2pIndex)); + bGoToScan = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, (" P2pConnectIdle - peer device's state %s \n", decodeP2PClientState(pAd->P2pTable.Client[GrpIndex].P2pClientState))); + } + + if (bGoToScan == TRUE) + { + P2pSetListenIntBias(pAd, 12); + pAd->P2pCfg.P2pCounter.CounterAftrScanButton = 0; + P2pGotoScan(pAd); + } + +} + +/* + ========================================================================== + Description: + Connect to Addr. Addr is already in a P2P Group. + + Parameters: + Note: + + ========================================================================== + */ +BOOLEAN P2pConnectP2pGo( + IN PRTMP_ADAPTER pAd, + IN UCHAR idx) +{ + BOOLEAN brc = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("P2pConnectP2pGo. %s\n", decodeP2PState(pAd->P2pCfg.P2PConnectState))); + DBGPRINT(RT_DEBUG_TRACE, ("pAd->P2pCfg.Dpid = %d \n", pAd->P2pCfg.Dpid)); + /* Decide connect method when I am in COnnect_Idle state. This means I am a P2P Device. */ + if (P2P_GO_ON(pAd)) + return brc; + + if (pAd->P2pCfg.P2PConnectState == P2P_CONNECT_IDLE) + { + pAd->P2pTable.Client[idx].P2pClientState = P2PSTATE_PROVISION_COMMAND; + DBGPRINT(RT_DEBUG_TRACE,("P2p : Use Provision first before connecting to GO with Bssid %x. %x. %x. %x. %x. %x. \n", pAd->P2pTable.Client[idx].bssid[0], pAd->P2pTable.Client[idx].bssid[1],pAd->P2pTable.Client[idx].bssid[2],pAd->P2pTable.Client[idx].bssid[3],pAd->P2pTable.Client[idx].bssid[4],pAd->P2pTable.Client[idx].bssid[5])); + DBGPRINT(RT_DEBUG_TRACE,("P2p : its GroupCapability= %x. DevCapability= %x. \n", pAd->P2pTable.Client[idx].GroupCapability, pAd->P2pTable.Client[idx].DevCapability)); + brc = TRUE; + } + else if (P2P_CLI_ON(pAd)) + { + } + else + DBGPRINT(RT_DEBUG_ERROR, ("invalid P2pConnectP2pGo command when %s \n", decodeP2PState(pAd->P2pCfg.P2PConnectState))); + + return brc; + +} + +/* + ========================================================================== + Description: + Try to connect to a P2P Client. So Use Client discovery first. CLient Discvoery frame is + forwarded by the help of GO. + + Parameters: + P2pTabIdx is GO's index in P2P table. + Note: + + ========================================================================== + */ +BOOLEAN P2pClientDiscovery( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr, + IN UCHAR GoP2pTabIdx) +{ + UCHAR ClientP2PIndex = P2P_NOT_FOUND; + UCHAR i; + ULONG TotalFrameLen; + + DBGPRINT(RT_DEBUG_ERROR, ("P2pClientDiscovery %d\n", GoP2pTabIdx)); + if (GoP2pTabIdx >= MAX_P2P_GROUP_SIZE) + return FALSE; + + /* Search what is the P2P client that I was about to ask it's existence. */ + for (i = 0; i < MAX_P2P_GROUP_SIZE;i++) + { + if (pAd->P2pTable.Client[i].P2pClientState == P2PSTATE_CLIENT_DISCO_COMMAND) + ClientP2PIndex = i; + } + DBGPRINT(RT_DEBUG_ERROR, ("P2pClientDiscovery. ClientP2PIndex= %d\n", ClientP2PIndex)); + if (ClientP2PIndex == P2P_NOT_FOUND) + return FALSE; + + P2PSendDevDisReq(pAd, pAd->P2pTable.Client[GoP2pTabIdx].addr, pAd->P2pTable.Client[GoP2pTabIdx].addr, pAd->P2pTable.Client[ClientP2PIndex].addr, &TotalFrameLen); + if (TotalFrameLen > 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("P2pClientDiscovery. ClientP2PIndex = %d\n", ClientP2PIndex)); + return TRUE; + } + else + return FALSE; + +} + +/* + ========================================================================== + Description: + Invite can be used for reinvoke persistent entry or just to connect to an P2P client. So + Has 2 index for those choices. Only one is used. + invitation procedure is an optional procedure used for the following : + 1. A P2P group owner inviting a P2P Device to become a P2P Client in its P2P Group. + 2. A P2P client invitin another P2P Device to join the P2P Group of which the P2P Client is a member + because it wished to use some service of the P2P Device. + 3. Requesting to invoke a Persistent P2P Group for which both P2P Devices have previouslt been provisioned. + + Parameters: + Note: + + ========================================================================== + */ +BOOLEAN P2pInviteAsRule( + IN PRTMP_ADAPTER pAd, + IN UCHAR MyRule, + IN UCHAR P2pTabIdx) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + RT_P2P_CLIENT_ENTRY *pClient; + ULONG FrameLen; + + /* Reflash this flag on the next Invitation or DPID setting. */ + DBGPRINT(RT_DEBUG_TRACE, ("P2pInviteAsRule MyRule = %d. P2pTabIdx= %d \n", MyRule, P2pTabIdx)); + pClient = &pAd->P2pTable.Client[P2pTabIdx]; + P2PMakeInviteReq(pAd, MyRule, 0, pClient->addr, pP2PCtrl->CurrentAddress, &FrameLen); + + DBGPRINT(RT_DEBUG_TRACE, ("P2pInviteAsRule FrameLen = %ld. \n", FrameLen)); + if (FrameLen > 0) + return TRUE; + + return FALSE; + +} + +/* + ========================================================================== + Description: + Invite can be used for reinvoke persistent entry or just to connect to an P2P client. So + Has 2 index for those choices. Only one is used. + invitation procedure is an optional procedure used for the following : + 1. A P2P group owner inviting a P2P Device to become a P2P Client in its P2P Group. + 2. A P2P client invitin another P2P Device to join the P2P Group of which the P2P Client is a member + because it wished to use some service of the P2P Device. + 3. Requesting to invoke a Persistent P2P Group for which both P2P Devices have previouslt been provisioned. + + Parameters: + Note: + + ========================================================================== + */ +BOOLEAN P2pInvite( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr, + IN UCHAR PersistentTabIdx, + IN UCHAR P2pTabIdx) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + RT_P2P_PERSISTENT_ENTRY *pEntry; + RT_P2P_CLIENT_ENTRY *pClient; +/* UCHAR index; */ + ULONG FrameLen; + BOOLEAN brc = FALSE; + + /* Get one index that is valid to use during invitation procedure. */ + if (PersistentTabIdx < MAX_P2P_TABLE_SIZE) + { + /* those who can save to persistent table must also support persistent . So can use invite procedure now. */ + pEntry = &pAd->P2pTable.PerstEntry[PersistentTabIdx]; + if (P2pTabIdx < MAX_P2P_GROUP_SIZE) + { + pAd->P2pCfg.PhraseKeyLen = (UCHAR)pEntry->Profile.KeyLength; + RTMPMoveMemory(pAd->P2pCfg.PhraseKey, pEntry->Profile.Key, pEntry->Profile.KeyLength); + pClient = &pAd->P2pTable.Client[P2pTabIdx]; + RTMPMoveMemory(pAd->P2pCfg.SSID, pEntry->Profile.SSID.Ssid, 32); + pP2PCtrl->SSIDLen = (UCHAR)pEntry->Profile.SSID.SsidLength; + RTMPMoveMemory(pP2PCtrl->SSID, pEntry->Profile.SSID.Ssid, pP2PCtrl->SSIDLen); + + if (pEntry->MyRule == P2P_IS_CLIENT) + { + pClient->Rule = P2P_IS_GO; + pClient->P2pClientState = P2PSTATE_GO_WPS; + RTMPMoveMemory(pAd->P2pCfg.Bssid, pEntry->Addr, MAC_ADDR_LEN); + } + else + { + pClient->Rule = P2P_IS_CLIENT; + pClient->P2pClientState = P2PSTATE_CLIENT_WPS; + RTMPMoveMemory(pAd->P2pCfg.Bssid, pAd->CurrentAddress, MAC_ADDR_LEN); + } + P2PMakeInviteReq(pAd, pEntry->MyRule, P2P_INVITE_FLAG_REINVOKE, pEntry->Addr, pP2PCtrl->CurrentAddress, &FrameLen); + if (FrameLen > 0) + { + brc = TRUE; + pClient->P2pClientState = P2PSTATE_SENT_INVITE_REQ; + } + } + } + else if (P2pTabIdx < MAX_P2P_GROUP_SIZE) + { + if ((pAd->P2pTable.Client[P2pTabIdx].DevCapability & DEVCAP_INVITE) == DEVCAP_INVITE) + { + /*if (pP2PCtrl->PortSubtype == PORTSUBTYPE_P2PGO) */ + if (P2P_GO_ON(pAd)) + { + brc = P2pInviteAsRule(pAd, P2P_IS_GO, P2pTabIdx); + } + else if (P2P_CLI_ON(pAd)) + brc = P2pInviteAsRule(pAd, P2P_IS_CLIENT, P2pTabIdx); + + } + else + DBGPRINT(RT_DEBUG_TRACE, ("Peer doesn't support Invite. DevCapability = %x \n", pAd->P2pTable.Client[P2pTabIdx].DevCapability)); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("invalid P2pInvite command. %d %d \n", PersistentTabIdx, P2pTabIdx)); + + return brc; + +} + + + +/* + ========================================================================== + Description: + Start Group Formation Process. will send out Go Negociation Request frame. + + Parameters: + Note: + + ========================================================================== + */ +BOOLEAN P2pStartGroupForm( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr, + IN UCHAR idx) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + + /* Insert this candidate to p2p client table. */ + if (idx < MAX_P2P_GROUP_SIZE) + { + if ((pAd->P2pTable.Client[idx].P2pClientState == P2PSTATE_CONNECT_COMMAND)|| (pAd->P2pTable.Client[idx].P2pClientState == P2PSTATE_DISCOVERY)) + { + /* Reset Scan Counter to Zero . So Won't do Scan too sooon because group forming is started. */ + pAd->P2pCfg.P2pCounter.Counter100ms = 0; + if (IS_EXT_LISTEN_ON(pAd)) + { + pAd->P2pCfg.ExtListenInterval = P2P_EXT_LISTEN_INTERVAL; + pAd->P2pCfg.ExtListenPeriod = P2P_EXT_LISTEN_PERIOD; + } + + { + pP2PCtrl->P2PConnectState = P2P_ANY_IN_FORMATION_AS_CLIENT; + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Start GroupForm . \n", __FUNCTION__)); + /* allocate and send out ProbeRsp frame */ + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /* Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + return FALSE; + pAd->P2pTable.Client[idx].P2pClientState = P2PSTATE_SENT_GO_NEG_REQ; + pAd->P2pTable.Client[idx].StateCount = 0; + pAd->P2pTable.Client[idx].bValid = FALSE; + +#ifdef DPA_S + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_GROUP_OWNER_NEGOTIATION_START, NULL, NULL, 0); +#endif /* DPA_S */ + + /* Set as Client temporarily. Later when I get the GO Rsp, will update this based on correct Intent. */ + P2PMakeGoNegoReq(pAd, idx, Addr, pOutBuffer, &FrameLen); + pP2PCtrl->bP2pReSendTimerRunning = TRUE; + RTMPSetTimer(&pP2PCtrl->P2pReSendTimer, P2P_TRANSMIT_TIMER); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_ERROR, (" P2P - Make GO Negociation Req FrameLen = %ld. \n", FrameLen)); + } + /* Once dwell in a listen and start group formation process, should stop scan right away. */ + return TRUE; + } + } + + return FALSE; + +} + +/* + ========================================================================== + Description: + Check if the addr is in my MAC wish list if any. + + Parameters: + Note: + + ========================================================================== + */ +BOOLEAN P2PDeviceMatch( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr, + IN PUCHAR DeviceName, + IN ULONG DeviceNameLen) +{ + UCHAR i; + UCHAR *ptr; + + ptr = &pAd->P2pCfg.ConnectingMAC[0]; + return TRUE; + + if (NdisEqualMemory(Addr, ZERO_MAC_ADDR, 6)) + return FALSE; + + /* If didn't assign MAC connecting wish list, allow all and return TRUE. */ + if (NdisEqualMemory(pAd->P2pCfg.ConnectingMAC, ZERO_MAC_ADDR, 6)) + return TRUE; + + for (i = 0;iP2pCfg.P2PConnectState))); + return FALSE; + +} + +/* + ========================================================================== + Description: + Set WPS related parameters + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pSetWps( + IN PRTMP_ADAPTER pAd, + IN PRT_P2P_CLIENT_ENTRY pP2pEntry) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + /*BOOLEAN Cancelled;*/ + BOOLEAN bChangeInitBW = FALSE; + PAPCLI_STRUCT pApCliEntry = NULL; + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: ==> P2P Connect State = %d. %s.\n", + __FUNCTION__, pP2PCtrl->P2PConnectState, decodeP2PState(pP2PCtrl->P2PConnectState))); + + P2pStopConnectThis(pAd); /* clean Connecting MAC Address. */ + P2pStopScan(pAd); + pObj->ioctl_if_type = INT_P2P; + pP2PCtrl->bConfirmByUI = FALSE; + if ((pP2PCtrl->Rule == P2P_IS_GO) && (P2P_GO_ON(pAd))) + { + PWSC_CTRL pWscControl = &pAd->ApCfg.MBSSID[0].WscControl; + + /* Set Channel. */ + DBGPRINT(RT_DEBUG_ERROR, ("(%d, %d)\n", pAd->LatchRfRegs.Channel != pP2PCtrl->GroupChannel)); + if (pAd->LatchRfRegs.Channel != pP2PCtrl->GroupChannel) + bChangeInitBW = TRUE; + else + { + pApCliEntry = &pAd->ApCfg.ApCliTab[BSS0]; + + if (!INFRA_ON(pAd)&& !P2P_GO_ON(pAd) && (pApCliEntry->Valid == FALSE)) + bChangeInitBW = TRUE; + else + { + if (INFRA_ON(pAd) || P2P_GO_ON(pAd)) + { + if ((pAd->CommonCfg.BBPCurrentBW == BW_40) && (pAd->LatchRfRegs.Channel != pAd->CommonCfg.CentralChannel)) + bChangeInitBW = TRUE; + } + } + } + + if (bChangeInitBW == TRUE) + { + UINT32 Data = 0, macStatus; + UINT32 MTxCycle, MRxCycle; + UCHAR BBPValue = 0; + + /* 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; + } + + if (!INFRA_ON(pAd)) + { + pAd->CommonCfg.Channel = pP2PCtrl->GroupOpChannel; + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED + && pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + N_SetCenCh(pAd); + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + } + else + { + if ((pAd->CommonCfg.Channel != pAd->CommonCfg.CentralChannel) && (pAd->CommonCfg.BBPCurrentBW == BW_40)) + { + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + } + else + { + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + } + } + + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + UCHAR BBPValue = 0; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + BBPValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + } + + /* Enable MAC Tx/Rx */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Data); + Data |= 0x0C; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Data); + } + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Rule = %s. OpChannel = %d. CentralChannel = %d\n", + __FUNCTION__, decodeMyRule(pP2PCtrl->Rule), pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel)); + DBGPRINT(RT_DEBUG_ERROR, (" SSID[%d] = %s. BSSID = %02x:%02x:%02x:%02x:%02x:%02x.\n", + pP2PCtrl->SSIDLen, pP2PCtrl->SSID, PRINT_MAC(pP2PCtrl->CurrentAddress))); + pP2PCtrl->P2pCapability[1] |= GRPCAP_OWNER; + /* P2P GO up. */ + if (pWscControl->WscConfStatus == WSC_SCSTATE_CONFIGURED) + { + DBGPRINT(RT_DEBUG_ERROR, ("P2P_FIXED_MODE && WSC_SCSTATE_CONFIGURED\n")); + AsicBBPAdjust(pAd); + } + else + { + Set_P2p_OpMode_Proc(pAd, "1"); + } + + /* GO WPS trigger. */ + if (pP2PCtrl->WscMode == WSC_PIN_MODE) + { + if (pP2PCtrl->ConfigMethod == WSC_CONFMET_KEYPAD) + { + Set_AP_WscConfMode_Proc(pAd, "5"); /* Registrar / Enrollee */ + Set_AP_WscMode_Proc(pAd, "1"); /* PIN */ + /* note 2011-10-12 : only AutoGO need WscPinCode command */ + if ((!(pAd->flg_p2p_OpStatusFlags & P2P_FIXED_MODE)) || + (pP2PCtrl->bSigmaEnabled == TRUE)) + { + Set_AP_WscPinCode_Proc(pAd, pP2PCtrl->PinCode); + OS_WAIT(700); + } + Set_AP_WscGetConf_Proc(pAd, "1"); + } + else if (pP2PCtrl->ConfigMethod == WSC_CONFMET_DISPLAY) + { + Set_AP_WscConfMode_Proc(pAd, "5"); /* Registrar / Enrollee */ + Set_AP_WscMode_Proc(pAd, "1"); /* PIN */ + OS_WAIT(700); + Set_AP_WscGetConf_Proc(pAd, "1"); + } + } + else if (pP2PCtrl->WscMode == WSC_PBC_MODE) + { + Set_AP_WscConfMode_Proc(pAd, "5"); /* Registrar / Enrollee */ + Set_AP_WscMode_Proc(pAd, "2"); /* PBC */ + OS_WAIT(700); + Set_AP_WscGetConf_Proc(pAd, "1"); + } + RTMPSetTimer(&pAd->P2pCfg.P2pWscTimer, P2P_WSC_TIMER); + + } + else if ((pP2PCtrl->Rule == P2P_IS_CLIENT) && (P2P_CLI_ON(pAd))) + { + /* Set Channel. */ + pAd->CommonCfg.Channel = pP2PCtrl->GroupOpChannel; + /*N_SetCenCh(pAd); */ + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Rule = %s. OpChannel = %d. CentralChannel = %d\n", + __FUNCTION__, decodeMyRule(pP2PCtrl->Rule), pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel)); + DBGPRINT(RT_DEBUG_ERROR, (" SSID[%d] = %s. BSSID = %02x:%02x:%02x:%02x:%02x:%02x.\n", + pP2PCtrl->SSIDLen, pP2PCtrl->SSID, PRINT_MAC(pP2PCtrl->Bssid))); + + /* P2P CLIENT up. */ + Set_P2p_OpMode_Proc(pAd, "2"); + /* P2P AP-Client Enable. */ + Set_P2pCli_Enable_Proc(pAd, "1"); + + /* CLIENT WPS trigger. */ + if (pP2PCtrl->WscMode == WSC_PIN_MODE) + { + if (pP2PCtrl->ConfigMethod == WSC_CONFMET_KEYPAD) + { + Set_AP_WscConfMode_Proc(pAd, "1"); /* Enrollee */ + Set_AP_WscMode_Proc(pAd, "1"); /* PIN */ + Set_P2pCli_WscSsid_Proc(pAd, &pP2PCtrl->SSID[0]); + /* Need Enter PIN Code and trigger WPS. */ + Set_AP_WscPinCode_Proc(pAd, pP2PCtrl->PinCode); + Set_AP_WscGetConf_Proc(pAd, "1"); + } + else if (pP2PCtrl->ConfigMethod == WSC_CONFMET_DISPLAY) + { + Set_AP_WscConfMode_Proc(pAd, "1"); /* Enrollee */ + Set_AP_WscMode_Proc(pAd, "1"); /* PIN */ + Set_P2pCli_Ssid_Proc(pAd, &pP2PCtrl->SSID[0]); + Set_AP_WscGetConf_Proc(pAd, "1"); + } + /*COPY_MAC_ADDR(pAd->ApCfg.ApCliTab[0].CfgApCliBssid, pP2PCtrl->Bssid);*/ + } + else if (pP2PCtrl->WscMode == WSC_PBC_MODE) + { + Set_AP_WscConfMode_Proc(pAd, "1"); /* Enrollee */ + Set_AP_WscMode_Proc(pAd, "2"); /* PBC */ + Set_P2pCli_WscSsid_Proc(pAd, &pP2PCtrl->SSID[0]); + Set_AP_WscGetConf_Proc(pAd, "1"); + } + + RTMPSetTimer(&pAd->P2pCfg.P2pWscTimer, P2P_WSC_TIMER); + } +#ifdef DPA_S + //corey + //RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_WPS_START, NULL, NULL, 0); +#endif /* DPA_S */ +} + +/* + ========================================================================== + Description: + Call this function after a successful Go negociation. will do coreessponding action as GO or Client. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pGoNegoDone( + IN PRTMP_ADAPTER pAd, + IN PRT_P2P_CLIENT_ENTRY pP2pEntry) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + + if (pP2PCtrl->P2PConnectState == P2P_ANY_IN_FORMATION_AS_GO) + { + /* Set MyRule in P2P GroupFormat */ + pP2PCtrl->Rule = P2P_IS_GO; + pAd->flg_p2p_OpStatusFlags |= P2P_GO_UP; + P2pSetWps(pAd, pP2pEntry); + } + else if (pP2PCtrl->P2PConnectState == P2P_ANY_IN_FORMATION_AS_CLIENT) + { + DBGPRINT(RT_DEBUG_ERROR, ("pAd->P2pCfg.Dpid = %s \n", decodeDpid(pP2PCtrl->Dpid))); + /* Set MyRule in P2P GroupFormat */ + pP2PCtrl->Rule = P2P_IS_CLIENT; + pAd->flg_p2p_OpStatusFlags = P2P_CLI_UP; + + /* If WPS not triggered, don't so WPS AP now. Wait until P2PPRofile called */ + if (pP2PCtrl->Dpid != DEV_PASS_ID_NOSPEC) + { + /* Update Per client state */ + pP2pEntry->P2pClientState = P2PSTATE_GO_WPS; + /* Update Global State. Prepare to scan for GO beacon. So as to connect using WPS. */ + pP2PCtrl->P2PConnectState = P2P_DO_GO_SCAN_BEGIN; + pP2PCtrl->P2pCounter.Counter100ms = 0; + /* When Counter100ms reaches NextScanRound in P2P_DO_GO_NEG_DONE_CLIENT State, */ + /* Will start a site survey again. Because P2P GO start beacon after Go Negociation. */ + pP2PCtrl->P2pCounter.NextScanRound = 20 + pP2pEntry->ConfigTimeOut * 10; + /*pAd->StaCfg.WscControl.WscAPChannel = pP2PCtrl->GroupOpChannel; */ + + DBGPRINT(RT_DEBUG_ERROR, ("P2pGoNegoDone. NextScanRound= %ld\n", pP2PCtrl->P2pCounter.NextScanRound)); + DBGPRINT(RT_DEBUG_ERROR, ("2 WscMode = %lx \n", pP2PCtrl->WscMode)); + /* Start WPS. */ + P2pSetWps(pAd, pP2pEntry); + + } + } + else + DBGPRINT(RT_DEBUG_ERROR, ("P2pGoNegoDone- invalid p2pstate = %s\n", decodeP2PState(pP2PCtrl->P2PConnectState))); + + +} + +/* + ========================================================================== + Description: + Call this function after a successful WPS provisioning. do coreessponding action as GO or Client. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pWpsDone( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr) +{ + +} + +VOID P2pLinkDown( + IN PRTMP_ADAPTER pAd, + IN INT32 type) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + INT if_type = pObj->ioctl_if_type; + UCHAR BBPValue = 0; + + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: ==> P2P Connect State = %d. %s.\n", __FUNCTION__, pP2PCtrl->P2PConnectState, decodeP2PState(pP2PCtrl->P2PConnectState))); + + P2pStopConnectThis(pAd); /* clean Connecting MAC Address. */ + + pP2PCtrl->P2PConnectState = P2P_CONNECT_IDLE; +/* + pP2PCtrl->CtrlCurrentState = P2P_CTRL_IDLE; + pP2PCtrl->DiscCurrentState = P2P_DISC_LISTEN; + pP2PCtrl->GoFormCurrentState = P2P_GO_FORM_IDLE; +*/ + P2pStopScan(pAd); + P2pGroupTabInit(pAd); + pP2PCtrl->GoFormCurrentState = P2P_GO_FORM_IDLE; + + /* Restore P2P WSC Mode / Config Method */ + pP2PCtrl->WscMode = WSC_PIN_MODE; /* PIN */ + pP2PCtrl->ConfigMethod = 0x188; + pP2PCtrl->Dpid = DEV_PASS_ID_NOSPEC; + /*MlmeEnqueue(pAd, P2P_DISC_STATE_MACHINE, P2P_DISC_CANL_CMD_EVT, 0, NULL, 0);*/ + + pObj->ioctl_if_type = INT_P2P; + + if (P2P_CLI_ON(pAd)) + Set_P2pCli_Enable_Proc(pAd, "0"); + if (P2P_GO_ON(pAd)) + { + PWSC_CTRL pWscControl = &pAd->ApCfg.MBSSID[0].WscControl; + pWscControl->WscState = WSC_STATE_OFF; + } + + Set_P2p_OpMode_Proc(pAd, "0"); + pObj->ioctl_if_type = if_type; + pAd->ApCfg.ApCliTab[0].WscControl.WscConfStatus = WSC_SCSTATE_UNCONFIGURED; + pAd->ApCfg.MBSSID[0].WscControl.WscConfStatus = WSC_SCSTATE_UNCONFIGURED; + + P2pGetRandomSSID(pAd, pAd->ApCfg.MBSSID[MAIN_MBSSID].Ssid, &(pAd->ApCfg.MBSSID[MAIN_MBSSID].SsidLen)); + pAd->P2pCfg.SSIDLen = pAd->ApCfg.MBSSID[MAIN_MBSSID].SsidLen; + NdisMoveMemory(pAd->P2pCfg.SSID, pAd->ApCfg.MBSSID[MAIN_MBSSID].Ssid, pAd->P2pCfg.SSIDLen); + + /* Set Channel. */ + if ((INFRA_ON(pAd)) && (pAd->StaActive.SupportedHtPhy.ChannelWidth == BW_40)) + { + } + else + { + BOOLEAN bDisableMAC = FALSE; + UINT32 Data = 0, macStatus; + UINT32 MTxCycle; + + if (pAd->CommonCfg.BBPCurrentBW = BW_40) + bDisableMAC = TRUE; + + if (bDisableMAC) + { + /* 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; + } + } + + OS_WAIT(500); + pAd->CommonCfg.BBPCurrentBW = BW_20; + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + + if (bDisableMAC) + { + /* Enable MAC Tx/Rx */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Data); + Data |= 0x0C; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Data); + } + + if (!INFRA_ON(pAd)) + { + pAd->CommonCfg.Channel = pP2PCtrl->ListenChannel; + pAd->MlmeAux.AutoReconnectSsidLen = pAd->CommonCfg.SsidLen; + NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen); + } + + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + } + + if (IS_PERSISTENT_ON(pAd) && pP2PCtrl->bP2pCliReConnect) + { + COPY_MAC_ADDR(pAd->P2pCfg.ConnectingMAC, pAd->P2pTable.PerstEntry[0].Addr); + DBGPRINT(RT_DEBUG_ERROR, ("P2P CLIENT Re-Connect to %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pAd->P2pCfg.ConnectingMAC))); + } +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT + if (type == P2P_CONNECT_FAIL) + type = RT_P2P_CONNECT_FAIL; + else if (type == P2P_DISCONNECTED) + type = RT_P2P_DISCONNECTED; + P2pSendWirelessEvent(pAd, type, NULL, NULL); +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ +} + +/* + ========================================================================== + Description: + Start autonomous GO function/ + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pStartAutoGo( + IN PRTMP_ADAPTER pAd) +{ + +} + +VOID P2pEnable( + IN PRTMP_ADAPTER pAd) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + RTMPMoveMemory(pP2PCtrl->SSID, WILDP2PSSID, WILDP2PSSIDLEN); + + pP2PCtrl->P2pCapability[0] = 0; + pP2PCtrl->P2pCapability[1] = 0; + + if (IS_PERSISTENT_ON(pAd)) + { + pAd->P2pCfg.P2pCapability[1] |= GRPCAP_PERSISTENT; + pAd->P2pCfg.P2pCapability[1] |= GRPCAP_PERSISTENT_RECONNECT; + pAd->P2pCfg.P2pCapability[0] |= DEVCAP_INVITE; + pAd->P2pCfg.ExtListenInterval = P2P_EXT_LISTEN_INTERVAL; + pAd->P2pCfg.ExtListenPeriod = P2P_EXT_LISTEN_PERIOD; + } + else + { + /* When Persistent is disabled, I won't support extended listening, so set to Zero. */ + pAd->P2pCfg.ExtListenInterval = 0; + pAd->P2pCfg.ExtListenPeriod = 0; + } + + /* P2P Device Capability */ + pP2PCtrl->P2pCapability[0] |= DEVCAP_INVITE; + + if (pP2PCtrl->P2p_OpMode == P2P_CONCURRENT) + { + pP2PCtrl->P2pCapability[1] |= GRPCAP_CROSS_CONNECT; + pP2PCtrl->P2pCapability[0] |= DEVCAP_CLIENT_CONCURRENT; + } + + + if (IS_INTRA_BSS_ON(pAd)) + { + pP2PCtrl->P2pCapability[1] |= GRPCAP_INTRA_BSS; + } + + { + pP2PCtrl->ConfigMethod = 0x188; + pAd->StaCfg.WscControl.RegData.SelfInfo.ConfigMethods = 0x188; + pAd->StaCfg.WscControl.RegData.SelfInfo.DevPwdId = 0x188; + } + + pP2PCtrl->ConfigTimeout[0] = 4; + pP2PCtrl->ConfigTimeout[1] = 30; + + /* Construct AP RSN_IE. */ + RTMPMakeRSNIE(pAd, Ndis802_11AuthModeWPA2PSK, Ndis802_11Encryption3Enabled, 0 /*apidx*/); + + P2pStopNoA(pAd, NULL); + pAd->P2pCfg.CTWindows = 0; + P2pScanChannelDefault(pAd); + pP2PCtrl->P2PConnectState = P2P_CONNECT_IDLE; + P2pGotoIdle(pAd); + + /*AsicSetBssid(pAd, pP2PCtrl->CurrentAddress); */ + { + ULONG Addr4; + UINT32 regValue; + PUCHAR pP2PBssid = &pAd->CurrentAddress[0]; + + Addr4 = (ULONG)(pP2PBssid[0]) | + (ULONG)(pP2PBssid[1] << 8) | + (ULONG)(pP2PBssid[2] << 16) | + (ULONG)(pP2PBssid[3] << 24); + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4); + + Addr4 = 0; + + /* always one BSSID in STA mode */ + Addr4 = (ULONG)(pP2PBssid[4]) | (ULONG)(pP2PBssid[5] << 8); + + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4); + + RTMP_IO_READ32(pAd, MAC_BSSID_DW1, ®Value); + regValue &= 0x0000FFFF; + + if ((pAd->CurrentAddress[5] % 2 != 0) +#ifdef P2P_ODD_MAC_ADJUST + && FALSE +#endif /* P2P_ODD_MAC_ADJUST */ + ) + DBGPRINT(RT_DEBUG_ERROR, ("The 2-BSSID mode is enabled, the BSSID byte5 MUST be the multiple of 2\n")); + + regValue |= (1 << 16); + /* 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); + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, regValue); + } + + DBGPRINT(RT_DEBUG_ERROR, ("!4 OpStatusFlags = %lx. CentralChannel = %d. Channel = %d. !!! \n", pAd->CommonCfg.OpStatusFlags,pAd->CommonCfg.CentralChannel,pAd->CommonCfg.Channel)); + +} + +/* + ========================================================================== + Description: + Modify P2P's listen channel when in Concurrent Operation to get better performance. + Can be called from LinkUp and LinkDown; + + Parameters: + + Note: + + ========================================================================== + */ +VOID P2pScanChannelDefault( + IN PRTMP_ADAPTER pAd) +{ + /* Default listen channel is based on spec, using Social channels 1, 6, 11. */ + pAd->P2pCfg.P2pProprietary.ListenChanel[0] = 1; + pAd->P2pCfg.P2pProprietary.ListenChanel[1] = 6; + pAd->P2pCfg.P2pProprietary.ListenChanel[2] = 11; + pAd->P2pCfg.P2pProprietary.ListenChanelIndex = 0; + pAd->P2pCfg.P2pProprietary.ListenChanelCount = 3; + + DBGPRINT(RT_DEBUG_ERROR, ("%s <=== count = %d, Channels are %d, %d,%d separately \n", + __FUNCTION__, pAd->P2pCfg.P2pProprietary.ListenChanelCount, pAd->P2pCfg.P2pProprietary.ListenChanel[0], pAd->P2pCfg.P2pProprietary.ListenChanel[1], pAd->P2pCfg.P2pProprietary.ListenChanel[2])); +} + +/* + ======================================================================== + + Routine Description: + If. + + Arguments: + - NIC Adapter pointer + + Return Value: + FALSE - None of channel in ChannelList Match any channel in pAd->ChannelList[] array + + IRQL = DISPATCH_LEVEL + + Note: + ======================================================================== + +*/ +BOOLEAN P2pCheckChannelList( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pChannelList) +{ + UCHAR i, k; + UCHAR NumOfDismatch = 0; + + /* Check if new (control) channel is in our channellist which we currently agree to operate in. */ + for (k = 0;k < MAX_NUM_OF_CHANNELS;k++) + { + if (*(pChannelList + k) == 0) + break; + + for (i = 0;i < pAd->ChannelListNum;i++) + { + if (pAd->ChannelList[i].Channel == *(pChannelList + k)) + { + break; + } + } + if ( i == pAd->ChannelListNum) + NumOfDismatch++; + } + + if ((NumOfDismatch == k) && (k != 0)) + { + DBGPRINT(RT_DEBUG_TRACE, (" P2P - no common channel = %d...\n", *pChannelList)); + return FALSE; + } + + return TRUE; + +} + + +/* + ========================================================================== + Description: + The routine check whether we need to check this frame's transmission result. Success ? or Retry fail?. + If found retry fail, we may need to resend this frame again. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pAckRequiredCheck( + IN PRTMP_ADAPTER pAd, + IN PP2P_PUBLIC_FRAME pFrame, + OUT UCHAR *TempPid) +{ + UCHAR EAPHEAD[8] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e}; + PUCHAR pDest; + PFRAME_P2P_ACTION pP2pActFrame; + PUCHAR pP2pOUI = (PUCHAR) pFrame; + + pP2pOUI += (sizeof(HEADER_802_11) + 2); + + pP2pActFrame = (PFRAME_P2P_ACTION)pFrame; + /* check Go Neg Confirm Frame. */ + if ((pFrame->Subtype == GO_NEGOCIATION_CONFIRM) && + (NdisEqualMemory(pP2pOUI, P2POUIBYTE, 4)) && + (pFrame->Action == ACTION_WIFI_DIRECT) && + (pFrame->Category == CATEGORY_PUBLIC)) + { + DBGPRINT(RT_DEBUG_TRACE,("P2pAckRequiredCheck --> This is a Confirm Frame. Pid = RequireACK !!!\n")); + *TempPid = 0x7; /* PID_REQUIRE_ACK */ + return; + } + + /* check Intivation Response. */ + if ((pFrame->Subtype == P2P_INVITE_RSP) && + (NdisEqualMemory(pP2pOUI, P2POUIBYTE, 4)) && + (pFrame->Action == ACTION_WIFI_DIRECT) && + (pFrame->Category == CATEGORY_PUBLIC)) + { + DBGPRINT(RT_DEBUG_TRACE,("P2pAckRequiredCheck --> This is a Invite Rsp Frame. Pid = RequireACK !!!\n")); + *TempPid = 0x7; /* PID_REQUIRE_ACK */ + return; + } + + if ((pP2pActFrame->Category == 0x7F/*MT2_ACT_VENDOR*/) + && (pP2pActFrame->OUISubType == P2PACT_GO_DISCOVER_REQ) + && (pP2pActFrame->OUIType == 0x9)) + { + DBGPRINT(RT_DEBUG_TRACE,("P2pAckRequiredCheck --> This is a GO Discoverbility. Pid = RequireACK !!!\n")); + *TempPid = 0x7; /* PID_REQUIRE_ACK */ + return; + } + /* As Go, need to check EAP fail's ACK */ + if ((IS_P2P_REGISTRA(pAd)) && (pFrame->p80211Header.FC.Type == BTYPE_DATA)) + { + pDest = &pFrame->Category; + if (NdisEqualMemory(EAPHEAD, pDest, 8)) + { + pDest += 8; + if ((*pDest == EAPOL_VER) && (*(pDest+1) == EAPPacket) && (*(pDest + 3) == EAP_CODE_FAIL)) + { + DBGPRINT(RT_DEBUG_TRACE,("P2pAckRequiredCheck --> This is a EAP FailFrame. Pid = RequireACK!!!\n")); + *TempPid = 0x7; /* PID_REQUIRE_ACK */ + } + } + + } + +} + +BOOLEAN IsP2pFirstMacSmaller( + IN PUCHAR Firststaddr, + IN PUCHAR SecondAddr) +{ + UCHAR i; + for (i=0 ; i< 6;i++) + { + if (*(Firststaddr+i) > *(SecondAddr+i)) + return FALSE; + } + + return TRUE; +} + +/* + ========================================================================== + Description: + Initial Listen interval for Listen Timer + Return: + VOID + NOTE: + ========================================================================== +*/ +VOID P2PInitListenTimer( + IN PRTMP_ADAPTER pAd, + UINT32 value) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + DBGPRINT(RT_DEBUG_TRACE, ("<---- %s\n", __FUNCTION__)); + pP2PCtrl->P2pCounter.bListen = FALSE; + pP2PCtrl->P2pCounter.ListenInterval = 0; +} + +/* + ========================================================================== + Description: + Set Listen interval for Listen Timer + Return: + VOID + NOTE: + ========================================================================== +*/ +VOID P2PSetListenTimer( + IN PRTMP_ADAPTER pAd, + UINT32 value) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + DBGPRINT(RT_DEBUG_INFO, ("<---- %s\n", __FUNCTION__)); + if ((pP2PCtrl->P2pCounter.bStartScan == TRUE) && (pP2PCtrl->P2pCounter.bListen == FALSE)) + { + /* update Discovery State Machine state. */ + if (pP2PCtrl->P2pCounter.bStartScan) + MlmeEnqueue(pAd, P2P_DISC_STATE_MACHINE, P2P_DISC_LISTEN_CMD_EVT, 0, NULL, 0); + } +} + +/* + ========================================================================== + Description: + Listen State Timer Handler + Return: + VOID + NOTE: + ========================================================================== +*/ +VOID P2PListenTimerExec( + IN PRTMP_ADAPTER pAd, + UINT32 value) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + DBGPRINT(RT_DEBUG_INFO, ("<---- %s\n", __FUNCTION__)); + pP2PCtrl->P2pCounter.bListen = FALSE; + + if (pP2PCtrl->P2pCounter.bStartScan == TRUE) + { + /* Listen interval has expired, go to Search state. */ + MlmeEnqueue(pAd, P2P_DISC_STATE_MACHINE, P2P_DISC_SEARCH_CMD_EVT, 0, NULL, 0); +} + else + { + /* Listen interval has expired, go to IDLE state. */ + MlmeEnqueue(pAd, P2P_DISC_STATE_MACHINE, P2P_DISC_CANL_CMD_EVT, 0, NULL, 0); + + NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen); + pAd->MlmeAux.AutoReconnectSsidLen = (UCHAR)pAd->CommonCfg.SsidLen; + } +} + +/* + ========================================================================== + Description: + Initial Next Scan Round for Scan Timer + Return: + VOID + NOTE: + ========================================================================== +*/ +VOID P2PInitNextScanTimer( + IN PRTMP_ADAPTER pAd, + UINT32 value) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + DBGPRINT(RT_DEBUG_TRACE, ("<---- %s\n", __FUNCTION__)); + pP2PCtrl->P2pCounter.bNextScan = FALSE; + pP2PCtrl->P2pCounter.NextScanRound = 0xffffffff; +} + +/* + ========================================================================== + Description: + Set Next Scan Round for Scan Timer + Return: + VOID + NOTE: + ========================================================================== +*/ +VOID P2PSetNextScanTimer( + IN PRTMP_ADAPTER pAd, + UINT32 value) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + DBGPRINT(RT_DEBUG_INFO, ("<---- %s\n", __FUNCTION__)); + if ((pP2PCtrl->P2pCounter.bStartScan == TRUE) && (pP2PCtrl->P2pCounter.bNextScan == FALSE)) + { + pP2PCtrl->P2pCounter.bNextScan = TRUE; + if (value) + pP2PCtrl->P2pCounter.NextScanRound = value; + else + pP2PCtrl->P2pCounter.NextScanRound = (RandomByte(pAd) % P2P_RANDOM_BASE) + P2P_RANDOM_BIAS; + } + DBGPRINT(RT_DEBUG_TRACE, ("%s: NextScanRound - %ld\n", __FUNCTION__, pP2PCtrl->P2pCounter.NextScanRound)); +} + +/* + ========================================================================== + Description: + Next Scan Round Timer Handler + Return: + VOID + NOTE: + ========================================================================== +*/ +VOID P2PNextScanTimerExec( + IN PRTMP_ADAPTER pAd, + UINT32 value) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + DBGPRINT(RT_DEBUG_INFO, ("<---- %s\n", __FUNCTION__)); + pP2PCtrl->P2pCounter.bNextScan = FALSE; + MlmeEnqueue(pAd, P2P_CTRL_STATE_MACHINE, P2P_CTRL_DISC_EVT, 0, NULL, 0); +} + +VOID P2PInitDevDiscTimer( + IN PRTMP_ADAPTER pAd, + UINT32 value) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + DBGPRINT(RT_DEBUG_INFO, ("<---- %s\n", __FUNCTION__)); + pP2PCtrl->P2pCounter.bStartScan = FALSE; + pP2PCtrl->P2pCounter.CounterAftrScanButton = 0xffffffff; +} + +VOID P2PSetDevDiscTimer( + IN PRTMP_ADAPTER pAd, + UINT32 value) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + DBGPRINT(RT_DEBUG_INFO, ("<---- %s\n", __FUNCTION__)); + if (pP2PCtrl->P2pCounter.bStartScan == FALSE) + { + pP2PCtrl->P2pCounter.bStartScan = TRUE; + if (P2P_GO_ON(pAd) || P2P_CLI_ON(pAd)) + pP2PCtrl->P2pCounter.CounterAftrScanButton = 200; + pP2PCtrl->P2pCounter.CounterAftrScanButton = pP2PCtrl->DevDiscPeriod; + DBGPRINT(RT_DEBUG_ERROR, ("%s:: CounterAftrScanButton = %lu.\n", __FUNCTION__, pP2PCtrl->P2pCounter.CounterAftrScanButton)); + } +} + +VOID P2PDevDiscTimerExec( + IN PRTMP_ADAPTER pAd, + UINT32 value) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + DBGPRINT(RT_DEBUG_INFO, ("<---- %s\n", __FUNCTION__)); + pP2PCtrl->P2pCounter.bStartScan = FALSE; + MlmeEnqueue(pAd, P2P_CTRL_STATE_MACHINE, P2P_CTRL_DISC_DONE_EVT, 0, NULL, 1); +#ifdef DPA_S + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_DISCOVER_COMPLETE, NULL, NULL, 0); +#endif /* DPA_S */ +} + +VOID P2P_SetWscRule( + IN PRTMP_ADAPTER pAd, + UCHAR index, + PUSHORT PeerWscMethod) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PRT_P2P_CLIENT_ENTRY pP2pEntry = &pAd->P2pTable.Client[index]; + DBGPRINT(RT_DEBUG_TRACE, ("%s:: Peer Dpid = %s. My Dpid = %s.\n", __FUNCTION__, decodeDpid(pP2pEntry->Dpid), decodeDpid(pP2PCtrl->Dpid))); + DBGPRINT(RT_DEBUG_TRACE, ("%s:: Peer Config Method = %s. My Config Method = %s.\n", __FUNCTION__, decodeConfigMethod(pP2pEntry->ConfigMethod), decodeConfigMethod(pP2PCtrl->ConfigMethod))); + + if (pP2PCtrl->Dpid == DEV_PASS_ID_NOSPEC) + { + if ((pP2pEntry->ConfigMethod == WSC_CONFMET_KEYPAD) || (pP2pEntry->Dpid == DEV_PASS_ID_USER)) + { + pP2PCtrl->WscMode = WSC_PIN_MODE; + pP2PCtrl->ConfigMethod = WSC_CONFMET_DISPLAY; + pP2PCtrl->Dpid = DEV_PASS_ID_REG; + *PeerWscMethod = WSC_CONFMET_KEYPAD; + } + else if ((pP2pEntry->ConfigMethod == WSC_CONFMET_DISPLAY) || (pP2pEntry->Dpid == DEV_PASS_ID_REG)) + { + pP2PCtrl->WscMode = WSC_PIN_MODE; + pP2PCtrl->ConfigMethod = WSC_CONFMET_KEYPAD; + pP2PCtrl->Dpid = DEV_PASS_ID_USER; + *PeerWscMethod = WSC_CONFMET_DISPLAY; + } + else if ((pP2pEntry->ConfigMethod == WSC_CONFMET_PBC) || (pP2pEntry->Dpid == DEV_PASS_ID_PBC)) + { + pP2PCtrl->WscMode = WSC_PBC_MODE; + pP2PCtrl->ConfigMethod = WSC_CONFMET_PBC; + pP2PCtrl->Dpid = DEV_PASS_ID_PBC; + *PeerWscMethod = WSC_CONFMET_PBC; + } + else + { + if ((pP2pEntry->Rule == P2P_IS_CLIENT) && (pP2PCtrl->Rule == P2P_IS_GO)) + { + /* I'm Registrar and Enter PIN. */ + pP2PCtrl->WscMode = WSC_PIN_MODE; + pP2PCtrl->ConfigMethod = WSC_CONFMET_KEYPAD; + pP2PCtrl->Dpid = DEV_PASS_ID_USER; + } + else + { + /* I'm Enrollee and Use Default Config Method. */ + if (pP2PCtrl->DefaultConfigMethod == P2P_REG_CM_DISPLAY) + { + pP2PCtrl->WscMode = WSC_PIN_MODE; + pP2PCtrl->ConfigMethod = WSC_CONFMET_DISPLAY; + pP2PCtrl->Dpid = DEV_PASS_ID_REG; + *PeerWscMethod = WSC_CONFMET_KEYPAD; + } + else if (pP2PCtrl->DefaultConfigMethod == P2P_REG_CM_KEYPAD) + { + pP2PCtrl->WscMode = WSC_PIN_MODE; + pP2PCtrl->ConfigMethod = WSC_CONFMET_KEYPAD; + pP2PCtrl->Dpid = DEV_PASS_ID_USER; + *PeerWscMethod = WSC_CONFMET_DISPLAY; + } + else if (pP2PCtrl->DefaultConfigMethod == P2P_REG_CM_PBC) + { + pP2PCtrl->WscMode = WSC_PBC_MODE; + pP2PCtrl->ConfigMethod = WSC_CONFMET_PBC; + pP2PCtrl->Dpid = DEV_PASS_ID_PBC; + *PeerWscMethod = WSC_CONFMET_PBC; + } + } + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("My P2P Wsc Configuration:\n")); + DBGPRINT(RT_DEBUG_TRACE, ("WscMode = %d. WscConfigMethod = %s. WscDpid = %s.\n", pP2PCtrl->WscMode, decodeConfigMethod(pP2PCtrl->ConfigMethod), decodeDpid(pP2PCtrl->Dpid))); + if (pP2PCtrl->ConfigMethod == WSC_CONFMET_DISPLAY) + { + /* + Although driver uses different structure for P2P GO and P2P CLI but PIN shall be the same. + */ + pAd->ApCfg.MBSSID[0].WscControl.WscEnrolleePinCode = pAd->ApCfg.ApCliTab[0].WscControl.WscEnrolleePinCode; + pAd->ApCfg.MBSSID[0].WscControl.WscEnrolleePinCodeLen = pAd->ApCfg.ApCliTab[0].WscControl.WscEnrolleePinCodeLen; + + /* Woody 1: Show PIN Code */ + DBGPRINT(RT_DEBUG_TRACE, (" *************************************************\n")); + DBGPRINT(RT_DEBUG_TRACE, (" * *\n")); + DBGPRINT(RT_DEBUG_TRACE, (" * PIN Code = %08u *\n", pAd->ApCfg.ApCliTab[0].WscControl.WscEnrolleePinCode)); + DBGPRINT(RT_DEBUG_TRACE, (" * *\n")); + DBGPRINT(RT_DEBUG_TRACE, (" *************************************************\n")); + { +/* + RtmpOSWrielessEventSendExt(pAd->net_dev, RT_WLAN_EVENT_SHOWPIN, -1, pP2pEntry->addr, + NULL, 0, 0); +*/ + } + } + else if (pP2PCtrl->ConfigMethod == WSC_CONFMET_KEYPAD) + { + /* Woody 2: Enter PIN Code */ + { +/* + RtmpOSWrielessEventSendExt(pAd->net_dev, RT_WLAN_EVENT_PIN, -1, pP2pEntry->addr, + NULL, 0, 0); +*/ + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("Peer P2P Wsc Configuration:\n")); + DBGPRINT(RT_DEBUG_TRACE, ("WscMode = %d. WscConfigMethod = %s. WscDpid = %s.\n", pP2pEntry->WscMode, decodeConfigMethod(pP2pEntry->ConfigMethod), decodeDpid(pP2pEntry->Dpid))); + +} + +/* + ========================================================================== + Description: + decode Dpid + Return: + State string + NOTE: + ========================================================================== +*/ + PSTRING decodeDpid (USHORT dpid) +{ + PSTRING retval = " "; + switch (dpid) + { + case DEV_PASS_ID_PIN: retval = "DEV_PASS_ID_PIN "; break; + case DEV_PASS_ID_USER: retval = "DEV_PASS_ID_USER_SPECIFIED"; break; + case DEV_PASS_ID_REG: retval = "DEV_PASS_ID_REGISTRA_SPECIFIED"; break; + case DEV_PASS_ID_PBC: retval = "DEV_PASS_ID_PBC"; break; + default: retval = "***UNKNOWN dpid***"; + } + return(retval); + +} +/* + ========================================================================== + Description: + decode ConfigMethod + Return: + State string + NOTE: + ========================================================================== +*/ +PSTRING ddecodeConfigMethod (USHORT ConfigMethos) +{ + PSTRING retval = " "; + ULONG mm[4], i; + mm[0] = 0; + mm[1] = 0; + mm[2] = 0; + mm[3] = 0; + if ((ConfigMethos & WSC_CONFMET_LABEL) != 0) + mm[0] = 1; + if ((ConfigMethos & WSC_CONFMET_DISPLAY) != 0) + mm[1] = 1; + if ((ConfigMethos & WSC_CONFMET_KEYPAD) != 0) + mm[2] = 1; + if ((ConfigMethos & WSC_CONFMET_PBC) != 0) + mm[3] = 1; + for ( i = 0;i < 4;i++) + { + } + return (retval); +} + +PSTRING decodeMyRule (USHORT Rule) +{ + PSTRING retval = " "; + switch (Rule) + { + case P2P_IS_CLIENT: retval = "I am P2P Client"; break; + case P2P_IS_GO: retval = "I am P2P GO"; break; + case P2P_IS_DEVICE: retval = "I am P2P Device"; break; + case P2P_IS_CLIENT_IN_GROUP: retval = "I am P2P Client in Group"; break; + default: retval = "*** Unknown Rule ***"; + } + return(retval); +} + +PSTRING decodeConfigMethod (USHORT ConfigMethos) +{ + PSTRING retval = " "; + switch (ConfigMethos) + { + case WSC_CONFMET_LABEL: retval = "LABEL LABEL "; break; + case WSC_CONFMET_DISPLAY: retval = "DISPLAY DISPLAY"; break; + case WSC_CONFMET_KEYPAD: retval = "KEYPAD KEYPAD"; break; + case WSC_CONFMET_PBC: retval = "PBC PBC"; break; + case WSC_CONFMET_DISPLAY | WSC_CONFMET_KEYPAD: retval = "DISPLAY KEYPAD"; break; + case WSC_CONFMET_DISPLAY | WSC_CONFMET_PBC: retval = "DISPLAY PBC"; break; + case WSC_CONFMET_KEYPAD | WSC_CONFMET_PBC: retval = "KEYPAD PBC"; break; + case WSC_CONFMET_DISPLAY | WSC_CONFMET_KEYPAD | WSC_CONFMET_PBC: retval = "DISPLAY KEYPAD PBC"; break; + default: retval = "***Multiple ConfigMethod***"; + } + return(retval); +} + + +/* + ========================================================================== + Description: + decode P2P state + Return: + State string + NOTE: + ========================================================================== +*/ + PSTRING decodeP2PState (UCHAR P2pState) +{ + PSTRING retval = " "; + switch (P2pState) { + case P2P_CONNECT_IDLE: retval = "P2P_CONNECT_IDLE"; break; + case P2P_ANY_IN_FORMATION_AS_CLIENT: retval = "GroupForming as Client"; break; + case P2P_ANY_IN_FORMATION_AS_GO: retval = "P2P_ANY_IN_FORMATION_AS_GO"; break; + case P2P_DO_GO_NEG_DONE_CLIENT: retval = "P2P_DO_GO_NEG_DONE_CLIENT"; break; + case P2P_DO_GO_SCAN_BEGIN: retval = "P2P_DO_GO_SCAN_BEGIN"; break; + case P2P_DO_GO_SCAN_DONE: retval = "P2P_DO_GO_SCAN_DONE"; break; + case P2P_WPS_REGISTRA: retval = "P2P_WPS_REGISTRA"; break; + case P2P_DO_WPS_ENROLLEE: retval = "P2P_DO_WPS_ENROLLEE"; break; + default: retval = "***UNKNOWN state***"; + } + return(retval); +} + +/* + ========================================================================== + Description: + decode P2P client state + Return: + State string + NOTE: + ========================================================================== +*/ + PSTRING decodeP2PClientState (P2P_CLIENT_STATE P2pClientState) +{ + PSTRING retval = " "; + switch (P2pClientState) { + case P2PSTATE_NONE: retval = "P2PSTATE_NONE"; break; + case P2PSTATE_DISCOVERY: retval = "P2PSTATE_DISCOVERY"; break; + case P2PSTATE_DISCOVERY_CLIENT: retval = "P2PSTATE_DISCOVERY_CLIENT"; break; + case P2PSTATE_DISCOVERY_GO: retval = "P2PSTATE_DISCOVERY_GO"; break; + case P2PSTATE_CLIENT_DISCO_COMMAND: retval = "P2PSTATE_CLIENT_DISCO_COMMAND"; break; + case P2PSTATE_GO_DISCO_COMMAND: retval = "P2PSTATE_GO_DISCO_COMMAND"; break; + case P2PSTATE_PROVISION_COMMAND: retval = "P2PSTATE_PROVISION_COMMAND"; break; + case P2PSTATE_SERVICE_DISCO_COMMAND: retval = "P2PSTATE_SERVICE_DISCO_COMMAND"; break; + case P2PSTATE_INVITE_COMMAND: retval = "P2PSTATE_INVITE_COMMAND"; break; + case P2PSTATE_CONNECT_COMMAND: retval = "P2PSTATE_CONNECT_COMMAND"; break; + case P2PSTATE_SENT_INVITE_REQ: retval = "P2PSTATE_SENT_INVITE_REQ"; break; + case P2PSTATE_SENT_GO_NEG_REQ: retval = "P2PSTATE_SENT_GO_NEG_REQ"; break; + case P2PSTATE_WAIT_GO_COMFIRM: retval = "P2PSTATE_WAIT_GO_COMFIRM"; break; + case P2PSTATE_WAIT_GO_COMFIRM_ACK: retval = "P2PSTATE_WAIT_GO_COMFIRM_ACK"; break; + case P2PSTATE_GO_COMFIRM_ACK_SUCCESS: retval = "P2PSTATE_GO_COMFIRM_ACK_SUCCESS"; break; + case P2PSTATE_WAIT_GO_DISCO_ACK: retval = "P2PSTATE_WAIT_GO_DISCO_ACK"; break; + case P2PSTATE_WAIT_GO_DISCO_ACK_SUCCESS: retval = "P2PSTATE_WAIT_GO_DISCO_ACK_SUCCESS"; break; + case P2PSTATE_GO_WPS: retval = "P2PSTATE_GO_WPS"; break; + case P2PSTATE_GO_AUTH: retval = "P2PSTATE_GO_AUTH"; break; + case P2PSTATE_GO_ASSOC: retval = "P2PSTATE_GO_ASSOC"; break; + case P2PSTATE_CLIENT_WPS: retval = "P2PSTATE_CLIENT_WPS"; break; + case P2PSTATE_CLIENT_WPS_DONE: retval = "P2PSTATE_CLIENT_WPS_DONE"; break; + case P2PSTATE_CLIENT_AUTH: retval = "P2PSTATE_CLIENT_AUTH"; break; + case P2PSTATE_CLIENT_ASSOC: retval = "P2PSTATE_CLIENT_ASSOC"; break; + case P2PSTATE_CLIENT_OPERATING: retval = "P2PSTATE_CLIENT_OPERATING"; break; + case P2PSTATE_CLIENT_ABSENCE: retval = "P2PSTATE_CLIENT_ABSENCE"; break; + case P2PSTATE_CLIENT_SCAN: retval = "P2PSTATE_CLIENT_SCAN"; break; + case P2PSTATE_CLIENT_FIND: retval = "P2PSTATE_CLIENT_FIND"; break; + case P2PSTATE_GO_OPERATING: retval = "P2PSTATE_GO_OPERATING"; break; + case P2PSTATE_GO_ABSENCE: retval = "P2PSTATE_GO_ABSENCE"; break; + case P2PSTATE_GO_SCAN: retval = "P2PSTATE_GO_SCAN"; break; + case P2PSTATE_GO_FIND: retval = "P2PSTATE_GO_FIND"; break; + case P2PSTATE_NONP2P_WPS: retval = "P2PSTATE_NONP2P_WPS"; break; + case P2PSTATE_NONP2P_PSK: retval = "P2PSTATE_NONP2P_PSK"; break; + default: retval = "***UNKNOWN state***"; + } + return(retval); + +} + +PSTRING decodeCtrlState (UCHAR State) +{ + PSTRING retval = " "; + switch (State) + { + case P2P_CTRL_IDLE: retval = "P2P_CTRL_IDLE"; break; + case P2P_CTRL_DISCOVERY: retval = "P2P_CTRL_DISCOVERY"; break; + case P2P_CTRL_GROUP_FORMATION: retval = "P2P_CTRL_GROUP_FORMATION"; break; + case P2P_CTRL_DONE: retval = "P2P_CTRL_DONE"; break; + default: retval = "***Unknown CTRL State***"; + } + return(retval); +} + +PSTRING decodeDiscoveryState (UCHAR State) +{ + PSTRING retval = " "; + switch (State) + { + case P2P_DISC_IDLE: retval = "P2P_DISC_IDLE"; break; + case P2P_DISC_SCAN: retval = "P2P_DISC_SCAN"; break; + case P2P_DISC_LISTEN: retval = "P2P_DISC_LISTEN"; break; + case P2P_DISC_SEARCH: retval = "P2P_DISC_SEARCH"; break; + default: retval = "***Unknown Device Discovery State***"; + } + return(retval); +} + +PSTRING decodeGroupFormationState (UCHAR State) +{ + PSTRING retval = " "; + switch (State) + { + case P2P_GO_FORM_IDLE: retval = "P2P_GO_FORM_IDLE"; break; + case P2P_WAIT_GO_FORM_RSP: retval = "P2P_WAIT_GO_FORM_RSP"; break; + case P2P_WAIT_GO_FORM_CONF: retval = "P2P_WAIT_GO_FORM_CONF"; break; + case P2P_GO_FORM_DONE: retval = "P2P_GO_FORM_DONE"; break; + case P2P_GO_FORM_PROV: retval = "P2P_GO_FORM_PROV"; break; + case P2P_GO_FORM_INVITE: retval = "P2P_GO_FORM_INVITE"; break; + case P2P_WAIT_GO_FORM_INVITE_RSP: retval = "P2P_WAIT_GO_FORM_INVITE_RSP"; break; + default: retval = "***Unknown Group Formation State***"; + } + return(retval); +} + +VOID decodeDeviceCap (UCHAR State) +{ + DBGPRINT(RT_DEBUG_TRACE, (" DeviceCapability = %x.\n", State)); + if (State & DEVCAP_SD) + DBGPRINT(RT_DEBUG_TRACE, (" [0] bServiceDiscovery\n")); + if (State & DEVCAP_CLIENT_DISCOVER) + DBGPRINT(RT_DEBUG_TRACE, (" [1] bP2PClientDiscoverability\n")); + if (State & DEVCAP_CLIENT_CONCURRENT) + DBGPRINT(RT_DEBUG_TRACE, (" [2] bConcurrentOperation\n")); + if (State & DEVCAP_INFRA_MANAGED) + DBGPRINT(RT_DEBUG_TRACE, (" [3] bP2PInfrastructureManaged\n")); + if (State & DEVCAP_DEVICE_LIMIT) + DBGPRINT(RT_DEBUG_TRACE, (" [4] bP2PDeviceLimit\n")); + if (State & DEVCAP_INVITE) + DBGPRINT(RT_DEBUG_TRACE, (" [5] bP2PInvitationProcedure\n")); +} + +VOID decodeGroupCap (UCHAR State) +{ + DBGPRINT(RT_DEBUG_TRACE, (" GroupCapability = %x.\n", State)); + if (State & GRPCAP_OWNER) + DBGPRINT(RT_DEBUG_TRACE, (" [0] bP2PGroupOwner\n")); + if (State & GRPCAP_PERSISTENT) + DBGPRINT(RT_DEBUG_TRACE, (" [1] bPersistentP2PGroup\n")); + if (State & GRPCAP_LIMIT) + DBGPRINT(RT_DEBUG_TRACE, (" [2] bP2PGroupLimit\n")); + if (State & GRPCAP_INTRA_BSS) + DBGPRINT(RT_DEBUG_TRACE, (" [3] bIntra-BssDistribution\n")); + if (State & GRPCAP_CROSS_CONNECT) + DBGPRINT(RT_DEBUG_TRACE, (" [4] bCrossConnection\n")); + if (State & GRPCAP_PERSISTENT_RECONNECT) + DBGPRINT(RT_DEBUG_TRACE, (" [5] bPersistentReconnect\n")); + if (State & GRPCAP_GROUP_FORMING) + DBGPRINT(RT_DEBUG_TRACE, (" [6] bGroupFormation\n")); +} + +/* + ========================================================================== + Description: + debug print function for P2P. + Return: + + NOTE: + + ========================================================================== +*/ +VOID P2PPrintMac( + IN PRTMP_ADAPTER pAd, + IN UCHAR macindex) +{ + MAC_TABLE_ENTRY *pEntry; + + DBGPRINT(RT_DEBUG_TRACE, (" ====================================================>P2PPrintMac i = %d, \n", macindex)); + pEntry = &pAd->MacTab.Content[macindex]; + DBGPRINT(RT_DEBUG_TRACE, ("!! , HTMode = %x, WepStatus = %d, AuthMode = %d. \n", pEntry->HTPhyMode.word, pEntry->WepStatus, pEntry->AuthMode)); + + DBGPRINT(RT_DEBUG_TRACE, ("ValidAsCLI = %d. ClientStatusFlags = %lx, \n", IS_ENTRY_CLIENT(pEntry), pEntry->ClientStatusFlags)); +#ifdef RELEASE_EXLCUDE + /* MAC_TABLE_ENTRY don't have P2pInfo, skip this. */ +#endif /* RELEASE_EXCLUDE */ + DBGPRINT(RT_DEBUG_TRACE, ("devaddr = %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pEntry->Addr))); +#ifdef RELEASE_EXLCUDE + /* MAC_TABLE_ENTRY don't have P2pInfo, skip this. */ +#endif /* RELEASE_EXCLUDE */ +} + +/* + ========================================================================== + Description: + debug print function for P2P Table entry. + Return: + + NOTE: + + ========================================================================== +*/ +VOID P2PPrintP2PEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR p2pindex) +{ + RT_P2P_CLIENT_ENTRY *pClient; + int j; + + if (p2pindex >= MAX_P2P_GROUP_SIZE) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: p2p Entry idx = %d\n", __FUNCTION__, p2pindex)); + DBGPRINT(RT_DEBUG_TRACE, ("====================================================>\n")); + pClient = &pAd->P2pTable.Client[p2pindex]; + DBGPRINT(RT_DEBUG_TRACE, ("P2pClientState = %s \n", decodeP2PClientState(pClient->P2pClientState))); + DBGPRINT(RT_DEBUG_TRACE, ("ConfigMethod = %x. %s \n", pClient->ConfigMethod, decodeConfigMethod(pClient->ConfigMethod))); + DBGPRINT(RT_DEBUG_TRACE, ("Opchannel = %d. Listenchannel = %d.\n", pClient->OpChannel, pClient->ListenChannel)); + DBGPRINT(RT_DEBUG_TRACE, ("MyGOIndex = %d. rule = %s.\n", pClient->MyGOIndex, decodeMyRule(pClient->Rule))); + DBGPRINT(RT_DEBUG_TRACE, ("addr = %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pClient->addr))); + DBGPRINT(RT_DEBUG_TRACE, ("bssid = %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pClient->bssid))); + DBGPRINT(RT_DEBUG_TRACE, ("interface addr = %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pClient->InterfaceAddr))); + DBGPRINT(RT_DEBUG_TRACE, ("DeviceType = %02x %02x %02x %02x %02x %02x %02x %02x\n", pClient->PrimaryDevType[0], pClient->PrimaryDevType[1], pClient->PrimaryDevType[2],pClient->PrimaryDevType[3],pClient->PrimaryDevType[4],pClient->PrimaryDevType[5],pClient->PrimaryDevType[6],pClient->PrimaryDevType[7])); + DBGPRINT(RT_DEBUG_TRACE, ("NumSecondaryType = %x. RegClass = %x. ConfigTimeOut = %x. \n", pClient->NumSecondaryType, pClient->RegClass, pClient->ConfigTimeOut)); + DBGPRINT(RT_DEBUG_TRACE, ("DeviceName[%ld] = %s\n", pClient->DeviceNameLen, pAd->P2pTable.Client[p2pindex].DeviceName)); + decodeDeviceCap(pClient->DevCapability); + decodeGroupCap(pClient->GroupCapability); + DBGPRINT(RT_DEBUG_TRACE, ("\n")); + DBGPRINT(RT_DEBUG_TRACE, ("<====================================================\n\n")); +} + +/* + ========================================================================== + Description: + debug print function for P2P Persistent Table entry. + Return: + + NOTE: + + ========================================================================== +*/ +VOID P2PPrintP2PPerstEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR p2pindex) +{ + RT_P2P_PERSISTENT_ENTRY *pClient; + + if (p2pindex >= MAX_P2P_TABLE_SIZE) + return; + + DBGPRINT(RT_DEBUG_TRACE, (" P2PPrintP2PPerstEntry i = %d, \n", p2pindex)); + pClient = &pAd->P2pTable.PerstEntry[p2pindex]; + DBGPRINT(RT_DEBUG_TRACE, ("addr = %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pClient->Addr))); + DBGPRINT(RT_DEBUG_TRACE, ("Key = %x %x %x %x %x %x %x %x\n", pClient->Profile.Key[0], pClient->Profile.Key[1], pClient->Profile.Key[2],pClient->Profile.Key[3],pClient->Profile.Key[4],pClient->Profile.Key[5],pClient->Profile.Key[6],pClient->Profile.Key[7])); + DBGPRINT(RT_DEBUG_TRACE, ("MacAddr = %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pClient->Profile.MacAddr))); + DBGPRINT(RT_DEBUG_TRACE, ("Ssid %d = DIRECT-%c%c%c%c%c%c\n", pClient->Profile.SSID.SsidLength,pClient->Profile.SSID.Ssid[7], pClient->Profile.SSID.Ssid[8], pClient->Profile.SSID.Ssid[9],pClient->Profile.SSID.Ssid[10],pClient->Profile.SSID.Ssid[11],pClient->Profile.SSID.Ssid[12])); + DBGPRINT(RT_DEBUG_TRACE, ("MyRule = %x, bValid = %x, \n", pClient->MyRule, pClient->bValid)); + +} + +/* + ========================================================================== + Description: + debug print function for P2P. + Return: + + NOTE: + + ========================================================================== +*/ + +VOID P2P_GoStartUp( + IN PRTMP_ADAPTER pAd, + IN INT bssidx) +{ + UINT32 rx_filter_flag; + INT idx; + ULONG offset; +#ifdef INF_AMAZON_SE + ULONG i; +#endif /* INF_AMAZON_SE */ + BOOLEAN bWmmCapable = FALSE; + BOOLEAN TxPreamble, SpectrumMgmt = FALSE; + UCHAR BBPR1 = 0, BBPR3 = 0; + UINT32 Value = 0; +#ifdef DOT1X_SUPPORT +/* BOOLEAN bDot1xReload = FALSE; */ +#endif /* DOT1X_SUPPORT */ + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("===> P2P_GoStartUp\n")); + + /*RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); */ + /*pAd->MlmeAux.Channel = 0; */ + /*ScanNextChannel(pAd, OPMODE_STA); */ + + + pAd->P2pCfg.P2pCapability[1] |= GRPCAP_OWNER; +#ifndef DPA_S + pAd->StaCfg.bAutoReconnect = FALSE; +#endif /* !DPA_S */ + pAd->ApCfg.MBSSID[0].UapsdInfo.bAPSDCapable = TRUE; + pAd->P2pCfg.bSentProbeRSP = TRUE; + /*pAd->P2pCfg.DiscCurrentState = P2P_DISC_LISTEN;*/ + + /* Stop Scan. */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); + pAd->MlmeAux.Channel = 0; + ScanNextChannel(pAd, OPMODE_STA); + } + + 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 */ + pAd->ApCfg.MBSSID[MAIN_MBSSID].bBcnSntReq = TRUE; + + /*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_P2P_GO); */ + pAd->flg_p2p_OpStatusFlags |= P2P_GO_UP; + pAd->P2pCfg.GroupOpChannel = pAd->P2pCfg.GroupChannel; + if (!INFRA_ON(pAd)) + pAd->CommonCfg.Channel = pAd->P2pCfg.GroupChannel; + pAd->P2pCfg.Rule = P2P_IS_GO; + +#ifdef INF_AMAZON_SE + for (i = 0; i < NUM_OF_TX_RING; i++) + { + pAd->BulkOutDataSizeLimit[i]=24576; + } +#endif /* INF_AMAZON_SE */ + + AsicDisableSync(pAd); + + + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + { + if (pAd->CommonCfg.Channel > 14) + pAd->ApCfg.MBSSID[MAIN_MBSSID].PhyMode = PHY_11AN_MIXED; + else + pAd->ApCfg.MBSSID[MAIN_MBSSID].PhyMode = PHY_11BGN_MIXED; + } + else + { + if (pAd->CommonCfg.Channel > 14) + pAd->ApCfg.MBSSID[MAIN_MBSSID].PhyMode = PHY_11A; + else + pAd->ApCfg.MBSSID[MAIN_MBSSID].PhyMode = PHY_11BG_MIXED; + } + + TxPreamble = (pAd->CommonCfg.TxPreamble == Rt802_11PreambleLong ? 0 : 1); + + { + PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[MAIN_MBSSID]; + + if ((pMbss->SsidLen <= 0) || (pMbss->SsidLen > MAX_LEN_OF_SSID)) + { + NdisMoveMemory(pMbss->Ssid, "P2P_Linux_AP", 12); + pMbss->SsidLen = 12; + } + + if (pMbss->bWmmCapable) + { + bWmmCapable = TRUE; + } + + /* GO always use WPA2PSK / AES */ + pMbss->AuthMode = Ndis802_11AuthModeWPA2PSK; + pMbss->WepStatus = Ndis802_11Encryption3Enabled; + pMbss->WscSecurityMode = WPA2PSKAES; + pMbss->GroupKeyWepStatus = pMbss->WepStatus; + pMbss->CapabilityInfo = + CAP_GENERATE(1, 0, (pMbss->WepStatus != Ndis802_11EncryptionDisabled), TxPreamble, pAd->CommonCfg.bUseShortSlotTime, SpectrumMgmt); + +#ifdef UAPSD_SUPPORT + if (pAd->ApCfg.MBSSID[0].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; + } /* End of if */ +#endif /* UAPSD_SUPPORT */ + + /* decide the mixed WPA cipher combination */ + if (pMbss->WepStatus == Ndis802_11Encryption4Enabled) + { + switch ((UCHAR)pMbss->AuthMode) + { + /* WPA mode */ + case Ndis802_11AuthModeWPA: + case Ndis802_11AuthModeWPAPSK: + pMbss->WpaMixPairCipher = WPA_TKIPAES_WPA2_NONE; + break; + + /* WPA2 mode */ + case Ndis802_11AuthModeWPA2: + case Ndis802_11AuthModeWPA2PSK: + pMbss->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 (pMbss->WpaMixPairCipher == MIX_CIPHER_NOTUSE || + pMbss->WpaMixPairCipher == WPA_TKIPAES_WPA2_NONE || + pMbss->WpaMixPairCipher == WPA_NONE_WPA2_TKIPAES) + pMbss->WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIPAES; + break; + } + + } + else + pMbss->WpaMixPairCipher = MIX_CIPHER_NOTUSE; + + /* Generate the corresponding RSNIE */ + RTMPMakeRSNIE(pAd, pMbss->AuthMode, pMbss->WepStatus, MAIN_MBSSID + MIN_NET_DEVICE_FOR_P2P_GO); + +#ifdef WSC_V2_SUPPORT + if (pMbss->WscControl.WscV2Info.bEnableWpsV2) + { + /* + WPS V2 doesn't support WEP and WPA/WPAPSK-TKIP. + */ + if ((pMbss->WepStatus == Ndis802_11WEPEnabled) || (pMbss->WepStatus == Ndis802_11Encryption2Enabled)) + WscOnOff(pAd, MAIN_MBSSID | MIN_NET_DEVICE_FOR_P2P_GO, TRUE); + else + WscOnOff(pAd, MAIN_MBSSID | MIN_NET_DEVICE_FOR_P2P_GO, FALSE); + } +#endif /* WSC_V2_SUPPORT */ + } + + if (INFRA_ON(pAd) && (pAd->StaActive.SupportedHtPhy.ChannelWidth == BW_40) && + (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA != pAd->StaActive.SupportedHtPhy.ExtChanOffset)) + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = pAd->StaActive.SupportedHtPhy.ExtChanOffset; + + N_ChannelCheck(pAd); + +#ifdef DOT11_N_SUPPORT + RTMPSetPhyMode(pAd, pAd->CommonCfg.PhyMode); + P2P_GoSetCommonHT(pAd); +#endif /* DOT11_N_SUPPORT */ + +#if defined(RT2883) || defined(RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + { + /* do nothing for DAC */ + } + else +#endif /* defined(RT2883) || defined(RT3883) */ + { +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->Antenna.field.TxPath == 2)) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1); + BBPR1 &= (~0x18); + BBPR1 |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1); + } + else +#endif /* DOT11_N_SUPPORT */ + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1); + BBPR1 &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1); + } + } + + /* Receiver Antenna selection, write to BBP R3(bit4:3) */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); + BBPR3 &= (~0x18); + if(pAd->Antenna.field.RxPath == 3) + { + BBPR3 |= (0x10); + } + else if(pAd->Antenna.field.RxPath == 2) + { + BBPR3 |= (0x8); + } + else if(pAd->Antenna.field.RxPath == 1) + { + BBPR3 |= (0x0); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); + + if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + if ((pAd->CommonCfg.PhyMode > PHY_11G) || bWmmCapable) + { + /* EDCA parameters used for AP's own transmission */ + 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; /*96; */ + pAd->CommonCfg.APEdcaParm.Txop[3] = 47; /*48; */ + AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); + + /* EDCA parameters to be annouced in outgoing BEACON, used by WMM STA */ + 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; */ + } + else + AsicSetEdcaParm(pAd, NULL); + } + +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED) + { + /* Patch UI */ + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = BW_20; + } + + /* init */ + if (pAd->CommonCfg.bRdg) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); + AsicEnableRDG(pAd); + } + else + { + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); + AsicDisableRDG(pAd); + } +#endif /* DOT11_N_SUPPORT */ + + AsicSetBssid(pAd, pAd->CurrentAddress); + AsicSetMcastWC(pAd); + + /* 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. */ + RTMP_IO_WRITE32(pAd, MAC_WCID_BASE, 0x00); + RTMP_IO_WRITE32(pAd, MAC_WCID_BASE+4, 0x0); + + /* reset WCID table */ + for (idx=2; idx<255; idx++) + { + offset = MAC_WCID_BASE + (idx * HW_WCID_ENTRY_SIZE); + RTMP_IO_WRITE32(pAd, offset, 0x0); + RTMP_IO_WRITE32(pAd, offset+4, 0x0); + } + + 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;*/ + pAd->P2PChannel = pAd->CommonCfg.Channel; + + AsicBBPAdjust(pAd); + + /* Clear BG-Protection flag */ + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED + && pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + N_SetCenCh(pAd); + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + + MlmeSetTxPreamble(pAd, (USHORT)pAd->CommonCfg.TxPreamble); + MlmeUpdateTxRates(pAd, FALSE, MIN_NET_DEVICE_FOR_P2P_GO); +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.PhyMode > PHY_11G) + MlmeUpdateHtTxRates(pAd, MIN_NET_DEVICE_FOR_P2P_GO); +#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 */ + +#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 + */ + for (idx=2; idxMacTab.Content[idx].PortSecured = WPA_802_1X_PORT_NOT_SECURED; + AsicRemovePairwiseKeyEntry(pAd, (UCHAR)idx); + } + + { + USHORT Wcid = 0; + PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[MAIN_MBSSID]; + + pMbss->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + if (IS_WPA_CAPABILITY(pMbss->AuthMode)) + { + pMbss->DefaultKeyId = 1; + } + + /* Get a specific WCID to record this MBSS key attribute */ + GET_GroupKey_WCID(pAd, Wcid, MAIN_MBSSID); + + /* When WEP, TKIP or AES is enabled, set group key info to Asic */ + if (pMbss->WepStatus == Ndis802_11WEPEnabled) + { + UCHAR CipherAlg; + UCHAR idx_len; + + for (idx=0; idx < SHARE_KEY_NUM; idx++) + { + CipherAlg = pAd->SharedKey[MAIN_MBSSID + 1][idx].CipherAlg; + + if (pAd->SharedKey[MAIN_MBSSID + 1][idx].KeyLen > 0) + { + /* Set key material to Asic */ + RTMP_ASIC_SHARED_KEY_TABLE(pAd, + MAIN_MBSSID + 1, + idx, + &pAd->SharedKey[MAIN_MBSSID + 1][idx]); + + if (idx == pMbss->DefaultKeyId) + { + /* Generate 3-bytes IV randomly for software encryption using */ + for(idx_len = 0; idx_len < LEN_WEP_TSC; idx_len++) + pAd->SharedKey[MAIN_MBSSID + 1][idx].TxTsc[idx_len] = RandomByte(pAd); + + /* Update WCID attribute table and IVEIV table */ + RTMPSetWcidSecurityInfo(pAd, + MAIN_MBSSID + 1, + idx, + CipherAlg, + Wcid, + SHAREDKEYTABLE); + } + } + } + } + else if ((pMbss->WepStatus == Ndis802_11Encryption2Enabled) || + (pMbss->WepStatus == Ndis802_11Encryption3Enabled) || + (pMbss->WepStatus == Ndis802_11Encryption4Enabled)) + { + /* Generate GMK and GNonce randomly per MBSS */ + GenRandom(pAd, pMbss->Bssid, pMbss->GMK); + GenRandom(pAd, pMbss->Bssid, pMbss->GNonce); + + /* Derive GTK per BSSID */ + WpaDeriveGTK(pMbss->GMK, + (UCHAR*)pMbss->GNonce, + pMbss->Bssid, + pMbss->GTK, + LEN_TKIP_GTK); + + /* Install Shared key */ + WPAInstallSharedKey(pAd, + pMbss->GroupKeyWepStatus, + MAIN_MBSSID + 1, + pMbss->DefaultKeyId, + Wcid, + TRUE, + pMbss->GTK, + LEN_TKIP_GTK); + + } +#ifdef WAPI_SUPPORT + else if (pMbss->WepStatus == Ndis802_11EncryptionSMS4Enabled) + { + INT cnt; + + /* Initial the related variables */ + pMbss->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, + pMbss->GroupKeyWepStatus, + MAIN_MBSSID + 1, + pMbss->DefaultKeyId, + Wcid, + pMbss->GTK); + + } +#endif /* WAPI_SUPPORT */ + +#ifdef DOT1X_SUPPORT + /* Send singal to daemon to indicate driver had restarted */ + if ((pMbss->AuthMode == Ndis802_11AuthModeWPA) || (pMbss->AuthMode == Ndis802_11AuthModeWPA2) + || (pMbss->AuthMode == Ndis802_11AuthModeWPA1WPA2) || (pMbss->IEEE8021X == TRUE)) + { + ;/*bDot1xReload = TRUE; */ + } +#endif /* DOT1X_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("### BSS(%d) AuthMode(%d)=%s, WepStatus(%d)=%s , AccessControlList.Policy=%ld\n", MAIN_MBSSID + 1, pMbss->AuthMode, GetAuthMode(pMbss->AuthMode), + pMbss->WepStatus, GetEncryptType(pMbss->WepStatus), pMbss->AccessControlList.Policy)); + +#ifdef DOT1X_SUPPORT + /* Send internal command to DOT1X daemon for reloading configuration */ +/* + if (bDot1xReload) + DOT1X_InternalCmdAction(pAd, NULL, DOT1X_RELOAD_CONFIG); +*/ +#endif /* DOT1X_SUPPORT */ + + /* Disable Protection first. */ + /*AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT|CCKSETPROTECT|OFDMSETPROTECT), TRUE, FALSE); */ +#ifdef PIGGYBACK_SUPPORT + RTMPSetPiggyBack(pAd, pAd->CommonCfg.bPiggyBackCapable); +#endif /* PIGGYBACK_SUPPORT */ + + ApLogEvent(pAd, pAd->CurrentAddress, EVENT_RESET_ACCESS_POINT); + +#if defined(WSC_AP_SUPPORT) || defined(WSC_STA_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[MAIN_MBSSID].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("Generate UUID for apidx(%d)\n", MAIN_MBSSID)); + if (NdisEqualMemory(&pWscControl->Wsc_Uuid_E[0], zeros16, UUID_LEN_HEX)) + WscGenerateUUID(pAd, &pWscControl->Wsc_Uuid_E[0], &pWscControl->Wsc_Uuid_Str[0], MIN_NET_DEVICE_FOR_P2P_GO, FALSE); + WscInit(pAd, FALSE, MIN_NET_DEVICE_FOR_P2P_GO); + } +#endif /* defined(WSC_AP_SUPPORT) || defined(WSC_STA_SUPPORT) */ + } + + OPSTATUS_SET_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED); + +#ifndef DPA_S + RTMP_IndicateMediaState(pAd, NdisMediaStateConnected); +#endif /* !DPA_S */ + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + + + /*pAd->Dot11_H.RDMode = RD_NORMAL_MODE;*/ + /*AsicEnableP2PGoSync(pAd); */ + + /* start sending BEACON out */ + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); + + /*AsicEnableP2PGoSync(pAd); */ + + { + pAd->Dot11_H.RDMode = RD_NORMAL_MODE; + AsicEnableP2PGoSync(pAd); + +#ifdef CONFIG_AP_SUPPORT +#ifdef CARRIER_DETECTION_SUPPORT +#ifdef A_BAND_SUPPORT + if (pAd->CommonCfg.Channel > 14) + { + if ((pAd->CommonCfg.CarrierDetect.Enable == 0) + && ((pAd->CommonCfg.RDDurRegion == JAP) + || (pAd->CommonCfg.RDDurRegion == JAP_W53) + || (pAd->CommonCfg.RDDurRegion == JAP_W56))) + { + pAd->CommonCfg.CarrierDetect.Enable = 1; + } + } + else +#endif /* A_BAND_SUPPORT */ + { + if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) + { + if ((pAd->CommonCfg.CarrierDetect.Enable == 0) + && ((pAd->CommonCfg.RDDurRegion == JAP) + || (pAd->CommonCfg.RDDurRegion == JAP_W53) + || (pAd->CommonCfg.RDDurRegion == JAP_W56))) + { + pAd->CommonCfg.CarrierDetect.Enable = 1; + } + } + } + + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + { + /* trun on Carrier-Detection.*/ + CarrierDetectionStart(pAd); + } +#endif /* CARRIER_DETECTION_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + } + +#ifdef WAPI_SUPPORT + RTMPStartWapiRekeyTimerAction(pAd, NULL); +#endif /* WAPI_SUPPORT */ + + /* Pre-tbtt interrupt setting. */ + RTMP_IO_READ32(pAd, INT_TIMER_CFG, &Value); + Value &= 0xffff0000; + Value |= 6 << 4; /* Pre-TBTT is 6ms before TBTT interrupt. 1~10 ms is reasonable. */ + RTMP_IO_WRITE32(pAd, INT_TIMER_CFG, Value); + /* Enable pre-tbtt interrupt */ + RTMP_IO_READ32(pAd, INT_TIMER_EN, &Value); + Value |=0x1; + RTMP_IO_WRITE32(pAd, INT_TIMER_EN, Value); + + /* 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 MESH_SUPPORT + if (MESH_ON(pAd)) + MeshUp(pAd); +#endif /* MESH_SUPPORT */ + + +#ifdef DPA_S + if (pAd->ApCfg.MBSSID[0].WscControl.WscConfStatus == WSC_SCSTATE_CONFIGURED) + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_SOFTAP_READY, NULL, NULL, 0); +#endif /* DPA_S */ + + /* Start respons Auth Req. */ + pAd->P2pCfg.bStopAuthRsp = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("<=== P2P_GoStartUp\n")); +} + +VOID P2P_GoStop( + IN PRTMP_ADAPTER pAd) +{ + BOOLEAN Cancelled; + UINT32 Value; + INT apidx; + + DBGPRINT(RT_DEBUG_TRACE, ("===> P2P_GoStop\n")); + + pAd->P2pCfg.P2pCapability[1] &= ~(GRPCAP_OWNER); + + pAd->flg_p2p_OpStatusFlags &= P2P_FIXED_MODE; + + pAd->P2pCfg.Rule = P2P_IS_DEVICE; + + pAd->ApCfg.MBSSID[MAIN_MBSSID].bBcnSntReq = FALSE; + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); + +#ifdef DFS_SUPPORT + NewRadarDetectionStop(pAd); +#endif /* DFS_SUPPORT */ + +#ifdef MESH_SUPPORT + if (MESH_ON(pAd)) + MeshDown(pAd, TRUE); +#endif /* MESH_SUPPORT */ + +#ifdef WDS_SUPPORT + WdsDown(pAd); +#endif /* WDS_SUPPORT */ + + P2PMacTableReset(pAd); + + /* Disable pre-tbtt interrupt */ + RTMP_IO_READ32(pAd, INT_TIMER_EN, &Value); + Value &=0xe; + RTMP_IO_WRITE32(pAd, INT_TIMER_EN, Value); + + 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)) + { + /*RTMP_ASIC_INTERRUPT_DISABLE(pAd); */ + AsicDisableSync(pAd); + +#ifdef LED_CONTROL_SUPPORT + /* Set LED */ + RTMPSetLED(pAd, LED_LINK_DOWN); +#endif /* LED_CONTROL_SUPPORT */ + } + + + + for (apidx = 0; apidx < MAX_MBSSID_NUM(pAd); apidx++) + { + if (pAd->ApCfg.MBSSID[apidx].REKEYTimerRunning == TRUE) + { + RTMPCancelTimer(&pAd->ApCfg.MBSSID[apidx].REKEYTimer, &Cancelled); + pAd->ApCfg.MBSSID[apidx].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 DPA_S + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_SOFTAP_STOP, NULL, NULL, 0); +#endif /* DPA_S */ + + DBGPRINT(RT_DEBUG_TRACE, ("<=== P2P_GoStop\n")); +} + +VOID P2P_CliStartUp( + IN PRTMP_ADAPTER pAd) +{ + UCHAR ifIndex; + PAPCLI_STRUCT pApCliEntry; + + /* 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; + + pAd->P2pCfg.P2pCapability[1] &= ~(GRPCAP_OWNER); + pAd->flg_p2p_OpStatusFlags = P2P_CLI_UP; + pAd->P2pCfg.Rule = P2P_IS_CLIENT; + pAd->StaCfg.bAutoReconnect = FALSE; + AsicSetBssid(pAd, pAd->CurrentAddress); + AsicSetMcastWC(pAd); + + for(ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + if (pAd->CommonCfg.Channel != 0) + pAd->P2PChannel = pAd->CommonCfg.Channel; + else + pAd->P2PChannel = FirstChannel(pAd); + + if (APCLI_IF_UP_CHECK(pAd, ifIndex) + && (pApCliEntry->Enable == TRUE) + && (pApCliEntry->Valid == FALSE)) + { + 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); + } + } + + OPSTATUS_SET_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED); + + return; +} + +VOID P2P_CliStop( + IN PRTMP_ADAPTER pAd) +{ + UCHAR ifIndex; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: ===>\n", __FUNCTION__)); + + /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_P2P_CLI); */ + pAd->flg_p2p_OpStatusFlags = P2P_DISABLE; + pAd->P2pCfg.Rule = P2P_IS_DEVICE; + for (ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) + { + /* send disconnect-req to sta State Machine. */ + if (pAd->ApCfg.ApCliTab[ifIndex].Enable) + { + 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)); + } + } + + OPSTATUS_CLEAR_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED); + + +} + +/* + ========================================================================== + 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 P2PMacTableMaintenance( + IN PRTMP_ADAPTER pAd) +{ + int i, FirstWcid; +#ifdef DOT11_N_SUPPORT + ULONG MinimumAMPDUSize = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor; /*Default set minimum AMPDU Size to 2, i.e. 32K */ + BOOLEAN bRdgActive; +#endif /* DOT11_N_SUPPORT */ +#ifdef RTMP_MAC_PCI + unsigned long IrqFlags; +#endif /* RTMP_MAC_PCI */ + UINT fAnyStationPortSecured[MAX_MBSSID_NUM(pAd)]; + UINT bss_index; + MAC_TABLE *pMacTable; + + FirstWcid = 2; + + for (bss_index = BSS0; bss_index < MAX_MBSSID_NUM(pAd); bss_index++) + fAnyStationPortSecured[bss_index] = 0; + + 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 */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef WAPI_SUPPORT + pMacTable->fAnyWapiStation = FALSE; +#endif /* WAPI_SUPPORT */ + + for (i = FirstWcid; i < MAX_LEN_OF_MAC_TABLE; i++) + { + MAC_TABLE_ENTRY *pEntry = &pMacTable->Content[i]; + + BOOLEAN bDisconnectSta = FALSE; + + if (!IS_ENTRY_CLIENT(pEntry)) + continue; + + if (pEntry->NoDataIdleCount == 0) + pEntry->StationKeepAliveCount = 0; + + pEntry->NoDataIdleCount ++; + pEntry->StaConnectTime ++; + + /* 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", + pEntry->Addr[0],pEntry->Addr[1],pEntry->Addr[2],pEntry->Addr[3], + pEntry->Addr[4],pEntry->Addr[5],MAC_TABLE_ASSOC_TIMEOUT)); + MacTableDeleteEntry(pAd, pEntry->Aid, 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 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; + + if (!INFRA_ON(pAd)) + { +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.IOTestParm.bRTSLongProtOn == FALSE) + AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, FALSE, pMacTable->fAnyStationNonGF); +#endif /* DOT11_N_SUPPORT */ + +#ifndef DOT11N_SS3_SUPPORT + if (pEntry->WepStatus != Ndis802_11EncryptionDisabled) + { + pMacTable->fAnyTxOPForceDisable = TRUE; + } +#endif /* DOT11N_SS3_SUPPORT */ + } + } + + /* detect the station alive status */ + /* detect the station alive status */ + if ((pAd->ApCfg.MBSSID[pEntry->apidx].StationKeepAliveTime > 0) && + (pEntry->NoDataIdleCount >= pAd->ApCfg.MBSSID[pEntry->apidx].StationKeepAliveTime)) + { + MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[pEntry->apidx]; + + /* + 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 dont 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) + { +#ifdef P2P_SUPPORT + /* Modify for P2P test plan 6.1.11 /6.1.12, enqueue null frame will influence the test item */ + if (pAd->P2pCfg.bSigmaEnabled == FALSE) + { +#endif /* P2P_SUPPORT */ + 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; + + ApEnqueueNullFrame(pAd, pEntry->Addr, pEntry->CurrTxRate, + pEntry->Aid, pEntry->apidx, bQosNull, TRUE, 0); + } +#ifdef P2P_SUPPORT + } +#endif /* P2P_SUPPORT */ + } + 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) + { + bDisconnectSta = TRUE; + DBGPRINT(RT_DEBUG_WARN, ("ageout %02x:%02x:%02x:%02x:%02x:%02x after %d-sec silence\n", + pEntry->Addr[0],pEntry->Addr[1],pEntry->Addr[2],pEntry->Addr[3], + pEntry->Addr[4],pEntry->Addr[5],pEntry->StaIdleTimeout)); + ApLogEvent(pAd, pEntry->Addr, EVENT_AGED_OUT); + } + 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; + DBGPRINT(RT_DEBUG_WARN, ("STA-%02x:%02x:%02x:%02x:%02x:%02x had left\n", + pEntry->Addr[0],pEntry->Addr[1],pEntry->Addr[2],pEntry->Addr[3], + pEntry->Addr[4],pEntry->Addr[5])); + } + } + + 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 %02x:%02x:%02x:%02x:%02x:%02x. \n",Reason, PRINT_MAC(pEntry->Addr))); + MgtMacHeaderInit(pAd, &DeAuthHdr, SUBTYPE_DEAUTH, 0, pEntry->Addr, +#ifdef P2P_SUPPORT + pAd->ApCfg.MBSSID[pEntry->apidx].Bssid, +#endif /* P2P_SUPPORT */ + pAd->ApCfg.MBSSID[pEntry->apidx].Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DeAuthHdr, + 2, &Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + + MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr); + continue; + } + + /* 3. garbage collect the PsQueue if the STA has being idle for a while */ + if (pEntry->PsQueue.Head) + { + pEntry->PsQIdleCount ++; + if (pEntry->PsQIdleCount > 2) + { + NdisAcquireSpinLock(&pAd->irq_lock); + APCleanupPsQueue(pAd, &pEntry->PsQueue); + NdisReleaseSpinLock(&pAd->irq_lock); + 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->Aid, pEntry->apidx); + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ +#ifdef WAPI_SUPPORT + if (pEntry->WepStatus == Ndis802_11EncryptionSMS4Enabled) + pMacTable->fAnyWapiStation = TRUE; +#endif /* WAPI_SUPPORT */ + + } + + /* Update the state of port per MBSS */ + for (bss_index = BSS0; bss_index < MAX_MBSSID_NUM(pAd); bss_index++) + { + if (fAnyStationPortSecured[bss_index] > 0) + { + pAd->ApCfg.MBSSID[bss_index].PortSecured = WPA_802_1X_PORT_SECURED; + } + else + pAd->ApCfg.MBSSID[bss_index].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) + { + bRdgActive = TRUE; + } + else + { + bRdgActive = FALSE; + } +#ifdef DOT11_N_SUPPORT +#ifdef GREENAP_SUPPORT + if (pAd->CommonCfg.PhyMode>=PHY_11ABGN_MIXED) + { + 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)) + { + if (bRdgActive) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); + AsicEnableRDG(pAd); + } + else + { + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); + AsicDisableRDG(pAd); + } + } +#endif /* DOT11_N_SUPPORT */ + + + if (!INFRA_ON(pAd)) + { + 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 ++; + if (pMacTable->PsQIdleCount > 1) + { + + /*NdisAcquireSpinLock(&pAd->MacTabLock); */ + APCleanupPsQueue(pAd, &pMacTable->McastPsQueue); + /*NdisReleaseSpinLock(&pAd->MacTabLock); */ + pMacTable->PsQIdleCount = 0; + + /* sanity check */ + if (pAd->ApCfg.BssidNum > MAX_MBSSID_NUM(pAd)) + pAd->ApCfg.BssidNum = MAX_MBSSID_NUM(pAd); + /* End of if */ + + /* clear MCAST/BCAST backlog bit for all BSS */ + for(bss_index=BSS0; bss_indexApCfg.BssidNum; bss_index++) + WLAN_MR_TIM_BCMC_CLEAR(bss_index); + /* End of for */ + } + } + else + pMacTable->PsQIdleCount = 0; +#ifdef RTMP_MAC_PCI + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); +#endif /* RTMP_MAC_PCI */ +} + +VOID AsicEnableP2PGoSync( + IN PRTMP_ADAPTER pAd) +{ + BCN_TIME_CFG_STRUC csr; + + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); + + + /* start sending BEACON */ + 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 in IBSS mode */ + csr.field.bTBTTEnable = 1; + csr.field.bBeaconGen = 1; + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); +} + +VOID MgtMacP2PHeaderInit( + 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 = BTYPE_MGMT; + pHdr80211->FC.SubType = SubType; + pHdr80211->FC.ToDs = ToDs; + COPY_MAC_ADDR(pHdr80211->Addr1, pDA); + COPY_MAC_ADDR(pHdr80211->Addr2, pBssid); + COPY_MAC_ADDR(pHdr80211->Addr3, pBssid); +} + +/* + ========================================================================== + Description: + This routine reset the entire MAC table. All packets pending in + the power-saving queues are freed here. + ========================================================================== + */ +VOID P2PMacTableReset( + IN PRTMP_ADAPTER pAd) +{ + int i, FirstWcid; + BOOLEAN Cancelled; +#ifdef CONFIG_AP_SUPPORT +#ifdef RTMP_MAC_PCI + unsigned long IrqFlags; +#endif /* RTMP_MAC_PCI */ + PUCHAR 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 *pEntry = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n")); + /*NdisAcquireSpinLock(&pAd->MacTabLock); */ + + + FirstWcid = 2; + + for (i = FirstWcid; i < MAX_LEN_OF_MAC_TABLE; i++) + { + pEntry = &pAd->MacTab.Content[i]; + + if (IS_ENTRY_CLIENT(pEntry)) + { + /* Delete a entry via WCID */ + + /*MacTableDeleteEntry(pAd, i, pAd->MacTab.Content[i].Addr); */ + RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); + +#ifdef CONFIG_STA_SUPPORT +#ifdef ADHOC_WPA2PSK_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + RTMPCancelTimer(&pEntry->WPA_Authenticator.MsgRetryTimer, &Cancelled); + } +#endif /* ADHOC_WPA2PSK_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; + +#ifdef CONFIG_AP_SUPPORT + if ((pAd->OpMode == OPMODE_AP) || IS_P2P_GO_ENTRY(pEntry)) + { + /* Before reset MacTable, send disassociation packet to client. */ + if (pEntry->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 frame tO %02x:%02x:%02x:%02x:%02x:%02x \n", + Reason, PRINT_MAC(pAd->MacTab.Content[i].Addr))); + + MgtMacHeaderInit(pAd, &DeAuthHdr, SUBTYPE_DEAUTH, 0, pEntry->HdrAddr1, +#ifdef P2P_SUPPORT + pEntry->HdrAddr2, +#endif /* P2P_SUPPORT */ + pEntry->HdrAddr3); + 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, pEntry->Addr); + } + NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); + } + +#ifdef CONFIG_AP_SUPPORT + { + for (apidx = MAIN_MBSSID; apidx < pAd->ApCfg.BssidNum; apidx++) + { +#ifdef WSC_AP_SUPPORT + PWSC_CTRL pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + BOOLEAN Cancelled; + + RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); + pWscControl->EapolTimerRunning = FALSE; + NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN); + pWscControl->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 %ld...\n",pAd->MacTab.McastPsQueue.Number)); + if (pAd->MacTab.McastPsQueue.Number > 0) + APCleanupPsQueue(pAd, &pAd->MacTab.McastPsQueue); + DBGPRINT(RT_DEBUG_TRACE, ("2McastPsQueue.Number %ld...\n",pAd->MacTab.McastPsQueue.Number)); + + /*NdisZeroMemory(&pAd->MacTab, sizeof(MAC_TABLE)); */ + InitializeQueueHeader(&pAd->MacTab.McastPsQueue); +#ifdef RTMP_MAC_PCI + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); +#endif /* RTMP_MAC_PCI */ + } +#endif /* CONFIG_AP_SUPPORT */ + return; +} + +VOID P2PChannelInit( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex) +{ + if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { +#ifdef DOT11_N_SUPPORT + ADD_HTINFO RootApHtInfo, HtInfo; + + HtInfo = pAd->CommonCfg.AddHTInfo.AddHtInfo; + RootApHtInfo = pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.AddHtInfo.AddHtInfo; + + if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && + (RootApHtInfo.RecomWidth) && + (RootApHtInfo.ExtChanOffset != HtInfo.ExtChanOffset)) + { + if (RootApHtInfo.ExtChanOffset == EXTCHA_ABOVE) + Set_HtExtcha_Proc(pAd, "1"); + else + Set_HtExtcha_Proc(pAd, "0"); + } + + N_ChannelCheck(pAd); +#endif /* DOT11_N_SUPPORT */ + { + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + } + } +} + +VOID P2PCfgInit( + IN PRTMP_ADAPTER pAd) +{ + UCHAR apcliIdx, apidx = MAIN_MBSSID; + + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeOpen; + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11EncryptionDisabled; + pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus = Ndis802_11EncryptionDisabled; + pAd->ApCfg.MBSSID[apidx].DefaultKeyId = 0; + pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher = MIX_CIPHER_NOTUSE; + +#ifdef DOT1X_SUPPORT + pAd->ApCfg.MBSSID[apidx].IEEE8021X = FALSE; + pAd->ApCfg.MBSSID[apidx].PreAuth = FALSE; + + /* PMK cache setting */ + pAd->ApCfg.MBSSID[apidx].PMKCachePeriod = (10 * 60 * OS_HZ); /* unit : tick(default: 10 minute) */ + NdisZeroMemory(&pAd->ApCfg.MBSSID[apidx].PMKIDCache, sizeof(NDIS_AP_802_11_PMKID)); + + /* dot1x related per BSS */ + pAd->ApCfg.MBSSID[apidx].radius_srv_num = 0; + pAd->ApCfg.MBSSID[apidx].NasIdLen = 0; +#endif /* DOT1X_SUPPORT */ + + /* VLAN related */ + pAd->ApCfg.MBSSID[apidx].VLAN_VID = 0; + + /* Default MCS as AUTO */ + pAd->ApCfg.MBSSID[apidx].bAutoTxRateSwitch = TRUE; + pAd->ApCfg.MBSSID[apidx].DesiredTransmitSetting.field.MCS = MCS_AUTO; + + /* Default is zero. It means no limit. */ + pAd->ApCfg.MBSSID[apidx].MaxStaNum = 0; + pAd->ApCfg.MBSSID[apidx].StaCount = 0; + +#ifdef P2P_SUPPORT +#ifdef APCLI_SUPPORT + for(apcliIdx = 0; apcliIdx < MAX_APCLI_NUM; apcliIdx++) + { + pAd->ApCfg.ApCliTab[apcliIdx].AuthMode = Ndis802_11AuthModeOpen; + pAd->ApCfg.ApCliTab[apcliIdx].WepStatus = Ndis802_11WEPDisabled; + } +#endif /* APCLI_SUPPORT */ +#endif /* P2P_SUPPORT */ + + for(apcliIdx = 0; apcliIdx < WLAN_MAX_NUM_OF_TIM; apcliIdx++) + pAd->ApCfg.MBSSID[apidx].TimBitmaps[apcliIdx] = 0; + + P2pGotoIdle(pAd); +} + +VOID P2PInitChannelRelatedValue( + IN PRTMP_ADAPTER pAd) +{ +} + +/* + ======================================================================== + + Routine Description: + Verify the support rate for different PHY type + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +VOID P2PUpdateMlmeRate( + IN PRTMP_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; + + switch (pAd->CommonCfg.PhyMode) + { + case PHY_11B: + ProperMlmeRate = RATE_11; + MinimumRate = RATE_1; + break; + case PHY_11BG_MIXED: +#ifdef DOT11_N_SUPPORT + case PHY_11ABGN_MIXED: + case PHY_11BGN_MIXED: +#endif /* DOT11_N_SUPPORT */ + if ((pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.SupRateLen == 4) && + (pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.ExtRateLen == 0)) + /* B only AP */ + ProperMlmeRate = RATE_11; + else + ProperMlmeRate = RATE_24; + + if (pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Channel <= 14) + MinimumRate = RATE_1; + else + MinimumRate = RATE_6; + break; + case PHY_11A: +#ifdef DOT11_N_SUPPORT + case PHY_11N_2_4G: /* rt2860 need to check mlmerate for 802.11n */ + case PHY_11GN_MIXED: + case PHY_11AGN_MIXED: + case PHY_11AN_MIXED: + case PHY_11N_5G: +#endif /* DOT11_N_SUPPORT */ + ProperMlmeRate = RATE_24; + MinimumRate = RATE_6; + break; + case PHY_11ABG_MIXED: + ProperMlmeRate = RATE_24; + if (pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Channel <= 14) + MinimumRate = RATE_1; + else + MinimumRate = RATE_6; + break; + default: /* error */ + ProperMlmeRate = RATE_1; + MinimumRate = RATE_1; + break; + } + + for (i = 0; i < pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.SupRateLen; i++) + { + for (j = 0; j < RateIdx; j++) + { + if ((pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j]) + { + if (j == ProperMlmeRate) + { + bMatch = TRUE; + break; + } + } + } + + if (bMatch) + break; + } + + if (bMatch == FALSE) + { + for (i = 0; i < pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.ExtRateLen; i++) + { + for (j = 0; j < RateIdx; j++) + { + if ((pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.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_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, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word)); +} + + +/* + ========================================================================== + Description: + Shutdown AP and free AP specific resources + ========================================================================== + */ +VOID P2PAPShutdown( + IN PRTMP_ADAPTER pAd) +{ + DBGPRINT(RT_DEBUG_TRACE, ("---> P2PAPShutdown\n")); + +#ifdef RTMP_MAC_PCI + APStop(pAd); +#endif /* RTMP_MAC_PCI */ + + MlmeRadioOff(pAd); + +#ifdef IGMP_SNOOP_SUPPORT + MultiCastFilterTableReset(&pAd->pMulticastFilterTable); +#endif /* IGMP_SNOOP_SUPPORT */ + + NdisFreeSpinLock(&pAd->MacTabLock); + + DBGPRINT(RT_DEBUG_TRACE, ("<--- P2PAPShutdown\n")); +} + +VOID P2PUserCfgInit( + IN PRTMP_ADAPTER pAd) +{ + UINT i, j; + + /* Set MBSS Default Configurations */ + pAd->ApCfg.BssidNum = MAX_MBSSID_NUM(pAd); + for(j = BSS0; j < pAd->ApCfg.BssidNum; j++) + { + pAd->ApCfg.MBSSID[j].AuthMode = Ndis802_11AuthModeOpen; + pAd->ApCfg.MBSSID[j].WepStatus = Ndis802_11EncryptionDisabled; + pAd->ApCfg.MBSSID[j].GroupKeyWepStatus = Ndis802_11EncryptionDisabled; + pAd->ApCfg.MBSSID[j].DefaultKeyId = 0; + pAd->ApCfg.MBSSID[j].WpaMixPairCipher = MIX_CIPHER_NOTUSE; + +#ifdef DOT1X_SUPPORT + pAd->ApCfg.MBSSID[j].IEEE8021X = FALSE; + pAd->ApCfg.MBSSID[j].PreAuth = FALSE; + + /* PMK cache setting */ + pAd->ApCfg.MBSSID[j].PMKCachePeriod = (10 * 60 * OS_HZ); /* unit : tick(default: 10 minute) */ + NdisZeroMemory(&pAd->ApCfg.MBSSID[j].PMKIDCache, sizeof(NDIS_AP_802_11_PMKID)); + + /* dot1x related per BSS */ + pAd->ApCfg.MBSSID[j].radius_srv_num = 0; + pAd->ApCfg.MBSSID[j].NasIdLen = 0; +#endif /* DOT1X_SUPPORT */ + + /* VLAN related */ + pAd->ApCfg.MBSSID[j].VLAN_VID = 0; + + /* Default MCS as AUTO */ + pAd->ApCfg.MBSSID[j].bAutoTxRateSwitch = TRUE; + pAd->ApCfg.MBSSID[j].DesiredTransmitSetting.field.MCS = MCS_AUTO; + + /* Default is zero. It means no limit. */ + pAd->ApCfg.MBSSID[j].MaxStaNum = 0; + pAd->ApCfg.MBSSID[j].StaCount = 0; + +#ifdef WSC_AP_SUPPORT + { + 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 = &pAd->ApCfg.MBSSID[j].WscControl; + NdisZeroMemory(&pWscControl->RegData, sizeof(WSC_REG_DATA)); + NdisZeroMemory(&pAd->CommonCfg.WscStaPbcProbeInfo, sizeof(WSC_STA_PBC_PROBE_INFO)); + pWscControl->WscMode = 1; + pWscControl->WscConfStatus = 1; + pWscControl->WscConfigMethods= 0x0184; + 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; + +#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; +#endif /* WSC_V2_SUPPORT */ + } +#endif /* WSC_AP_SUPPORT */ + +#ifdef EASY_CONFIG_SETUP + AutoProvisionGenWpsPTK(pAd, j); + pAd->ApCfg.MBSSID[j].EasyConfigInfo.RssiThreshold = -50; + pAd->ApCfg.MBSSID[j].EasyConfigInfo.bEnable = TRUE; + NdisZeroMemory(pAd->ApCfg.MBSSID[j].EasyConfigInfo.WpsPinCode, MAC_ADDR_LEN); +#endif /* EASY_CONFIG_SETUP */ + + for(i = 0; i < WLAN_MAX_NUM_OF_TIM; i++) + pAd->ApCfg.MBSSID[j].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 WSC_INCLUDED + pAd->WriteWscCfgToDatFile = 0xFF; + pAd->WriteWscCfgToAr9DatFile = FALSE; +#ifdef CONFIG_AP_SUPPORT + pAd->bWscDriverAutoUpdateCfg = TRUE; +#ifdef RTMP_RBUS_SUPPORT + if (pAd->infType == RTMP_DEV_INF_RBUS) + /* Update PortCfg by WebUI */ + pAd->bWscDriverAutoUpdateCfg = FALSE; +#endif +#endif /* CONFIG_AP_SUPPORT */ +#endif /* WSC_INCLUDED */ + + for(j = 0; j < MAX_APCLI_NUM; j++) + { + pAd->ApCfg.ApCliTab[j].AuthMode = Ndis802_11AuthModeOpen; + pAd->ApCfg.ApCliTab[j].WepStatus = Ndis802_11WEPDisabled; + pAd->ApCfg.ApCliTab[j].bAutoTxRateSwitch = TRUE; + pAd->ApCfg.ApCliTab[j].DesiredTransmitSetting.field.MCS = MCS_AUTO; + } + + { + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + pP2PCtrl->P2p_OpMode = P2P_CONCURRENT; + + pP2PCtrl->bKeepSlient = FALSE; + pP2PCtrl->NoAIndex = MAX_P2P_GROUP_SIZE; +/* pP2PCtrl->PortNumber = 0; */ + pP2PCtrl->ListenChannel = 1; + pP2PCtrl->GroupChannel = 11; + pP2PCtrl->GroupOpChannel = 11; + P2pSetListenIntBias(pAd, 3); + pP2PCtrl->DeviceNameLen = 10; + pP2PCtrl->DeviceName[0] = 'R'; + pP2PCtrl->DeviceName[1] = 'a'; + pP2PCtrl->DeviceName[2] = 'l'; + pP2PCtrl->DeviceName[3] = 'i'; + pP2PCtrl->DeviceName[4] = 'n'; + pP2PCtrl->DeviceName[5] = 'k'; + pP2PCtrl->DeviceName[6] = '-'; + pP2PCtrl->DeviceName[7] = 'P'; + pP2PCtrl->DeviceName[8] = 0x32; + pP2PCtrl->DeviceName[9] = 'P'; + +/* pP2PCtrl->P2PDiscoProvState = P2P_DISABLE; */ + pP2PCtrl->P2PConnectState = P2P_CONNECT_IDLE; + /* Set Dpid to "not specified". it means, GUI doesn't set for connection yet. */ + pP2PCtrl->Dpid = DEV_PASS_ID_NOSPEC; + pP2PCtrl->P2pManagedParm.APP2pManageability = 0xff; + pP2PCtrl->P2pManagedParm.ICSStatus = ICS_STATUS_DISABLED; + P2pGroupTabInit(pAd); + P2pCrednTabClean(pAd); + P2pScanChannelDefault(pAd); + RTMPMoveMemory(pAd->P2pCfg.SSID, WILDP2PSSID, WILDP2PSSIDLEN); +/* RTMPMoveMemory(pAd->P2pCfg.Bssid, pAd->P2pCfg.CurrentAddress, MAC_ADDR_LEN); */ + pP2PCtrl->SSIDLen = WILDP2PSSIDLEN; + pP2PCtrl->GONoASchedule.bValid = FALSE; + pP2PCtrl->GONoASchedule.bInAwake = TRUE; + pP2PCtrl->GONoASchedule.bWMMPSInAbsent = FALSE; /* Set to FALSE if changes state to Awake */ + pP2PCtrl->GONoASchedule.Token = 0; + pP2PCtrl->GoIntentIdx = 0; + pP2PCtrl->Rule = P2P_IS_DEVICE; + pP2PCtrl->WscMode = WSC_PIN_MODE; + pP2PCtrl->DefaultConfigMethod = P2P_REG_CM_DISPLAY; + pP2PCtrl->bExtListen = FALSE; + pP2PCtrl->bIntraBss = FALSE; + pP2PCtrl->ExtListenInterval = P2P_EXT_LISTEN_INTERVAL; + pP2PCtrl->ExtListenPeriod = P2P_EXT_LISTEN_PERIOD; + pP2PCtrl->GONoASchedule.Count = 0; + pP2PCtrl->GONoASchedule.Duration = 0; + pP2PCtrl->GONoASchedule.Interval = 0; + } +} + +VOID P2pInit( + IN PRTMP_ADAPTER pAd, + IN RTMP_OS_NETDEV_OP_HOOK *pNetDevOps) +{ + PNET_DEV new_dev_p; + APCLI_STRUCT *pApCliEntry; + + /* sanity check to avoid redundant virtual interfaces are created */ + if (pAd->flg_p2p_init != FALSE) + return; + /* End of if */ + + DBGPRINT(RT_DEBUG_TRACE, ("%s --->\n", __FUNCTION__)); + + /* init */ + pAd->ApCfg.MBSSID[MAIN_MBSSID].MSSIDDev = NULL; + pAd->ApCfg.ApCliTab[MAIN_MBSSID].dev = NULL; + pApCliEntry = &pAd->ApCfg.ApCliTab[MAIN_MBSSID]; + + /* create virtual network interface */ + { + UINT32 MC_RowID = 0, IoctlIF = 0; + new_dev_p = RtmpOSNetDevCreate(MC_RowID, &IoctlIF, INT_P2P, MAIN_MBSSID, sizeof(PRTMP_ADAPTER), INF_P2P_DEV_NAME); + + if (new_dev_p == NULL) + { + /* allocation fail, exit */ + DBGPRINT(RT_DEBUG_ERROR, ("Allocate network device fail (MBSS)...\n")); + return; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Register P2P IF (%s)\n", RTMP_OS_NETDEV_GET_DEVNAME(new_dev_p))); + } + + RTMP_OS_NETDEV_SET_PRIV(new_dev_p, pAd); + + + pNetDevOps->priv_flags = INT_P2P; /* We are virtual interface */ + pNetDevOps->needProtcted = TRUE; + + /* Init MAC address of virtual network interface */ + COPY_MAC_ADDR(pAd->P2PCurrentAddress, pAd->CurrentAddress); + /* + 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) + pAd->P2PCurrentAddress[0] += 2; + else + { +#ifdef P2P_ODD_MAC_ADJUST + if (pAd->P2PCurrentAddress[5] & 0x01 == 0x01) + pAd->P2PCurrentAddress[5] -= 1; + else +#endif /* P2P_ODD_MAC_ADJUST */ + pAd->P2PCurrentAddress[5] += FIRST_MBSSID; + } + NdisMoveMemory(&pNetDevOps->devAddr[0], &pAd->P2PCurrentAddress[0], MAC_ADDR_LEN); + + /* backup our virtual network interface */ + pAd->ApCfg.MBSSID[MAIN_MBSSID].MSSIDDev = new_dev_p; + COPY_MAC_ADDR(pAd->ApCfg.MBSSID[MAIN_MBSSID].Bssid, pAd->P2PCurrentAddress); + + pApCliEntry->dev = new_dev_p; + COPY_MAC_ADDR(pApCliEntry->CurrentAddress, pAd->P2PCurrentAddress); + + COPY_MAC_ADDR(pAd->P2pCfg.CurrentAddress, pAd->P2PCurrentAddress); + pAd->p2p_dev = new_dev_p; + + /* register this device to OS */ + RtmpOSNetDevAttach(pAd->OpMode, new_dev_p, pNetDevOps); + } + + pAd->CommonCfg.BeaconPeriod = 100; + pAd->ApCfg.DtimPeriod = 1; + pAd->CommonCfg.DisableOLBCDetect = 0; + + P2pGetRandomSSID(pAd, pAd->ApCfg.MBSSID[MAIN_MBSSID].Ssid, &(pAd->ApCfg.MBSSID[MAIN_MBSSID].SsidLen)); + pAd->ApCfg.MBSSID[MAIN_MBSSID].AuthMode = Ndis802_11AuthModeOpen; + pAd->ApCfg.MBSSID[MAIN_MBSSID].WepStatus = Ndis802_11EncryptionDisabled; + pAd->ApCfg.MBSSID[MAIN_MBSSID].DesiredTransmitSetting.field.MCS = pAd->StaCfg.DesiredTransmitSetting.field.MCS; + + if ((pAd->CommonCfg.bWmmCapable) || (pAd->CommonCfg.PhyMode > PHY_11G)) + pAd->ApCfg.MBSSID[MAIN_MBSSID].bWmmCapable = TRUE; + + /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_P2P_GO); */ + /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_P2P_CLI); */ + + pAd->flg_p2p_init = TRUE; + pAd->ApCfg.ApCliTab[MAIN_MBSSID].AuthMode = Ndis802_11AuthModeOpen; + pAd->ApCfg.ApCliTab[MAIN_MBSSID].WepStatus = Ndis802_11WEPDisabled; + pAd->ApCfg.ApCliTab[MAIN_MBSSID].DesiredTransmitSetting.field.MCS = pAd->StaCfg.DesiredTransmitSetting.field.MCS; + RTMPSetIndividualHT(pAd, MIN_NET_DEVICE_FOR_APCLI); + pAd->flg_apcli_init = TRUE; + + pAd->flg_p2p_OpStatusFlags = P2P_DISABLE; + +} + +INT P2P_OpenPre( + IN PNET_DEV pDev) +{ + PRTMP_ADAPTER pAd; + + + pAd = RTMP_OS_NETDEV_GET_PRIV(pDev); + if (ADHOC_ON(pAd)) + return -1; + + pAd->ApCfg.MBSSID[MAIN_MBSSID].bBcnSntReq = FALSE; + return 0; +} + +INT P2P_OpenPost( + IN PNET_DEV pDev) +{ + PRTMP_ADAPTER pAd; + PMULTISSID_STRUCT pMbss; + + pAd = RTMP_OS_NETDEV_GET_PRIV(pDev); + + if (ADHOC_ON(pAd)) + return -1; + + pMbss = &pAd->ApCfg.MBSSID[MAIN_MBSSID]; + /* 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(pMbss->Bssid, pAd->CurrentAddress); + + /* + 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) + pMbss->Bssid[MAIN_MBSSID] += 2; + else + { +#ifdef P2P_ODD_MAC_ADJUST + if ((pMbss->Bssid[5] & 0x01) == 0x01) + pMbss->Bssid[5] -= 1; + else +#endif /* P2P_ODD_MAC_ADJUST */ + pMbss->Bssid[5] += FIRST_MBSSID; + } + if (pMbss->MSSIDDev != NULL) + { + NdisMoveMemory(RTMP_OS_NETDEV_GET_PHYADDR(pMbss->MSSIDDev), + pMbss->Bssid, + MAC_ADDR_LEN); + } + + P2PCfgInit(pAd); + /*P2P_GoStartUp(pAd, MAIN_MBSSID); */ + /*P2P_CliStartUp(pAd); */ + + /* P2P Enable */ + P2pEnable(pAd); + + NdisAllocateSpinLock(pAd, &pAd->P2pTableSemLock); + + return 0; +} + +INT P2P_Close( + IN PNET_DEV pDev) +{ + PRTMP_ADAPTER pAd; + + pAd = RTMP_OS_NETDEV_GET_PRIV(pDev); + + if (P2P_CLI_ON(pAd)) + P2P_CliStop(pAd); + else if (P2P_GO_ON(pAd)) + P2P_GoStop(pAd); + + P2pGroupTabDisconnect(pAd, FALSE); + { + UINT32 Value; + /* Disable pre-tbtt interrupt */ + RTMP_IO_READ32(pAd, INT_TIMER_EN, &Value); + Value &=0xe; + RTMP_IO_WRITE32(pAd, INT_TIMER_EN, Value); + } + + /*update beacon Sync */ + /*if rausb0 is up => stop beacon */ + /*if rausb0 is down => we will call AsicDisableSync() in usb_rtusb_close_device() */ + if (INFRA_ON(pAd)) + AsicEnableBssSync(pAd); + else if (ADHOC_ON(pAd)) + AsicEnableIbssSync(pAd); + else + AsicDisableSync(pAd); + + NdisFreeSpinLock(&pAd->P2pTableSemLock); + return 0; +} + +VOID P2P_Remove( + IN PRTMP_ADAPTER pAd) +{ + MULTISSID_STRUCT *pMbss; + + + if (pAd->p2p_dev) + { + RtmpOSNetDevDetach(pAd->p2p_dev); + RtmpOSNetDevFree(pAd->p2p_dev); + + /* clear it as NULL to prevent latter access error */ + pAd->p2p_dev = NULL; + pAd->flg_p2p_init = FALSE; + + pMbss = &pAd->ApCfg.MBSSID[MAIN_MBSSID]; + pMbss->MSSIDDev = NULL; + + pAd->ApCfg.ApCliTab[MAIN_MBSSID].dev = NULL; + pAd->flg_apcli_init = FALSE; + } + + +} /* End of P2P_Remove */ + +int P2P_PacketSend( + IN PNDIS_PACKET pPktSrc, + IN PNET_DEV pDev, + IN RTMP_NET_PACKET_TRANSMIT Func) +{ + PRTMP_ADAPTER pAd; + PAPCLI_STRUCT pApCli; + + + pAd = RTMP_OS_NETDEV_GET_PRIV(pDev); + ASSERT(pAd); + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + RELEASE_NDIS_PACKET(pAd, pPktSrc, NDIS_STATUS_FAILURE); + return 0; + } +#endif /* RALINK_ATE */ + if ((RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))) + { + /* wlan is scanning/disabled/reset */ + RELEASE_NDIS_PACKET(pAd, pPktSrc, NDIS_STATUS_FAILURE); + /*printk("1. P2P_VirtualIF_PacketSend @@@@@\n"); */ + return 0; + } + + if(!(RTMP_OS_NETDEV_STATE_RUNNING(pDev))) + { + /* the interface is down */ + RELEASE_NDIS_PACKET(pAd, pPktSrc, NDIS_STATUS_FAILURE); + /*printk("2. P2P_VirtualIF_PacketSend @@@@@\n"); */ + return 0; + } + + if (P2P_CLI_ON(pAd)) + { + pApCli = (PAPCLI_STRUCT)&pAd->ApCfg.ApCliTab; + + if (pApCli[MAIN_MBSSID].Valid != TRUE) + { + RELEASE_NDIS_PACKET(pAd, pPktSrc, NDIS_STATUS_FAILURE); + /*printk("3. P2P_VirtualIF_PacketSend @@@@@\n"); */ + return 0; + } + + /* find the device in our ApCli list */ + if (pApCli[MAIN_MBSSID].dev == pDev) + { + /* ya! find it */ + pAd->RalinkCounters.PendingNdisPacketCount ++; + /*NdisZeroMemory((PUCHAR)&(RTPKT_TO_OSPKT(pPktSrc))->cb[CB_OFF], 15);*/ + NdisZeroMemory((PUCHAR)(GET_OS_PKT_CB(pPktSrc) + CB_OFF), 15); + RTMP_SET_PACKET_SOURCE(pPktSrc, PKTSRC_NDIS); + RTMP_SET_PACKET_MOREDATA(pPktSrc, FALSE); + RTMP_SET_PACKET_NET_DEVICE_APCLI(pPktSrc, MAIN_MBSSID); + SET_OS_PKT_NETDEV(pPktSrc, pAd->net_dev); + RTMP_SET_PACKET_OPMODE(pPktSrc, OPMODE_AP); + + + /* transmit the packet */ + /*return rt28xx_packet_xmit(RTPKT_TO_OSPKT(skb_p)); */ + return Func(RTPKT_TO_OSPKT(pPktSrc)); + } + } + else + { + /*printk("4. P2P_VirtualIF_PacketSend @@@@@\n"); */ + /* find the device in our p2p list */ + if (pAd->ApCfg.MBSSID[MAIN_MBSSID].MSSIDDev == pDev) + { + /* ya! find it */ + pAd->RalinkCounters.PendingNdisPacketCount ++; + /*NdisZeroMemory((PUCHAR)&(RTPKT_TO_OSPKT(pPktSrc))->cb[CB_OFF], 15);*/ + NdisZeroMemory((PUCHAR)(GET_OS_PKT_CB(pPktSrc) + CB_OFF), 15); + RTMP_SET_PACKET_SOURCE(pPktSrc, PKTSRC_NDIS); + RTMP_SET_PACKET_MOREDATA(pPktSrc, FALSE); + RTMP_SET_PACKET_NET_DEVICE_P2P(pPktSrc, MAIN_MBSSID); + SET_OS_PKT_NETDEV(pPktSrc, pAd->net_dev); + RTMP_SET_PACKET_OPMODE(pPktSrc, OPMODE_AP); + + + /* transmit the packet */ + /*return rt28xx_packet_xmit(RTPKT_TO_OSPKT(skb_p));*/ + return Func(RTPKT_TO_OSPKT(pPktSrc)); + } + } + + RELEASE_NDIS_PACKET(pAd, pPktSrc, NDIS_STATUS_FAILURE); + + return 0; +} + +INT P2P_GoSetCommonHT( + IN PRTMP_ADAPTER pAd) +{ + OID_SET_HT_PHYMODE SetHT; + + if (pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED) + { + /* Clear previous HT information */ + RTMPDisableDesiredHtInfo(pAd); + return FALSE; + } + + 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; + + if (INFRA_ON(pAd)) + { + if (pAd->StaActive.SupportedHtPhy.ChannelWidth == BW_40) + SetHT.ExtOffset = (UCHAR)pAd->StaActive.SupportedHtPhy.ExtChanOffset; + } + + RTMPSetHT(pAd, &SetHT); + + return TRUE; +} + diff --git a/mt7620/src/common/p2p_action.c b/mt7620/src/common/p2p_action.c new file mode 100644 index 0000000..b35dd69 --- /dev/null +++ b/mt7620/src/common/p2p_action.c @@ -0,0 +1,445 @@ +/* + *************************************************************************** + * 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: + p2p.c + + Abstract: + Peer to peer is also called Wifi Direct. P2P is a Task Group of WFA. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Jan Lee 2010-05-21 created for Peer-to-Peer Action frame(Wifi Direct) +*/ +#include "rt_config.h" +extern UCHAR P2POUIBYTE[]; + +/* + ========================================================================== + Description: + P2P state machine init. P2P state machine starts to function after P2P group is formed. the main task is support power save + mechanism. + + Parameters: + S - pointer to the association state machine + Note: + The state machine looks like the following as name implies its function + ========================================================================== + */ +VOID P2PStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, (ULONG)MAX_P2P_STATE, + (ULONG)MAX_P2P_MSG, (STATE_MACHINE_FUNC)Drop, P2P_IDLE_STATE, P2P_IDLE_STATE); + + StateMachineSetAction(Sm, P2P_IDLE_STATE, MT2_MLME_P2P_NOA, (STATE_MACHINE_FUNC)MlmeP2pNoaAction); + StateMachineSetAction(Sm, P2P_IDLE_STATE, MT2_MLME_P2P_PRESENCE_REQ, (STATE_MACHINE_FUNC)MlmeP2pPresReqAction); + StateMachineSetAction(Sm, P2P_IDLE_STATE, MT2_MLME_P2P_PRESENCE_RSP, (STATE_MACHINE_FUNC)MlmeP2pPresRspAction); + StateMachineSetAction(Sm, P2P_IDLE_STATE, MT2_MLME_P2P_GO_DIS_REQ, (STATE_MACHINE_FUNC)MlmeP2pGoDiscoverAction); + StateMachineSetAction(Sm, P2P_IDLE_STATE, MT2_MLME_P2P_GAS_INT_REQ, (STATE_MACHINE_FUNC)MlmeGASIntialReqAction); + StateMachineSetAction(Sm, P2P_IDLE_STATE, MT2_MLME_P2P_GAS_INT_RSP, (STATE_MACHINE_FUNC)MlmeGASIntialRspAction); + StateMachineSetAction(Sm, P2P_IDLE_STATE, MT2_MLME_P2P_GAS_CB_REQ, (STATE_MACHINE_FUNC)MlmeGASComebackReqAction); + StateMachineSetAction(Sm, P2P_IDLE_STATE, MT2_MLME_P2P_GAS_CB_RSP, (STATE_MACHINE_FUNC)MlmeGASComebackRspAction); + + StateMachineSetAction(Sm, P2P_IDLE_STATE, MT2_PEER_P2P_NOA, (STATE_MACHINE_FUNC)PeerP2pNoaAction); + StateMachineSetAction(Sm, P2P_IDLE_STATE, MT2_PEER_P2P_PRESENCE_REQ, (STATE_MACHINE_FUNC)PeerP2pPresReqAction); + StateMachineSetAction(Sm, P2P_IDLE_STATE, MT2_PEER_P2P_PRESENCE_RSP, (STATE_MACHINE_FUNC)PeerP2pPresRspAction); + StateMachineSetAction(Sm, P2P_IDLE_STATE, MT2_PEER_P2P_GO_DIS_REQ, (STATE_MACHINE_FUNC)PeerP2pGoDiscoverAction); + + /* init all P2P ctrl state. */ + pAd->P2pCfg.ActionState = P2P_IDLE_STATE; + +} + +/* + ========================================================================== + Description: + Support WiFi Direct Certification test for P2P Client to send Presence Request Test Case.. + + Parameters: + S - pointer to the association state machine + Note: + The state machine looks like the following as name implies its function + ========================================================================== + */ +VOID P2pSendServiceReqCmd( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr, + IN UCHAR p2pindex) +{ + +} + +/* + ========================================================================== + Description: + Support WiFi Direct Certification test for P2P Client to send Presence Request Test Case.. + + Parameters: + S - pointer to the association state machine + Note: + The state machine looks like the following as name implies its function + ========================================================================== + */ +VOID P2pSendPresenceReqCmd( + IN PRTMP_ADAPTER pAd, + IN UCHAR p2pindex) +{ + +} + +/* + ========================================================================== + Description: + P2P Action frame differs only in InBuffer. Others are all common to all ACtion Subtype + + Parameters: + S - pointer to the association state machine + Note: + The state machine looks like the following as name implies its function + ========================================================================== + */ +VOID MlmeP2pCommonAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR OUISubType, + IN UCHAR Token, + IN PUCHAR pInBuffer, + IN UCHAR InBufferLen, + IN MLME_QUEUE_ELEM *Elem) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PMLME_P2P_ACTION_STRUCT pGoReq = (PMLME_P2P_ACTION_STRUCT) Elem->Msg; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + FRAME_P2P_ACTION Frame; + ULONG TmpLen; + UCHAR i; + PUCHAR pDest; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + { + return; + } + DBGPRINT(RT_DEBUG_ERROR, (" TO= %x %x %x %x %x %x \n", PRINT_MAC(pGoReq->Addr))); + DBGPRINT(RT_DEBUG_ERROR, (" Bssid= %x %x %x %x %x %x \n", PRINT_MAC(pP2PCtrl->CurrentAddress))); + + ActHeaderInit(pAd, &Frame.Hdr, pGoReq->Addr, pP2PCtrl->CurrentAddress, pP2PCtrl->CurrentAddress); + Frame.Category = MT2_ACT_VENDOR; /* 0x7F */ + RTMPMoveMemory(&Frame.OUI[0], P2POUIBYTE, 4); + Frame.OUISubType = OUISubType; + Frame.Token = Token; + /* No Element */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_P2P_ACTION), &Frame, + END_OF_ARGS); + + if ((InBufferLen > 0) && (pInBuffer != NULL)) + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + InBufferLen, pInBuffer, + END_OF_ARGS); + FrameLen += TmpLen; + } + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + pDest = (PUCHAR)&Frame; + for (i = 0; i Msg; + UCHAR P2pIEFixed[6] = {0xdd, 0x04, 0x00, 0x50, 0xf2, 0x09}; + UCHAR Index = 0; + + RTMPMoveMemory(&P2pIEFixed[2], P2POUIBYTE, 4); + p2pindex = pGoReq->TabIndex; + /* If AP's index exists, it also means I am connected. Similar to sanity check. */ + if (p2pindex < MAX_LEN_OF_MAC_TABLE) + { + /* Add the header of P2P IE */ + RTMPMoveMemory(&NoAAttribute[0], &P2pIEFixed, 6); + Index += 6; + + NoAAttribute[Index] = SUBID_P2P_STATUS; + NoAAttribute[Index+1] = 1; + NoAAttribute[Index+2] = 0; + + /* Count Field is also called Type. type = 1 means preferred. type = 2 means max limit. */ + if ((pAd->MacTab.Content[p2pindex].P2pInfo.NoADesc[0].Count > 2) || (pAd->MacTab.Content[p2pindex].P2pInfo.NoADesc[0].Count == 0)) + { + NoAAttribute[Index+3] = P2PSTATUS_INVALID_PARM; /* index */ + MlmeP2pCommonAction(pAd, P2PACT_PERSENCE_RSP, pAd->MacTab.Content[p2pindex].P2pInfo.NoAToken, &NoAAttribute[0], 3+6, Elem); + DBGPRINT(RT_DEBUG_ERROR, ("P2P- Presence Response sent with error. \n")); + } + else + { + /* update NoA to Go */ + pAd->P2pCfg.GONoASchedule.Duration = pAd->MacTab.Content[p2pindex].P2pInfo.NoADesc[0].Duration; + pAd->P2pCfg.GONoASchedule.Interval = pAd->MacTab.Content[p2pindex].P2pInfo.NoADesc[0].Interval; + pAd->P2pCfg.GONoASchedule.Count = 255; + + NoAAttribute[Index+3] = P2PSTATUS_SUCCESS; /* index */ + NoAAttribute[Index+4] = SUBID_P2P_NOA; + NoAAttribute[Index+5] = 15; + NoAAttribute[Index+6] = 0; + NoAAttribute[Index+7] = pAd->MacTab.Content[p2pindex].P2pInfo.NoAToken; /* NoAToken should save the token from client's presence request. */ + NoAAttribute[Index+8] = pAd->P2pCfg.CTWindows; /* CTWindows */ + NoAAttribute[Index+9] = pAd->P2pCfg.GONoASchedule.Count; /* Count */ + /* TO DO : sync with windows if necessary */ + /*P2pGOStartNoA(pAd); */ + /* Duration */ + RTMPMoveMemory(&NoAAttribute[Index+10], &pAd->P2pCfg.GONoASchedule.Duration, 4); + /* Interval */ + RTMPMoveMemory(&NoAAttribute[Index+14], &pAd->P2pCfg.GONoASchedule.Interval, 4); + RTMPMoveMemory(&NoAAttribute[Index+18], &pAd->P2pCfg.GONoASchedule.StartTime, 4); + /* Update IE length */ + NoAAttribute[1] += 22; + MlmeP2pCommonAction(pAd, P2PACT_PERSENCE_RSP, pAd->MacTab.Content[p2pindex].P2pInfo.NoAToken, &NoAAttribute[0], 22+6, Elem); + DBGPRINT(RT_DEBUG_TRACE, ("P2P- Presence Response sent. \n")); + + /* Trigger to update GO's beacon */ + pAd->P2pCfg.GONoASchedule.bValid = TRUE; + DBGPRINT(RT_DEBUG_ERROR, ("MlmeP2pPresRspAction: Update NoA Schedual on GO!\n")); + } + + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s:: index = %d out of range.\n", __FUNCTION__, p2pindex)); + +} + +VOID MlmeP2pGoDiscoverAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PMLME_P2P_ACTION_STRUCT pGoReq = (PMLME_P2P_ACTION_STRUCT) Elem->Msg; + DBGPRINT(RT_DEBUG_TRACE, ("P2P- GO DISCOVERY request. \n")); + MlmeP2pCommonAction(pAd, P2PACT_GO_DISCOVER_REQ, 0, NULL, 0, Elem); + + if (pGoReq->TabIndex < MAX_P2P_GROUP_SIZE) + { + /* when used in MlmeP2pGoDiscoverAction, WcidIndex */ + pAd->P2pTable.Client[pGoReq->TabIndex].P2pClientState = P2PSTATE_WAIT_GO_DISCO_ACK; + DBGPRINT(RT_DEBUG_TRACE, ("P2P- Client State %s \n", decodeP2PClientState(pAd->P2pTable.Client[pGoReq->TabIndex].P2pClientState))); + } + +} + +VOID PeerP2pNoaAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PP2P_ACTION_FRAME pFrame = (PP2P_ACTION_FRAME)Elem->Msg; + PMAC_TABLE_ENTRY pClient; + + DBGPRINT(RT_DEBUG_TRACE,("PeerP2pNoaAction %s. \n", decodeP2PState(pAd->P2pCfg.P2PConnectState))); + DBGPRINT(RT_DEBUG_TRACE,("Category = %d. Subtype = %d. Token = %d.\n", pFrame->Category, pFrame->Subtype, pFrame->Token)); + if (!P2P_CLI_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE,("PeerP2pNoaAction return %s. \n", decodeP2PState(pAd->P2pCfg.P2PConnectState))); + return; + } + if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) + { + DBGPRINT(RT_DEBUG_TRACE,("PeerP2pNoaAction Elem->Wcid %d. return.\n", Elem->Wcid)); + return; + } + + pClient = &pAd->MacTab.Content[Elem->Wcid]; + pAd->P2pCfg.NoAIndex = Elem->Wcid; + DBGPRINT(RT_DEBUG_TRACE,("PeerP2pNoaAction Current NoAToken = %d. \n", pClient->P2pInfo.NoAToken)); + if (pFrame->Token != pClient->P2pInfo.NoAToken) + { + if ((RTMPEqualMemory(&pFrame->Octet[0], P2POUIBYTE, 4)) && (pFrame->Octet[4] == SUBID_P2P_NOA)) + { + DBGPRINT(RT_DEBUG_TRACE,("PeerP2pNoaAction CTWindow = %d. \n", pFrame->Octet[8])); + pClient->P2pInfo.CTWindow = pFrame->Octet[8]; + P2pHandleNoAAttri(pAd, pClient, &pFrame->Octet[0]); + } + } + +} + +VOID PeerP2pPresReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MLME_P2P_ACTION_STRUCT P2PActReq; + MAC_TABLE_ENTRY *pEntry; + PFRAME_P2P_ACTION pFrame; + PP2P_NOA_DESC pNoADesc; + + pFrame = (PFRAME_P2P_ACTION)Elem->Msg; + + if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) + { + DBGPRINT(RT_DEBUG_ERROR, ("PeerP2pPresReqAction. unknown Elem->Wcid = %d \n", Elem->Wcid )); + } + + DBGPRINT(RT_DEBUG_ERROR, ("PeerP2pPresReqAction. Send back to Elem->Wcid = %d \n", Elem->Wcid )); + + pEntry = &pAd->MacTab.Content[Elem->Wcid]; + + pNoADesc = (PP2P_NOA_DESC)(&Elem->Msg[11 + sizeof(FRAME_P2P_ACTION)]); + pEntry->P2pInfo.NoADesc[0].Count = pNoADesc->Count; + pEntry->P2pInfo.NoADesc[0].Duration = *(PUINT32)&pNoADesc->Duration[0]; + pEntry->P2pInfo.NoADesc[0].Interval = *(PUINT32)&pNoADesc->Interval[0]; + pEntry->P2pInfo.NoADesc[0].StartTime = *(PUINT32)&pNoADesc->StartTime[0]; + DBGPRINT(RT_DEBUG_ERROR,(" pP2pEntry->NoADesc[0].Count = %d, \n", pEntry->P2pInfo.NoADesc[0].Count)); + DBGPRINT(RT_DEBUG_ERROR,(" pP2pEntry->NoADesc[0].Duration = %ld, \n", pEntry->P2pInfo.NoADesc[0].Duration)); + DBGPRINT(RT_DEBUG_ERROR,(" pP2pEntry->NoADesc[0].Interval = %ld, \n", pEntry->P2pInfo.NoADesc[0].Interval)); + DBGPRINT(RT_DEBUG_ERROR,(" pP2pEntry->NoADesc[0].StartTime = %ld, \n", pEntry->P2pInfo.NoADesc[0].StartTime)); + DBGPRINT(RT_DEBUG_ERROR,("pFrame->Token = %d \n", pFrame->Token)); + + pEntry->P2pInfo.NoAToken = pFrame->Token; +/* pP2pEntry->NoADesc[0].Duration = Elem->Msg; */ + NdisZeroMemory(&P2PActReq, sizeof(P2PActReq)); + COPY_MAC_ADDR(P2PActReq.Addr, pEntry->Addr); + P2PActReq.TabIndex = Elem->Wcid; + MlmeEnqueue(pAd, P2P_ACTION_STATE_MACHINE, MT2_MLME_P2P_PRESENCE_RSP, sizeof(MLME_P2P_ACTION_STRUCT), (PVOID)&P2PActReq, 0); + MlmeHandler(pAd); + +} + + +VOID PeerP2pPresRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + DBGPRINT(RT_DEBUG_TRACE, ("PeerP2pPresRspAction.\n")); +} + +VOID PeerP2pGoDiscoverAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR i; + PUCHAR pDest; + + DBGPRINT(RT_DEBUG_TRACE,("PeerP2pGoDiscoverAction.\n")); + DBGPRINT(RT_DEBUG_TRACE,("bKeepSlient = %d.\n", pAd->P2pCfg.bKeepSlient)); + pDest = &Elem->Msg[0]; + for (i = 0; i MsgLen; ) + { + DBGPRINT(RT_DEBUG_TRACE,(": %x %x %x %x %x %x %x %x %x \n", *(pDest+i), *(pDest+i+1), *(pDest+i+2), + *(pDest+i+3), *(pDest+i+4), *(pDest+i+5), *(pDest+i+6), *(pDest+i+7), *(pDest+i+8))); + i = i + 9; + } +} + + diff --git a/mt7620/src/common/p2p_cfg.c b/mt7620/src/common/p2p_cfg.c new file mode 100644 index 0000000..1ba0bea --- /dev/null +++ b/mt7620/src/common/p2p_cfg.c @@ -0,0 +1,12099 @@ +/**************************************************************************** + * 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", FALSE, 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 */ + +INT Set_AP_SSID_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_TxRate_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +#ifdef RT305x +INT Set_RfRead_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_RfWrite_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); +#endif /* RT305x */ + +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_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_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_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); + +INT Set_AutoChannelSel_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_BADecline_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Show_MacTable_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_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); + +#ifdef RTMP_MAC_PCI +#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); + +INT Show_Diag_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* DBG_DAIGNOSE */ +#endif /* RTMP_MAC_PCI */ + +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 NINTENDO_AP +int Set_NintendiCapable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +int Set_NintendoGet_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +int Set_NintendoSet_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* NINTENDO_AP */ + +#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 WSC_AP_SUPPORT +INT Set_AP_WscSsid_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +#endif /* WSC_AP_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); + +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); + +#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_WscSetupLock_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); +#endif /* WSC_V2_SUPPORT */ + +#endif /* WSC_AP_SUPPORT */ + +#ifdef EASY_CONFIG_SETUP +INT Set_AP_AutoProvisionEnable_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_RssiThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef WAC_SUPPORT +INT Set_AP_WACEnable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* WAC_SUPPORT */ +#endif /* EASY_CONFIG_SETUP */ + +#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(IN PRTMP_ADAPTER pAd, IN PSTRING arg); +#endif /* DOT11N_DRAFT3 */ + +INT Set_EntryLifeCheck_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#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 P2P_SUPPORT +INT Set_P2p_OpMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_Ssid_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_Bssid_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_AuthMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_EncrypType_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_WPAPSK_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_Key1_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_Key2_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_Key3_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_Key4_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_TxMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2pCli_TxMcs_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef WSC_AP_SUPPORT +INT Set_P2pCli_WscSsid_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* WSC_AP_SUPPORT */ + +INT Set_P2P_ProvAccept_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* P2P_SUPPORT */ +static struct { + PSTRING name; + INT (*set_proc)(PRTMP_ADAPTER pAdapter, PSTRING arg); +} *PRTMP_PRIVATE_SET_PROC, RTMP_PRIVATE_SUPPORT_PROC[] = { + {"SSID", Set_AP_SSID_Proc}, + {"Channel", Set_Channel_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}, + {"WPAPSK", Set_AP_WPAPSK_Proc}, + {"ResetCounter", Set_ResetStatCounter_Proc}, + {"MaxStaNum", Set_AP_MaxStaNum_Proc}, +#ifdef DBG + {"Debug", Set_Debug_Proc}, +#endif /* DBG */ + + {"CountryString", Set_CountryString_Proc}, + {"CountryCode", Set_CountryCode_Proc}, + {"NoForwarding", Set_NoForwarding_Proc}, + +#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}, +#ifdef WSC_V2_SUPPORT + {"WscV2Support", Set_WscV2Support_Proc}, + {"WscVersion2", Set_WscVersion2_Proc}, + {"WscExtraTlvTag", Set_WscExtraTlvTag_Proc}, + {"WscExtraTlvType", Set_WscExtraTlvType_Proc}, + {"WscExtraTlvData", Set_WscExtraTlvData_Proc}, + {"WscSetupLock", Set_WscSetupLock_Proc}, + {"WscFragment", Set_WscFragment_Proc}, + {"WscFragmentSize", Set_WscFragmentSize_Proc}, +#endif /* WSC_V2_SUPPORT */ +#endif /* WSC_AP_SUPPORT */ + +#ifdef P2P_SUPPORT + {"P2pCliEnable", Set_P2pCli_Enable_Proc}, + {"P2pCliSsid", Set_P2pCli_Ssid_Proc}, + {"P2pCliBssid", Set_P2pCli_Bssid_Proc}, + {"P2pCliAuthMode", Set_P2pCli_AuthMode_Proc}, + {"P2pCliEncrypType", Set_P2pCli_EncrypType_Proc}, + {"P2pCliDefaultKeyID", Set_P2pCli_DefaultKeyID_Proc}, + {"P2pCliWPAPSK", Set_P2pCli_WPAPSK_Proc}, + {"P2pCliKey1", Set_P2pCli_Key1_Proc}, + {"P2pCliKey2", Set_P2pCli_Key2_Proc}, + {"P2pCliKey3", Set_P2pCli_Key3_Proc}, + {"P2pCliKey4", Set_P2pCli_Key4_Proc}, + {"P2pCliTxMode", Set_P2pCli_TxMode_Proc}, + {"P2pCliTxMcs", Set_P2pCli_TxMcs_Proc}, +#ifdef WSC_AP_SUPPORT + {"P2pCliWscSsid", Set_P2pCli_WscSsid_Proc}, +#endif /* WSC_AP_SUPPORT */ + {"P2pOpMode", Set_P2p_OpMode_Proc}, + {"p2pEnable", Set_P2P_Enable}, + {"p2pLisCh", Set_P2P_Listen_Channel}, + {"p2pOpCh", Set_P2P_Operation_Channel}, + {"p2pGoInt", Set_P2P_GO_Intent}, + {"p2pDevName", Set_P2P_Device_Name}, + {"p2pWscMode", Set_P2P_WSC_Mode}, + {"p2pWscConf", Set_P2P_WSC_ConfMethod}, + {"p2pScan", Set_P2P_Scan}, + {"p2pInv", Set_P2P_Invite_Proc}, + {"p2pDevDisc", Set_P2P_Device_Discoverability_Proc}, + {"p2pLink", Set_P2P_Connect_GoIndex_Proc}, + {"p2pConnDevAddr", Set_P2P_Connect_Dev_Addr_Proc}, + {"p2pCfg", Set_P2P_Print_Cfg}, + {"p2pTab", Set_P2P_Print_GroupTable_Proc}, + {"p2pProv", Set_P2P_Provision_Proc}, + {"p2pStat", Set_P2P_State_Proc}, + {"p2pReset", Set_P2P_Reset_Proc}, + {"p2pPerTab", Set_P2P_Print_PersistentTable_Proc}, + {"p2pDefConfMthd", Set_P2P_Default_Config_Method_Proc}, + {"p2pLinkDown", Set_P2P_Link_Down_Proc}, + {"p2pSigmaEnable", Set_P2P_Sigma_Enable_Proc}, + {"p2pQoSLegacyRate", Set_P2P_QoS_NULL_Legacy_Rate_Proc}, + {"p2pClientPmEnable", Set_P2P_CLIENT_PM_Enable_Proc}, + {"p2pEnterPIN", Set_P2P_Enter_WSC_PIN_Proc}, + {"p2pPerEnable", Set_P2P_Persistent_Enable_Proc}, + {"p2pDevDiscEnable", Set_P2P_Dev_Discoverability_Enable_Proc}, + {"p2pProvAccept", Set_P2P_ProvAccept_Proc}, + {"p2pDelDevByAddr", Set_P2P_DelDevByAddr_Proc}, + {"p2pDevDiscPeriod", Set_P2P_DevDiscPeriod_Proc}, + {"p2pPriDeviceType", Set_P2P_PriDeviceType_Proc}, + {"p2p2ndDevTypeList", Set_P2P_SecDevTypeList_Proc}, + {"p2pCancel", Set_P2P_Cancel_Proc}, +#endif /* P2P_SUPPORT */ + {NULL,} +}; + + +static struct { + PSTRING name; + INT (*set_proc)(PRTMP_ADAPTER pAdapter, PSTRING arg); +} *PRTMP_PRIVATE_SHOW_PROC, RTMP_PRIVATE_SHOW_SUPPORT_PROC[] = { + {"stainfo", Show_MacTable_Proc}, + {"stacountinfo", Show_StaCount_Proc}, + {"stasecinfo", Show_StaSecurityInfo_Proc}, + {"descinfo", Show_DescInfo_Proc}, + {"driverinfo", Show_DriverInfo_Proc}, +#ifdef DOT11_N_SUPPORT + {"bainfo", Show_BaTable_Proc}, +#endif /* DOT11_N_SUPPORT */ + {"stat", Show_Sat_Proc}, +#ifdef MAT_SUPPORT + {"matinfo", Show_MATTable_Proc}, +#endif /* MAT_SUPPORT */ + +#ifdef WSC_AP_SUPPORT + {"WscPeerList", WscApShowPeerList}, +#endif /* WSC_AP_SUPPORT */ + {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) && + (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; + } + if (Status == NDIS_STATUS_SUCCESS) + { + if (strcmp(this_char, "P2pOpMode") == 0) + { + if (P2P_GO_ON(pAd)) + pAd->flg_p2p_OpStatusFlags |= P2P_FIXED_MODE; + else + pAd->flg_p2p_OpStatusFlags &= (~P2P_FIXED_MODE); + } + } + 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; + +} + +#ifdef INF_AR9 +#ifdef AR9_MAPI_SUPPORT +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, + IN OUT 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 */ + UINT KeyIdx = 0; + PNDIS_AP_802_11_KEY pKey = NULL; + TX_RTY_CFG_STRUC tx_rty_cfg; + ULONG ShortRetryLimit, LongRetryLimit; +#endif /* SNMP_SUPPORT */ + UCHAR ctmp; + +#ifdef MESH_SUPPORT + BOOLEAN RestartMeshIsRequired = FALSE; +#endif /* MESH_SUPPORT */ + +#ifdef HOSTAPD_SUPPORT + NDIS_802_11_WEP_STATUS WepStatus; + NDIS_802_11_AUTHENTICATION_MODE AuthMode = Ndis802_11AuthModeMax; + NDIS_802_11_SSID Ssid; + MAC_TABLE_ENTRY *pEntry; + struct ieee80211req_mlme mlme; + + struct ieee80211req_key Key; + struct ieee80211req_del_key delkey; + ULONG KeyIdx; + UINT8 Wcid; + PMULTISSID_STRUCT pMbss ; + WSC_LV_INFO WscIEBeacon; + WSC_LV_INFO WscIEProbeResp; + int i; +#endif /*HOSTAPD_SUPPORT*/ + + + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + switch(cmd & 0x7FFF) + { +#ifdef P2P_SUPPORT + + case OID_802_11_P2P_MODE: + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_P2P_MODE \n")); + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + UCHAR OpMode=1; + Status = copy_from_user(&OpMode, wrq->u.data.pointer, wrq->u.data.length); + if (OpMode == OPMODE_AP) + { + if (P2P_CLI_ON(pAd)) + P2P_CliStop(pAd); + + if ((!P2P_GO_ON(pAd)) || (P2P_GO_ON(pAd))) + { + P2PCfgInit(pAd); + P2P_GoStartUp(pAd, MAIN_MBSSID); + } + } + else if (OpMode == OPMODE_APSTA) + { + if (P2P_GO_ON(pAd)) + P2P_GoStop(pAd); + + if ((!P2P_CLI_ON(pAd)) || (P2P_CLI_ON(pAd))) + { + P2PCfgInit(pAd); + P2P_CliStartUp(pAd); + AsicEnableBssSync(pAd); + } + } + else + { + if (P2P_CLI_ON(pAd)) + P2P_CliStop(pAd); + else if (P2P_GO_ON(pAd)) + { + P2P_GoStop(pAd); + if (INFRA_ON(pAd)) + AsicEnableBssSync(pAd); + } + P2PCfgInit(pAd); + } + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(p2p%d) Set_P2p_OpMode_Proc::(OpMode = %d)\n", pObj->ioctl_if, OpMode)); + + + } + break; +/* + case OID_802_11_P2P_CLEAN_TABLE: + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_P2P_CLEAN_TABLE \n")); + { + P2pGroupTabInit(pAd); + } + break; +*/ + + case OID_802_11_P2P_SSID: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_P2P_SSID \n")); + if (wrq->u.data.length > 32) + Status = -EINVAL; + else + { + UCHAR Ssid[MAX_LEN_OF_SSID] = {0}; + + NdisZeroMemory(Ssid, sizeof(Ssid)); + Status = copy_from_user(&Ssid, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_P2P_SSID Ssid=%s\n",Ssid)); + { + Set_AP_SSID_Proc(pAd, Ssid); + DBGPRINT(RT_DEBUG_TRACE, ("%s:: SSID = %s.\n", __FUNCTION__, Ssid)); + } + + } + break; + + case OID_802_11_P2P_DEVICE_NAME: + DBGPRINT(RT_DEBUG_ERROR, ("Set::OID_802_11_P2P_DEVICE_NAME \n")); + if (wrq->u.data.length > 32) + Status = -EINVAL; + else + { + UCHAR DeviceName[MAX_LEN_OF_SSID + 1] = {0}; + + NdisZeroMemory(DeviceName, sizeof(DeviceName)); + Status = copy_from_user(&DeviceName, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_ERROR, ("Set::OID_802_11_P2P_DEVICE_NAME DeviceName=%s\n",DeviceName)); + { + + pAd->P2pCfg.DeviceNameLen = wrq->u.data.length; + NdisZeroMemory(pAd->P2pCfg.DeviceName, 32); + NdisMoveMemory(pAd->P2pCfg.DeviceName, DeviceName, pAd->P2pCfg.DeviceNameLen); + P2pGetRandomSSID(pAd, pAd->ApCfg.MBSSID[MAIN_MBSSID].Ssid, &(pAd->ApCfg.MBSSID[MAIN_MBSSID].SsidLen)); + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Device Name = %s.\n", __FUNCTION__, pAd->P2pCfg.DeviceName)); + } + + } + break; + + case OID_802_11_P2P_LISTEN_CHANNEL: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_P2P_LISTEN_CHANNEL \n")); + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + UCHAR listen_ch; + Status = copy_from_user(&listen_ch, wrq->u.data.pointer, wrq->u.data.length); + + /* check if this channel is valid */ + if (ChannelSanity(pAd, listen_ch) == TRUE) + { + pAd->P2pCfg.ListenChannel = listen_ch; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Listen Channel out of range, using default.\n")); + pAd->P2pCfg.ListenChannel = 1; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: Listen Channel = %d.\n", __FUNCTION__, pAd->P2pCfg.ListenChannel)); + } + break; + + case OID_802_11_P2P_OPERATION_CHANNEL: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_P2P_OPERATION_CHANNEL \n")); + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + UCHAR op_ch; + Status = copy_from_user(&op_ch, wrq->u.data.pointer, wrq->u.data.length); + + /* check if this channel is valid */ + if (ChannelSanity(pAd, op_ch) == TRUE) + { + pAd->P2pCfg.GroupChannel = op_ch; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Opertation Channel out of range, using default.\n")); + pAd->P2pCfg.GroupChannel = 1; + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Op Channel = %d.\n", __FUNCTION__, pAd->P2pCfg.GroupChannel)); + + } + break; + + case OID_802_11_P2P_GO_INT: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_P2P_GO_INT \n")); + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + UCHAR intent; + Status = copy_from_user(&intent, wrq->u.data.pointer, wrq->u.data.length); + + /* check if this channel is valid */ + + if (intent <= 15) + pAd->P2pCfg.GoIntentIdx = intent; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("GO Intent out of range 0 ~ 15, using default.\n")); + pAd->P2pCfg.GoIntentIdx = 0; + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: GO Intent = %d.\n", __FUNCTION__, pAd->P2pCfg.GoIntentIdx)); + + } + break; + + case OID_802_11_P2P_SCAN: + DBGPRINT(RT_DEBUG_ERROR, ("Set::OID_802_11_P2P_SCAN \n")); + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + + UCHAR bScan; + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + Status = copy_from_user(&bScan, wrq->u.data.pointer, wrq->u.data.length); + + + if (bScan) + { + pAd->StaCfg.bAutoReconnect = FALSE; + pP2PCtrl->bSentProbeRSP = TRUE; + P2pGroupTabInit(pAd); + P2pScan(pAd); + } + else + { +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + pAd->StaCfg.bAutoReconnect = FALSE; +#else + pAd->StaCfg.bAutoReconnect = TRUE; +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + pP2PCtrl->bSentProbeRSP = FALSE; + P2pStopScan(pAd); + } + } + break; + + + case OID_P2P_WSC_PIN_CODE: + DBGPRINT(RT_DEBUG_ERROR, ("Set::OID_P2P_WSC_PIN_CODE wrq->u.data.length=%d\n",wrq->u.data.length)); + 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_AP_WscPinCode_Proc(pAd, (PSTRING) &PinCode[0]) == FALSE) + Status = -EINVAL; + } + } + break; + + case OID_802_11_P2P_WscMode: + DBGPRINT(RT_DEBUG_ERROR, ("Set::OID_802_11_P2P_WscMode \n")); + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + UCHAR p2pWscMode; + Status = copy_from_user(&p2pWscMode, wrq->u.data.pointer, wrq->u.data.length); + + /* check if this channel is valid */ + + if (p2pWscMode <= 2 && p2pWscMode >= 1) + pAd->P2pCfg.WscMode= p2pWscMode; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("WscMode is invalid, using default.\n")); + pAd->P2pCfg.WscMode = WSC_PIN_MODE; /* PIN */ + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: WscMode = %s.\n", __FUNCTION__, (p2pWscMode == 1) ? "PIN" : "PBC")); + } + break; + + case OID_802_11_P2P_WscConf: + DBGPRINT(RT_DEBUG_ERROR, ("Set::OID_802_11_P2P_WscConf \n")); + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + UCHAR method; + Status = copy_from_user(&method, wrq->u.data.pointer, wrq->u.data.length); + + if (pAd->P2pCfg.WscMode == WSC_PIN_MODE) + { + if (method == 1) + { + /* Display PIN */ + pAd->P2pCfg.Dpid = DEV_PASS_ID_REG; + pAd->P2pCfg.ConfigMethod = WSC_CONFMET_DISPLAY; + + } + else if (method == 2) + { + /* Enter PIN */ + pAd->P2pCfg.Dpid = DEV_PASS_ID_USER; + pAd->P2pCfg.ConfigMethod = WSC_CONFMET_KEYPAD; + } + } + else if (pAd->P2pCfg.WscMode == WSC_PBC_MODE) + { + if (method == 3) + { + pAd->P2pCfg.Dpid = DEV_PASS_ID_PBC; + pAd->P2pCfg.ConfigMethod = WSC_CONFMET_PBC; + } + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Config Method = %s.\n", __FUNCTION__, decodeConfigMethod(pAd->P2pCfg.ConfigMethod))); + } + break; + + case OID_802_11_P2P_Link: + DBGPRINT(RT_DEBUG_ERROR, ("Set::OID_802_11_P2P_Link \n")); + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + + UCHAR p2pindex; + PUCHAR pAddr; + Status = copy_from_user(&p2pindex, wrq->u.data.pointer, wrq->u.data.length); + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: TabIdx[%d]\n", __FUNCTION__, p2pindex)); + if (p2pindex < pAd->P2pTable.ClientNumber) + { + /*P2PPrintP2PEntry(pAd, P2pTabIdx); */ + /*pAd->P2pCfg.ConnectingIndex = 0; */ + /*if (pAd->P2pTable.Client[P2pTabIdx].P2pClientState == P2PSTATE_DISCOVERY) */ + /* pAd->P2pTable.Client[P2pTabIdx].P2pClientState = P2PSTATE_CONNECT_COMMAND; */ + /*COPY_MAC_ADDR(pAd->P2pCfg.ConnectingMAC, pAd->P2pTable.Client[P2pTabIdx].addr); */ + /*pAd->P2pTable.Client[P2pTabIdx].StateCount = 10; */ + /*pAd->P2pTable.Client[P2pTabIdx].bValid = TRUE; */ + /*P2pConnect(pAd); */ + pAddr = &pAd->P2pTable.Client[p2pindex].addr[0]; + P2pConnectPrepare(pAd, pAddr, P2PSTATE_CONNECT_COMMAND); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("Table Idx out of range!\n")); + } + break; + + case OID_802_11_P2P_RESET: + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_P2P_RESET \n")); + Set_P2P_Reset_Proc(pAd, "1"); + break; + + case OID_802_11_P2P_SIGMA_ENABLE: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_P2P_SIGMA_ENABLE \n")); + Set_P2P_Sigma_Enable_Proc(pAd, "1"); + break; + + case OID_802_11_P2P_CONNECT_ADDR: + { + UCHAR Addr[18] = {0}; + Status = copy_from_user(&Addr, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_P2P_CONNECT_ADDR \n")); + Set_P2P_Connect_Dev_Addr_Proc(pAd, &Addr); + } + break; + + case OID_802_11_P2P_ENTER_PIN: + { + UCHAR PIN[10] = {0}; + Status = copy_from_user(&PIN, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_P2P_ENTER_PIN \n")); + Set_P2P_Enter_WSC_PIN_Proc(pAd, &PIN); + } + break; + + case OID_802_11_P2P_PROVISION: + { + UCHAR p2pindex; + PUCHAR pAddr; + Status = copy_from_user(&p2pindex, wrq->u.data.pointer, wrq->u.data.length); + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_P2P_PROVISION(%d)\n", p2pindex)); + if (p2pindex < pAd->P2pTable.ClientNumber) + { + pAddr = &pAd->P2pTable.Client[p2pindex].addr[0]; + P2pConnectPrepare(pAd, pAddr, P2PSTATE_PROVISION_COMMAND); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("Set::OID_802_11_P2P_PROVISION out of range!\n")); + } + break; + + case OID_802_11_P2P_PROVISION_MAC: + { + UCHAR Addr[18] = {0}; + Status = copy_from_user(&Addr, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_P2P_CONNECT_ADDR \n")); + Set_P2P_Provision_Dev_Addr_Proc(pAd, &Addr); + } + break; + + case OID_802_11_P2P_PASSPHRASE: + { + MULTISSID_STRUCT *pMBSSStruct; + INT retval; + UCHAR pass_phrase[65]; + + NdisZeroMemory(&pass_phrase, sizeof(pass_phrase)); + Status = copy_from_user(&pass_phrase, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_P2P_PASSPHRASE(%s)\n", pass_phrase)); + pMBSSStruct = &pAd->ApCfg.MBSSID[0]; + retval = RT_CfgSetWPAPSKKey(pAd, &pass_phrase, strlen(&pass_phrase), (PUCHAR)pMBSSStruct->Ssid, pMBSSStruct->SsidLen, pMBSSStruct->PMK); + if (retval == FALSE) + DBGPRINT(RT_DEBUG_ERROR, ("P2P PassPhrase Generate Fail\n")); + +#ifdef WSC_AP_SUPPORT + NdisZeroMemory(pMBSSStruct->WscControl.WpaPsk, 64); + pMBSSStruct->WscControl.WpaPskLen = 0; + pMBSSStruct->WscControl.WpaPskLen = strlen(pass_phrase); + NdisMoveMemory(pMBSSStruct->WscControl.WpaPsk, pass_phrase, pMBSSStruct->WscControl.WpaPskLen); + +#endif /* WSC_AP_SUPPORT */ + } + break; + case OID_802_11_P2P_LINK_DOWN: + { + CHAR conn_stat; + Status = copy_from_user(&conn_stat, wrq->u.data.pointer, wrq->u.data.length); + if( conn_stat == 1) + P2pLinkDown(pAd, P2P_DISCONNECTED); + else + P2pLinkDown(pAd, P2P_CONNECT_FAIL); + } + break; + + case OID_802_11_P2P_PRI_DEVICE_TYPE: + { + UCHAR pri_dev_type[8]; + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + if ( wrq->u.data.length == 8 ) + Status = copy_from_user(&pri_dev_type, wrq->u.data.pointer, wrq->u.data.length); + + if ( Status == 0 ) + { + + NdisMoveMemory(pP2PCtrl->DevInfo.PriDeviceType, pri_dev_type, 8); + DBGPRINT(RT_DEBUG_TRACE, ("%s::OID_802_11_P2P_PRI_DEVICE_TYPE = %02X%02X-%02X%02X%02X%02X-%02X%02X.\n", __FUNCTION__, + pP2PCtrl->DevInfo.PriDeviceType[0], pP2PCtrl->DevInfo.PriDeviceType[1], + pP2PCtrl->DevInfo.PriDeviceType[2], pP2PCtrl->DevInfo.PriDeviceType[3], + pP2PCtrl->DevInfo.PriDeviceType[4], pP2PCtrl->DevInfo.PriDeviceType[5], + pP2PCtrl->DevInfo.PriDeviceType[6], pP2PCtrl->DevInfo.PriDeviceType[7])); + } + } + break; + +#endif /* P2P_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; + 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) + { + 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->Aid; + 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 + { + RTMP_GET_OS_PID(pObj->IappPid, IappPid); + pObj->IappPid_nr = IappPid; + DBGPRINT(RT_DEBUG_TRACE, ("RT_SET_APD_PID::(IappPid=%lu(0x%x))\n", IappPid, pObj->IappPid)); + } + } + break; +#endif /* IAPP_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 + { + 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%x))\n", apd_pid, pObj->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 + { + UCHAR HashIdx; + 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])); + + HashIdx = MAC_ADDR_HASH_INDEX(Addr); + pEntry = pAd->MacTab.Hash[HashIdx]; + + if (pEntry) + { + MlmeDeAuthAction(pAd, pEntry, REASON_DISASSOC_STA_LEAVING, FALSE); +/* MacTableDeleteEntry(pAd, pEntry->Aid, Addr); */ + } + } + break; +#ifdef WSC_AP_SUPPORT + case RT_OID_WSC_SET_SELECTED_REGISTRAR: + { + PUCHAR upnpInfo; + UCHAR apidx = pObj->ioctl_if; + +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[apidx].Hostapd == TRUE) + { + 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 == TRUE) + { + 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; + BOOLEAN bGetDeviceInfo = FALSE; + + 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 & MIN_NET_DEVICE_FOR_P2P_GO); + /* trigger wsc re-generate public key */ + pWscControl->RegData.ReComputePke = 1; + bGetDeviceInfo = TRUE; + } + 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 NINTENDO_AP + case RT_OID_802_11_NINTENDO_SET_TABLE: + RTMPIoctlNintendoSetTable(pAd, wrq); + break; + case RT_OID_802_11_NINTENDO_CAPABLE: + RTMPIoctlNintendoCapable(pAd, wrq); + break; +#endif /* NINTENDO_AP */ + +#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: + 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].DefaultKeyId].KeyLen = (UCHAR) pKey->KeyLength; + NdisMoveMemory(&pAd->SharedKey[pObj->ioctl_if][pAd->ApCfg.MBSSID[pObj->ioctl_if].DefaultKeyId].Key, &pKey->KeyMaterial, pKey->KeyLength); + if (pKey->KeyIndex & 0x80000000) + { + /* Default key for tx (shared key) */ + pAd->ApCfg.MBSSID[pObj->ioctl_if].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].DefaultKeyId, wrq->u.data.pointer, wrq->u.data.length); + + break; + +#endif /* SNMP_SUPPORT */ + + 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; + + +#ifdef MESH_SUPPORT + case OID_802_11_MESH_SECURITY_INFO: + Status = RTMPIoctlSetMeshSecurityInfo(pAd, wrq); + if (Status == NDIS_STATUS_SUCCESS) + RestartMeshIsRequired = TRUE; + break; + + case OID_802_11_MESH_ID: + if (wrq->u.data.length >= MAX_MESH_ID_LEN) + { + Status = -EINVAL; + break; + } + + { + UCHAR MeshID[MAX_MESH_ID_LEN]; + + NdisZeroMemory(pAd->MeshTab.MeshId, MAX_MESH_ID_LEN); + + Status = copy_from_user(&MeshID,wrq->u.data.pointer, wrq->u.data.length); + NdisMoveMemory(&pAd->MeshTab.MeshId, MeshID, wrq->u.data.length); + pAd->MeshTab.MeshIdLen = (UCHAR)wrq->u.data.length; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_MESH_ID (=%s)\n", pAd->MeshTab.MeshId)); + RestartMeshIsRequired = TRUE; + } + break; + + case OID_802_11_MESH_AUTO_LINK: + if (wrq->u.data.length != 1) + { + Status = -EINVAL; + break; + } + + { + UCHAR Enable = TRUE; + + Status = copy_from_user(&Enable, wrq->u.data.pointer, wrq->u.data.length); + pAd->MeshTab.MeshAutoLink = (Enable > 0) ? TRUE : FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_MESH_AUTO_LINK (=%s)\n", + pAd->MeshTab.MeshAutoLink == TRUE ? "Enable" : "Disable")); + } + break; + + case OID_802_11_MESH_ADD_LINK: + if (wrq->u.data.length != MAC_ADDR_LEN) + { + Status = -EINVAL; + break; + } + + { + UCHAR MacAddr[MAC_ADDR_LEN]; + UINT LinkIdx; + + Status = copy_from_user(&MacAddr, wrq->u.data.pointer, MAC_ADDR_LEN); + LinkIdx = GetMeshLinkId(pAd, (PCHAR)MacAddr); + if (LinkIdx == BSS_NOT_FOUND) + { + LinkIdx = MeshLinkAlloc(pAd, MacAddr, MESH_LINK_STATIC); + if (LinkIdx == BSS_NOT_FOUND) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() All Mesh-Links been occupied.\n", __FUNCTION__)); + return FALSE; + } + } + + if (!VALID_MESH_LINK_ID(LinkIdx)) + break; + + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_ACTOPN, 0, NULL, LinkIdx); + DBGPRINT(RT_DEBUG_TRACE, ("%s::(LinkIdx = %d)\n", __FUNCTION__, LinkIdx)); + } + break; + + case OID_802_11_MESH_DEL_LINK: + if (wrq->u.data.length != MAC_ADDR_LEN) + { + Status = -EINVAL; + break; + } + + { + UCHAR MacAddr[MAC_ADDR_LEN]; + UINT LinkIdx; + + Status = copy_from_user(&MacAddr, wrq->u.data.pointer, MAC_ADDR_LEN); + LinkIdx = GetMeshLinkId(pAd, (PCHAR)MacAddr); + if (!VALID_MESH_LINK_ID(LinkIdx)) + break; + + pAd->MeshTab.MeshLink[LinkIdx].Entry.LinkType = MESH_LINK_DYNAMIC; + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_CNCL, 0, NULL, LinkIdx); + DBGPRINT(RT_DEBUG_TRACE, ("%s::(LinkIdx = %d)\n", __FUNCTION__, LinkIdx)); + } + break; + + case OID_802_11_MESH_MAX_TX_RATE: + if (wrq->u.data.length != 1) + { + Status = -EINVAL; + break; + } + + { + UCHAR TxRate; + + Status = copy_from_user(&TxRate, wrq->u.data.pointer, wrq->u.data.length); + if (TxRate <= 12) + pAd->MeshTab.MeshMaxTxRate = TxRate; + else + pAd->MeshTab.MeshMaxTxRate = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_MESH_MAX_TX_RATE (=%ld)\n", + pAd->MeshTab.MeshMaxTxRate)); + } + break; + + case OID_802_11_MESH_CHANNEL: + if (wrq->u.data.length != 1) + { + Status = -EINVAL; + break; + } + { + UCHAR Channel; + + if (INFRA_ON(pAd) || ADHOC_ON(pAd)) + break; + + Status = copy_from_user(&Channel, wrq->u.data.pointer, wrq->u.data.length); + if (pAd->MeshTab.UCGEnable == TRUE) + { + pAd->MeshTab.MeshChannel = Channel; + MlmeEnqueue(pAd, MESH_CTRL_STATE_MACHINE, MESH_CTRL_UCG_EVT, 0, NULL, 0); + } + else + { + pAd->MeshTab.MeshChannel = pAd->CommonCfg.Channel = Channel; +#ifdef DOT11_N_SUPPORT + N_ChannelCheck(pAd); + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED + && pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + { + N_SetCenCh(pAd); + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + DBGPRINT(RT_DEBUG_TRACE, ("BW_40, control_channel(%d), CentralChannel(%d) \n", + pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, ("BW_20, Channel(%d)\n", pAd->CommonCfg.Channel)); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_MESH_CHANNEL (=%d)\n", (int)Channel)); + } + break; + + case OID_802_11_MESH_HOSTNAME: + if (wrq->u.data.length >= MAX_HOST_NAME_LEN) + { + Status = -EINVAL; + break; + } + + { + NdisZeroMemory(pAd->MeshTab.HostName, MAX_HOST_NAME_LEN); + Status = copy_from_user(pAd->MeshTab.HostName, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_HOSTNAME_ID (=%s)\n", pAd->MeshTab.HostName)); + } + break; + + case OID_802_11_MESH_ONLY_MODE: + if (wrq->u.data.length != 1) + { + Status = -EINVAL; + break; + } + { + UCHAR Enable; + + Status = copy_from_user(&Enable, wrq->u.data.pointer, wrq->u.data.length); + + pAd->MeshTab.MeshOnly = (Enable == 1 ? TRUE : FALSE); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_MESH_ONLY_MODE (=%s)\n", pAd->MeshTab.MeshOnly == TRUE ? "Enable" : "Disable")); + } + break; + + case OID_802_11_MESH_FORWARD: + if (wrq->u.data.length != 1) + { + Status = -EINVAL; + break; + } + + { + UCHAR Enable = TRUE; + + Status = copy_from_user(&Enable, wrq->u.data.pointer, wrq->u.data.length); + pAd->MeshTab.MeshCapability.field.Forwarding = (Enable > 0) ? (1) : (0); + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_MESH_FORWARD (=%s)\n", + pAd->MeshTab.MeshCapability.field.Forwarding == 1 ? "Enable" : "Disable")); + } + break; +#endif /* MESH_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%x))\n", wapi_pid, pObj->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 */ + +#ifdef HOSTAPD_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; + } + else + { + if (pAd->ApCfg.MBSSID[pObj->ioctl_if].AuthMode != AuthMode) + { + /* Config has changed */ + pAd->bConfigChanged = TRUE; + } + pAd->ApCfg.MBSSID[pObj->ioctl_if].AuthMode = AuthMode; + } + pAd->ApCfg.MBSSID[pObj->ioctl_if].PortSecured = WPA_802_1X_PORT_NOT_SECURED; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_AUTHENTICATION_MODE (=%d) \n",pAd->ApCfg.MBSSID[0].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); + /* Since TKIP, AES, WEP are all supported. It should not have any invalid setting */ + if (WepStatus <= Ndis802_11GroupWEP104Enabled) + { + if (pAd->ApCfg.MBSSID[pObj->ioctl_if].WepStatus != WepStatus) + { + /* Config has changed */ + pAd->bConfigChanged = TRUE; + } + pAd->ApCfg.MBSSID[pObj->ioctl_if].WepStatus = WepStatus; + + if (pAd->ApCfg.MBSSID[pObj->ioctl_if].WepStatus == Ndis802_11Encryption4Enabled){ + pAd->ApCfg.MBSSID[pObj->ioctl_if].GroupKeyWepStatus = Ndis802_11Encryption2Enabled; + } + else{ + pAd->ApCfg.MBSSID[pObj->ioctl_if].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 + { + //pSsidString = (PSTRING)kmalloc(MAX_LEN_OF_SSID+1, MEM_ALLOC_FLAG); + 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); + 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(pAd, pSsidString); + } + else + Status = -ENOMEM; + } + } + } + break; + + + case HOSTAPD_OID_SET_802_1X:/*pure 1x is enabled. */ + Set_IEEE8021X_Proc(pAd,"1"); + break; + + case HOSTAPD_OID_SET_KEY: + 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->Aid, + &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]; + KeyIdx = Key.ik_keyix& 0x0fff; + /* 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) */ + pMbss->DefaultKeyId = (UCHAR) KeyIdx; + } + /*pMbss->DefaultKeyId=1; */ + + pAd->SharedKey[apidx][KeyIdx].CipherAlg = Key.ik_type; + RTMP_ASIC_SHARED_KEY_TABLE(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->Aid, + &pEntry->PairwiseKey); + + RTMPSetWcidSecurityInfo(pAd, + pEntry->apidx, + (UINT8)KeyIdx, + pEntry->PairwiseKey.CipherAlg, + pEntry->Aid, + 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); + + RTMP_ASIC_SHARED_KEY_TABLE(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->Aid != 0) + { + NdisZeroMemory(&pEntry->PairwiseKey, sizeof(CIPHER_KEY)); + AsicRemovePairwiseKeyEntry(pAd,(UCHAR)pEntry->Aid); + } + } + 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: + + 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; */ + if (pAd->ApCfg.MBSSID[pObj->ioctl_if].IEEE8021X != TRUE) + break; + if (pEntry->WepStatus != Ndis802_11Encryption1Enabled) + break; + + apidx = pObj->ioctl_if; + pMbss = &pAd->ApCfg.MBSSID[apidx]; + KeyIdx=pMbss->DefaultKeyId; + 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->Aid, + &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->Aid; + 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. */ + apidx = pObj->ioctl_if; + + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + BOOLEAN hostapd_enable; + int v; + + Status = copy_from_user(&hostapd_enable, wrq->u.data.pointer, wrq->u.data.length); + pAd->ApCfg.MBSSID[apidx].Hostapd = hostapd_enable; + MULTISSID_STRUCT *pMBSSStruct; + + for (v=0;vApCfg.MBSSID[v].Hostapd == TRUE) + 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 0f 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. */ + apidx = pObj->ioctl_if; + DBGPRINT(RT_DEBUG_TRACE,("HOSTAPD_OID_SET_WPS_BEACON_IE\n")); + if (wrq->u.data.length != sizeof(WSC_LV_INFO)) + { + Status = -EINVAL; + } + else + { + 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 + { + 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*/ + + + default: + DBGPRINT(RT_DEBUG_TRACE, ("Set::unknown IOCTL's subcmd = 0x%08x\n", cmd)); + Status = -EOPNOTSUPP; + break; + } + +#ifdef MESH_SUPPORT + /* important parameter is changed, restart mesh */ + if (RestartMeshIsRequired) + { + MeshDown(pAd, TRUE); + MeshUp(pAd); + } +#endif /* MESH_SUPPORT */ + + return Status; +} + + +INT RTMPAPQueryInformation( + IN PRTMP_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; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + STRING driverVersion[8]; + +#if defined(DBG) || defined(WSC_AP_SUPPORT) + UCHAR apidx = pObj->ioctl_if; +#endif +#ifdef WSC_AP_SUPPORT + UINT WscPinCode = 0; + PWSC_PROFILE pProfile; + PWSC_CTRL pWscControl; +#endif /* WSC_AP_SUPPORT */ + +#ifdef SNMP_SUPPORT + /*for snmp, kathy */ + ULONG ulInfo; + 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*/ + + NDIS_802_11_STATISTICS *pStatistics; + ULONG ulInfo; + +#ifdef EASY_CONFIG_SETUP + PUCHAR pStaMacAddr = NULL; +#endif /* EASY_CONFIG_SETUP */ + +#ifdef P2P_SUPPORT + /*RT_P2P_UI_TABLE UI_table;*/ + PRT_P2P_UI_TABLE pUI_table; + PRT_P2P_TABLE pP2pTable; + PRT_P2P_CLIENT_ENTRY pPAdCli, pUICli; + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + UCHAR tmp[24]; + UCHAR i; +#endif /* P2P_SUPPORT */ + + + switch(cmd) + { +#ifdef P2P_SUPPORT + case OID_802_11_P2P_Connected_MAC: + wrq->u.data.length = MAC_ADDR_LEN; + Status = copy_to_user(wrq->u.data.pointer, &pAd->P2pCfg.ConnectingMAC, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_Connected_MAC\n")); + break; + + case OID_802_11_P2P_MODE: + wrq->u.data.length = sizeof(char); + Status = copy_to_user(wrq->u.data.pointer, &pAd->P2pCfg.Rule, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_MODE (Len=%d, Rule=%d)\n", sizeof(char), pAd->P2pCfg.Rule)); + break; + + case OID_802_11_P2P_DEVICE_NAME: + wrq->u.data.length = pAd->P2pCfg.DeviceNameLen; + Status = copy_to_user(wrq->u.data.pointer, pAd->P2pCfg.DeviceName, pAd->P2pCfg.DeviceNameLen); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_DEVICE_NAME (Len=%ld, DeviceName=%s)\n", pAd->P2pCfg.DeviceNameLen, pAd->P2pCfg.DeviceName)); + break; + + case OID_802_11_P2P_LISTEN_CHANNEL: + wrq->u.data.length = sizeof(char); + Status = copy_to_user(wrq->u.data.pointer, &pAd->P2pCfg.ListenChannel, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_LISTEN_CHANNEL (Len=%d, Listen_Ch=%d)\n", sizeof(char),pAd->P2pCfg.ListenChannel)); + break; + + case OID_802_11_P2P_OPERATION_CHANNEL: + wrq->u.data.length = sizeof(char); + Status = copy_to_user(wrq->u.data.pointer, &pAd->P2pCfg.GroupChannel, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_OPERATION_CHANNEL (Len=%d, Op_Ch=%d)\n", sizeof(char),pAd->P2pCfg.GroupOpChannel)); + break; + + + case OID_802_11_P2P_DEV_ADDR: + wrq->u.data.length = 6; + Status = copy_to_user(wrq->u.data.pointer, pAd->P2pCfg.CurrentAddress, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_DEV_ADDR (Len=%d, Addr=%02x:%02x:%02x:%02x:%02x:%02x)\n", wrq->u.data.length, PRINT_MAC(pAd->P2pCfg.CurrentAddress))); + break; + + case OID_802_11_P2P_CTRL_STATUS: + wrq->u.data.length = 24; + pP2PCtrl = &pAd->P2pCfg; + NdisZeroMemory(tmp, 24); + sprintf(tmp,"%s",decodeCtrlState(pP2PCtrl->CtrlCurrentState)); + Status = copy_to_user(wrq->u.data.pointer, tmp, 24); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_MODE (Len=%ld, DeviceName=%s)\n", pAd->P2pCfg.DeviceNameLen,pAd->P2pCfg.DeviceName)); + break; + + case OID_802_11_P2P_DISC_STATUS: + wrq->u.data.length = 24; + pP2PCtrl = &pAd->P2pCfg; + NdisZeroMemory(tmp, 24); + sprintf(tmp,"%s",decodeDiscoveryState(pP2PCtrl->DiscCurrentState)); + Status = copy_to_user(wrq->u.data.pointer, tmp, 24); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_MODE (Len=%ld, DeviceName=%s)\n", pAd->P2pCfg.DeviceNameLen,pAd->P2pCfg.DeviceName)); + break; + + case OID_802_11_P2P_GOFORM_STATUS: + wrq->u.data.length = 24; + pP2PCtrl = &pAd->P2pCfg; + NdisZeroMemory(tmp, 24); + sprintf(tmp,"%s",decodeGroupFormationState(pP2PCtrl->GoFormCurrentState)); + Status = copy_to_user(wrq->u.data.pointer, tmp, 24); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_MODE (Len=%ld, DeviceName=%s)\n", pAd->P2pCfg.DeviceNameLen,pAd->P2pCfg.DeviceName)); + break; + + case OID_802_11_P2P_SCAN_LIST: + + os_alloc_mem(NULL, (UCHAR **)&pUI_table, sizeof(RT_P2P_UI_TABLE)); + pP2pTable = &pAd->P2pTable; + if (pUI_table) + { + NdisZeroMemory(pUI_table, sizeof(RT_P2P_UI_TABLE)); + pUI_table->ClientNumber = pAd->P2pTable.ClientNumber; + for (i=0; i < pAd->P2pTable.ClientNumber; i++) + { + pPAdCli = &pP2pTable->Client[i]; + pUICli = &pUI_table->Client[i]; + NdisMoveMemory(pUICli, pPAdCli, sizeof(RT_P2P_CLIENT_ENTRY)); + } + wrq->u.data.length = sizeof(RT_P2P_UI_TABLE); + Status = copy_to_user(wrq->u.data.pointer, pUI_table, sizeof(RT_P2P_UI_TABLE)); + os_free_mem(NULL, pUI_table); + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_SCAN_LIST (Len=%d)\n", sizeof(RT_P2P_UI_TABLE))); + break; + + case OID_P2P_WSC_PIN_CODE: + wrq->u.data.length = sizeof(UINT); + WscPinCode = pAd->ApCfg.ApCliTab[0].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 OID_802_11_P2P_CONNECT_STATUS: + { + UCHAR stat = 0; + + wrq->u.data.length = sizeof(UCHAR); + if (P2P_GO_ON(pAd)) + { + pWscControl = &pAd->ApCfg.MBSSID[0].WscControl; + /*if ((pWscControl->WscState == WSC_STATE_CONFIGURED) || (pWscControl->WscStatus == WSC_STATE_CONFIGURED))*/ + if (pAd->P2pCfg.WscState == WSC_STATE_CONFIGURED) + stat = 1; + else + { + + for (i=0; iMacTab.Content[i]; + if ((IS_ENTRY_CLIENT(pEntry) || IS_ENTRY_APCLI(pEntry)) + && (pEntry->Sst == SST_ASSOC)) + { + stat = 1; + } + } + } + + } + if (P2P_CLI_ON(pAd)) + { + pWscControl = &pAd->ApCfg.ApCliTab[0].WscControl; + /*if ((pWscControl->WscState == WSC_STATE_CONFIGURED) || (pWscControl->WscStatus == WSC_STATE_CONFIGURED))*/ + if (pAd->P2pCfg.WscState == WSC_STATE_CONFIGURED) + stat = 2; + } + + if (copy_to_user(wrq->u.data.pointer, &stat, wrq->u.data.length)) + { + Status = -EFAULT; + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_CONNECT_STATUS (=%d)\n", stat)); + } + break; + + case OID_802_11_P2P_PEER_GROUP_ID: + { + UCHAR GroupId[128] = {0}; + wrq->u.data.length = sizeof(GroupId); + + + if (P2P_GO_ON(pAd)) + { + printk("OID_802_11_P2P_PEER_GROUP_ID bssid: %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pP2PCtrl->CurrentAddress)); + printk("OID_802_11_P2P_PEER_GROUP_ID ssid: %s\n", pAd->ApCfg.MBSSID[MAIN_MBSSID].Ssid); + sprintf(GroupId, "%02x:%02x:%02x:%02x:%02x:%02x %s", pP2PCtrl->CurrentAddress[0], pP2PCtrl->CurrentAddress[1], pP2PCtrl->CurrentAddress[2], + pP2PCtrl->CurrentAddress[3], pP2PCtrl->CurrentAddress[4], pP2PCtrl->CurrentAddress[5], pAd->ApCfg.MBSSID[MAIN_MBSSID].Ssid); + } + if (P2P_CLI_ON(pAd)) + { + printk("OID_802_11_P2P_PEER_GROUP_ID bssid: %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pP2PCtrl->Bssid)); + printk("OID_802_11_P2P_PEER_GROUP_ID ssid: %s\n", pP2PCtrl->SSID); + sprintf(GroupId, "%02x:%02x:%02x:%02x:%02x:%02x %s", pP2PCtrl->Bssid[0], pP2PCtrl->Bssid[1], pP2PCtrl->Bssid[2], + pP2PCtrl->Bssid[3], pP2PCtrl->Bssid[4], pP2PCtrl->Bssid[5], pP2PCtrl->SSID); + } + DBGPRINT(RT_DEBUG_TRACE, ("GROUP ID :: %s\n", GroupId)); + if (copy_to_user(wrq->u.data.pointer, &GroupId, wrq->u.data.length)) + { + Status = -EFAULT; + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_PEER_GROUP_ID (=%s)\n", GroupId)); + } + break; + case OID_802_11_P2P_GO_INT: + wrq->u.data.length = sizeof(char); + Status = copy_to_user(wrq->u.data.pointer, &pAd->P2pCfg.GoIntentIdx, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_GO_INT (GoIntentIdx=%d)\n", sizeof(char),pAd->P2pCfg.GoIntentIdx)); + break; + + case OID_802_11_P2P_SSID: + if (wrq->u.data.length >= pAd->P2pCfg.SSIDLen) + { + wrq->u.data.length = pAd->P2pCfg.SSIDLen; + Status = copy_to_user(wrq->u.data.pointer, pAd->P2pCfg.SSID, wrq->u.data.length); + + } + else + { + Status = -EFAULT; + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_SSID (SSIDLen=%d)\n", pAd->P2pCfg.SSIDLen)); + break; + + case OID_802_11_P2P_ASSOCIATE_TAB: + break; + break; +#endif /* P2P_SUPPORT */ + + 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", AP_DRIVER_VERSION); + driverVersion[7] = '\0'; + if (copy_to_user(wrq->u.data.pointer, &driverVersion, wrq->u.data.length)) + { + Status = -EFAULT; + } + 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")); + + + if (FlgIs11rSup == FALSE) + { + { + Status = -EFAULT; + } + } + } + break; + + +#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 */ +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + if (P2P_CLI_ON(pAd)) + { + INT ApCliIdx = pObj->ioctl_if; + APCLI_MR_APIDX_SANITY_CHECK(ApCliIdx); + WscStatus = pAd->ApCfg.ApCliTab[ApCliIdx].WscControl.WscStatus; + } + else + { + WscStatus = pAd->ApCfg.MBSSID[apidx].WscControl.WscStatus; + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_WscConfMode_Proc:: This command is from p2p interface now.\n", apidx)); + } + else +#endif /* P2P_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); */ +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + { + if (P2P_CLI_ON(pAd)) + { + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + } + else + { + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_WscConfMode_Proc:: This command is from p2p interface now.\n", apidx)); + } + else +#endif /* P2P_SUPPORT */ + 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; +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + if (P2P_CLI_ON(pAd)) + { + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + } + else + { + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_WscConfMode_Proc:: This command is from p2p interface now.\n", apidx)); + } + else +#endif /* P2P_SUPPORT */ + 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].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; + } +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + if (P2P_CLI_ON(pAd)) + { + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + } + else + { + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_WscConfMode_Proc:: This command is from p2p interface now.\n", apidx)); + } + else +#endif /* P2P_SUPPORT */ + 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; + } + +/* kfree(pProfile); */ + os_free_mem(NULL, pProfile); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_WSC_QUERY_PROFILE \n")); + break; +#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 */ +#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)) + { + 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; + } + } + 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 NINTENDO_AP + case RT_OID_802_11_NINTENDO_GET_TABLE: + RTMPIoctlNintendoGetTable(pAd, wrq); + break; +#endif /* NINTENDO_AP */ +#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; +#endif /* DOT1X_SUPPORT */ +#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")); + 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")); + /*KeyIdxValue.KeyIdx = pAd->PortCfg.MBSSID[pObj->ioctl_if].DefaultKeyId; */ + pKeyIdxValue = 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].DefaultKeyId].KeyLen; + NdisMoveMemory(pKeyIdxValue->Value, + &pAd->SharedKey[pObj->ioctl_if][pAd->ApCfg.MBSSID[pObj->ioctl_if].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].DefaultKeyId, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("DefaultKeyId =%d \n", pAd->ApCfg.MBSSID[pObj->ioctl_if].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].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 */ + + 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 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); + + 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; + PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[apidx]; + + os_alloc_mem(pAd, (UCHAR * *) &pMbssStat, sizeof(MBSS_STATISTICS)); + NdisZeroMemory(pMbssStat, sizeof(MBSS_STATISTICS)); + + pMbssStat->TransmittedByteCount = pMbss->TransmittedByteCount; + pMbssStat->ReceivedByteCount = pMbss->ReceivedByteCount; + 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) + { + INT i; + RT_802_11_TXBF_TABLE MacTab; + + MacTab.Num = 0; + for (i=0; iMacTab.Content[i]) && (pAd->MacTab.Content[i].Sst == SST_ASSOC)) + { + memcpy(&MacTab.Entry[MacTab.Num], &pAd->MacTab.Content[i].TxBFCounters, sizeof(RT_COUNTER_TXBF)); + MacTab.Num++; + } + } + + wrq->u.data.length = sizeof(RT_802_11_TXBF_TABLE); + Status = copy_to_user(wrq->u.data.pointer, &MacTab, wrq->u.data.length); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_TXBF_TABLE(chip not support)\n")); + Status= -EFAULT; + } + break; +#endif /* TXBF_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef MESH_SUPPORT + case OID_802_11_MESH_DEVICENAME: + if (pAd->MeshTab.dev) + { + wrq->u.data.length = strlen(RtmpOsGetNetDevName(pAd->MeshTab.dev)) + 1; + Status = copy_to_user(wrq->u.data.pointer, RtmpOsGetNetDevName(pAd->MeshTab.dev), strlen(RtmpOsGetNetDevName(pAd->MeshTab.dev))); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_DEVICENAME (Len=%d, Name=%s)\n", wrq->u.data.length, RtmpOsGetNetDevName(pAd->MeshTab.dev))); + } + break; + + case OID_802_11_MESH_SECURITY_INFO: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_SECURITY_INFO \n")); + if (wrq->u.data.length != sizeof(MESH_SECURITY_INFO)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Len Diff %d/%d \n", wrq->u.data.length, sizeof(MESH_SECURITY_INFO))); + Status = -EINVAL; + } + else + RTMPIoctlQueryMeshSecurityInfo(pAd, wrq); + break; + + case OID_802_11_MESH_ID: + wrq->u.data.length = pAd->MeshTab.MeshIdLen; + Status = copy_to_user(wrq->u.data.pointer, &pAd->MeshTab.MeshId, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_ID (Len=%d, MeshID=%s)\n", pAd->MeshTab.MeshIdLen, + pAd->MeshTab.MeshId)); + break; + + case OID_802_11_MESH_AUTO_LINK: + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &pAd->MeshTab.MeshAutoLink, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_AUTO_LINK (=%d)\n", pAd->MeshTab.MeshAutoLink)); + break; + + case OID_802_11_MESH_LINK_STATUS: + { + MESH_LINK_INFO MeshLinkInfo; + UCHAR i; + + NdisZeroMemory(&MeshLinkInfo, sizeof(MESH_LINK_INFO)); + + for (i=0; iMeshTab.MeshLink[i].Entry; + + COPY_MAC_ADDR(MeshLinkInfo.Entry[i].PeerMacAddr, pEntry->PeerMacAddr); + MeshLinkInfo.Entry[i].LinkType = pEntry->LinkType; + MeshLinkInfo.Entry[i].Status = PeerLinkValidCheck(pAd, i); + MeshLinkInfo.Entry[i].Rssi = + RTMPMaxRssi(pAd, pAd->MacTab.Content[pEntry->MacTabMatchWCID].RssiSample.AvgRssi0, + pAd->MacTab.Content[pEntry->MacTabMatchWCID].RssiSample.AvgRssi1, + pAd->MacTab.Content[pEntry->MacTabMatchWCID].RssiSample.AvgRssi2); + MeshLinkInfo.Entry[i].CurTxRate = pAd->MacTab.Content[pEntry->MacTabMatchWCID].HTPhyMode; + } + + wrq->u.data.length = sizeof(MESH_LINK_INFO); + Status = copy_to_user(wrq->u.data.pointer, &MeshLinkInfo, wrq->u.data.length); + } + break; + + case OID_802_11_MESH_LIST: + { + PMESH_NEIGHBOR_INFO pMeshNeighborInfo; /* = kmalloc(sizeof(MESH_NEIGHBOR_INFO), GFP_ATOMIC); */ + UCHAR i, idx = 0; + + os_alloc_mem(pAd, (UCHAR **)&pMeshNeighborInfo, sizeof(MESH_NEIGHBOR_INFO)); + if (pMeshNeighborInfo == NULL) + break; + + NdisZeroMemory(pMeshNeighborInfo, sizeof(MESH_NEIGHBOR_INFO)); + for (i=0; iMeshTab.pMeshNeighborTab->NeighborMP[i]; + + if (pEntry->Valid) + { + strcpy((PSTRING) pMeshNeighborInfo->Entry[idx].HostName, (PSTRING) pEntry->HostName); + COPY_MAC_ADDR(pMeshNeighborInfo->Entry[idx].MacAddr, pEntry->PeerMac); + strcpy((PSTRING) pMeshNeighborInfo->Entry[idx].MeshId, (PSTRING) pEntry->MeshId); + pMeshNeighborInfo->Entry[idx].Channel = pEntry->Channel; + pMeshNeighborInfo->Entry[idx].Rssi = pEntry->RealRssi; + pMeshNeighborInfo->Entry[idx].Status = pEntry->State != LINK_AVAILABLE ? 0 : 1; + pMeshNeighborInfo->Entry[idx].MeshEncrypType = + MeshCheckPeerMpCipher(pEntry->CapabilityInfo, pEntry->RSNIE, pEntry->RSNIE_Len);; + idx++; + } + } + pMeshNeighborInfo->num = idx; + wrq->u.data.length = sizeof(MESH_NEIGHBOR_INFO); + Status = copy_to_user(wrq->u.data.pointer, pMeshNeighborInfo, wrq->u.data.length); + + if (pMeshNeighborInfo) +/* kfree(pMeshNeighborInfo); */ + os_free_mem(NULL, pMeshNeighborInfo); + } + break; + + case OID_802_11_MESH_ROUTE_LIST: + { + PRT_MESH_ROUTE_TABLE rt_table; /* = kmalloc(sizeof(RT_MESH_ROUTE_TABLE), GFP_ATOMIC); */ + UCHAR i; + + os_alloc_mem(pAd, (UCHAR **)&rt_table, sizeof(RT_MESH_ROUTE_TABLE)); + if (rt_table == NULL) + break; + + NdisZeroMemory(rt_table, sizeof(RT_MESH_ROUTE_TABLE)); + + for (i=0; iMeshTab.pMeshRouteTab->Content[i]; + + if (pEntry->Valid) + { + COPY_MAC_ADDR(rt_table->Entry[rt_table->Num].MeshDA, pEntry->MeshDA); + rt_table->Entry[rt_table->Num].Dsn = pEntry->Dsn; + COPY_MAC_ADDR(rt_table->Entry[rt_table->Num].NextHop, pEntry->NextHop); + rt_table->Entry[rt_table->Num].Metric = pEntry->PathMetric; + rt_table->Num++; + } + } + + wrq->u.data.length = sizeof(RT_MESH_ROUTE_TABLE); + Status = copy_to_user(wrq->u.data.pointer, rt_table, wrq->u.data.length); + + if (rt_table) +/* kfree(rt_table); */ + os_free_mem(NULL, rt_table); + + DBGPRINT(RT_DEBUG_OFF, ("Query::OID_802_11_MESH_ROUTE_LIST \n")); + } + break; + + case OID_802_11_MESH_MAX_TX_RATE: + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &pAd->MeshTab.MeshMaxTxRate, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_CHANNEL (=%d)\n", pAd->MeshTab.MeshChannel)); + break; + + case OID_802_11_MESH_CHANNEL: + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &pAd->MeshTab.MeshChannel, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_CHANNEL (=%d)\n", pAd->MeshTab.MeshChannel)); + break; + + case OID_802_11_MESH_HOSTNAME: + wrq->u.data.length = strlen((PSTRING) pAd->MeshTab.HostName) + 1; + Status = copy_to_user(wrq->u.data.pointer, &pAd->MeshTab.HostName, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_HOSTNAME (MeshHostName=%s)\n", pAd->MeshTab.HostName)); + break; + case OID_802_11_MESH_ONLY_MODE: + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &pAd->MeshTab.MeshOnly, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_ONLY_MODE (=%s)\n", pAd->MeshTab.MeshOnly == TRUE ? "Enable" : "Disable")); + break; +#endif /* MESH_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->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->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) +#ifdef P2P_SUPPORT + && (pObj->ioctl_if_type != INT_P2P) +#endif /* P2P_SUPPORT */ + ) + { + 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) +#ifdef P2P_SUPPORT + && !IS_ENTRY_P2PCLI(pEntry) +#endif /* P2P_SUPPORT */ + ) + { + MediaState = NdisMediaStateDisconnected; + } + else + { + 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)) + { + 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)) + { + 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)) + { + 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 */ + +#ifdef EASY_CONFIG_SETUP + case OID_PIN_OF_ENROLLEE: + os_alloc_mem(NULL, &pStaMacAddr, MAC_ADDR_LEN); + if (pStaMacAddr) + { + Status = copy_from_user(pStaMacAddr, wrq->u.data.pointer, MAC_ADDR_LEN); + if (Status == NDIS_STATUS_SUCCESS) + { + PMAC_TABLE_ENTRY pEntry = NULL; + PEASY_CONFIG_INFO pEasyConf = &pAd->ApCfg.MBSSID[pObj->ioctl_if].EasyConfigInfo; + + DBGPRINT(RT_DEBUG_TRACE,("Query::OID_PIN_OF_ENROLLEE(STA - %02X:%02X:%02X:%02X:%02X:%02X)\n", + pStaMacAddr[0], + pStaMacAddr[1], + pStaMacAddr[2], + pStaMacAddr[3], + pStaMacAddr[4], + pStaMacAddr[5])); + pEntry = MacTableLookup(pAd, pStaMacAddr); + if (pEntry && pEntry->bRaAutoWpsCapable) + { + wrq->u.data.length = 8; + Status = copy_to_user(wrq->u.data.pointer, pEasyConf->WpsPinCode, wrq->u.data.length); + } + else + wrq->u.data.length = 0; + } + os_free_mem(NULL, pStaMacAddr); + } + break; +#endif /* EASY_CONFIG_SETUP */ + +#ifdef WAC_SUPPORT + case RT_OID_WAC_REQ: + if (wrq->u.data.length < sizeof(WAC_REQUEST)) + { + Status = -EINVAL; + } + else + { + WAC_IoctlReq(pAd, pObj->ioctl_if, wrq); + } + break; +#endif /* WAC_SUPPORT */ + + 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) +{ + + if(strlen(arg) == 2) + { + NdisMoveMemory(pAd->CommonCfg.CountryCode, arg, 2); + pAd->CommonCfg.bCountryFlag = TRUE; + } + else + { + NdisZeroMemory(pAd->CommonCfg.CountryCode, 3); + pAd->CommonCfg.bCountryFlag = FALSE; + } + + 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) + { + switch(pAd->CommonCfg.PhyMode) + { + case PHY_11BG_MIXED: /* 0 */ + case PHY_11B: /* 1 */ + case PHY_11G: /* 4 */ +#ifdef DOT11_N_SUPPORT + case PHY_11N_2_4G: /* 6 */ + case PHY_11GN_MIXED: /* 7 */ + case PHY_11BGN_MIXED: /* 9 */ +#endif /* DOT11_N_SUPPORT */ + if (pAd->CommonCfg.CountryRegionForABand & 0x80) + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryString_Proc::parameter of CountryRegion in eeprom is programmed \n")); + success = FALSE; + } + else + { + if (allCountry[index].SupportGBand == TRUE) + { + NdisZeroMemory(pAd->CommonCfg.CountryCode, 3); + NdisMoveMemory(pAd->CommonCfg.CountryCode, allCountry[index].IsoName, 2); + pAd->CommonCfg.CountryCode[2] = ' '; + + pAd->CommonCfg.bCountryFlag = TRUE; + + pAd->CommonCfg.CountryRegion = (UCHAR) allCountry[index].RegDomainNum11G; + + /* 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); */ + + success = TRUE; + } + else + { + success = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("The Country are not Support G Band Channel\n")); + } + } + + break; + case PHY_11A: /* 2 */ +#ifdef DOT11_N_SUPPORT + case PHY_11AN_MIXED: /* 8 */ + case PHY_11N_5G: /* 11 */ +#endif /* DOT11_N_SUPPORT */ + if (pAd->CommonCfg.CountryRegion & 0x80) + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryString_Proc::parameter of CountryRegion in eeprom is programmed \n")); + success = FALSE; + } + else + { + if (allCountry[index].SupportABand == TRUE) + { + NdisZeroMemory(pAd->CommonCfg.CountryCode, 3); + NdisMoveMemory(pAd->CommonCfg.CountryCode, allCountry[index].IsoName, 2); + pAd->CommonCfg.CountryCode[2] = ' '; + + pAd->CommonCfg.bCountryFlag = TRUE; + + pAd->CommonCfg.CountryRegionForABand = (UCHAR) allCountry[index].RegDomainNum11A; + + /* 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); */ + + success = TRUE; + } + else + { + success = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("The Country are not Support A Band Channel\n")); + } + } + break; + + default : + success = FALSE; + break; + } + } + + if (success == 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; +} + + +/* + ========================================================================== + Description: + Set SSID + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_SSID_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + INT success = FALSE; + POS_COOKIE pObj = (POS_COOKIE) pAdapter->OS_Cookie; + MULTISSID_STRUCT *pMBSSStruct; + + if(strlen(arg) <= MAX_LEN_OF_SSID) + { + pMBSSStruct = &pAdapter->ApCfg.MBSSID[pObj->ioctl_if]; + NdisZeroMemory(pMBSSStruct->Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pMBSSStruct->Ssid, arg, strlen(arg)); + pMBSSStruct->SsidLen = (UCHAR)strlen(arg); + success = TRUE; + + +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + RT_CfgSetWPAPSKKey( pAdapter, + pAdapter->P2pCfg.PhraseKey, + pAdapter->P2pCfg.PhraseKeyLen, + (PUCHAR)pMBSSStruct->Ssid, + pMBSSStruct->SsidLen, + pMBSSStruct->PMK); + + NdisZeroMemory(pAdapter->P2pCfg.SSID, MAX_LEN_OF_SSID); + NdisMoveMemory(pAdapter->P2pCfg.SSID, arg, strlen(arg)); + pAdapter->P2pCfg.SSIDLen = (UCHAR)strlen(arg); + + if (P2P_GO_ON(pAdapter)) + { + P2P_GoStop(pAdapter); + P2P_GoStartUp(pAdapter, MAIN_MBSSID); + DBGPRINT(RT_DEBUG_TRACE, ("I/F(p2p%d) Set_SSID_Proc::(Len=%d,Ssid=%s)\n", pObj->ioctl_if, + pMBSSStruct->SsidLen, pMBSSStruct->Ssid)); + } + } + else +#endif /* P2P_SUPPORT */ + { + /* If in detection mode, need to stop detect first. */ + if (pAdapter->CommonCfg.bIEEE80211H == FALSE) + { + APStop(pAdapter); + APStartUp(pAdapter); + } + else + { + /* each mode has different restart method */ + if (pAdapter->Dot11_H.RDMode == RD_SILENCE_MODE) + { + APStop(pAdapter); + APStartUp(pAdapter); + } + else if (pAdapter->Dot11_H.RDMode == RD_SWITCHING_MODE) + { + } + else if (pAdapter->Dot11_H.RDMode == RD_NORMAL_MODE) + { + APStop(pAdapter); + APStartUp(pAdapter); + AsicEnableBssSync(pAdapter); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Set_SSID_Proc::(Len=%d,Ssid=%s)\n", pObj->ioctl_if, + pAdapter->ApCfg.MBSSID[pObj->ioctl_if].SsidLen, pAdapter->ApCfg.MBSSID[pObj->ioctl_if].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( + IN PRTMP_ADAPTER pAd, + IN 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; +} + +#ifdef RT305x +INT Set_RfRead_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + int i; + UCHAR Value; + + for (i = 0; i < 32; i++) + { + RT30xxReadRFRegister(pAdapter, i, &Value); + printk("%02x ", Value); + if (((i + 1) % 4) == 0) + printk("\n"); + } + return TRUE; +} + +INT Set_RfWrite_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg) +{ + ULONG offset = 0; + ULONG value = 0; + PUCHAR p2 = (PUCHAR)arg; + + while((*p2 != ':') && (*p2 != '\0')) + { + p2++; + } + + if (*p2 == ':') + { + A2Hex(offset, arg); + A2Hex(value, p2+ 1); + } + else + { + A2Hex(value, arg); + } + + if (offset >= 32) + { + return FALSE; + } + + RT30xxWriteRFRegister(pAdapter, offset, value); + + return TRUE; +} +#endif /* RT305x */ + + +/* + ========================================================================== + 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].bWmmCapable = TRUE; + else if (bWmmCapable == 0) + pAd->ApCfg.MBSSID[pObj->ioctl_if].bWmmCapable = FALSE; + else + return FALSE; /*Invalid argument */ + + pAd->ApCfg.MBSSID[pObj->ioctl_if].bWmmCapableOrg = \ + pAd->ApCfg.MBSSID[pObj->ioctl_if].bWmmCapable; + +#ifdef RTL865X_FAST_PATH + if (!isFastPathCapable(pAd)) { + rtlairgo_fast_tx_unregister(); + rtl865x_extDev_unregisterUcastTxDev(pAd->net_dev); + } +#endif + +#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].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=%ld)\n", + pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].IsolateInterStaTraffic)); + + 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=%ld)\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; + + pAd->ApCfg.MBSSID[pObj->ioctl_if].VLAN_VID = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_VLANID_Proc::(VLAN_VID=%d)\n", pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].VLAN_VID)); + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set VLAN's priority field + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_VLANPriority_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + pAd->ApCfg.MBSSID[pObj->ioctl_if].VLAN_Priority = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_VLANPriority_Proc::(VLAN_Priority=%d)\n", pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].VLAN_Priority)); + + 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; + + 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; + } + } + + /* reset the PortSecure this BSS */ + pAd->ApCfg.MBSSID[apidx].PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + /* Default key index is always 2 in WPA mode */ + if(pAd->ApCfg.MBSSID[apidx].AuthMode >= Ndis802_11AuthModeWPA) + pAd->ApCfg.MBSSID[apidx].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; + + if ((strcmp(arg, "NONE") == 0) || (strcmp(arg, "none") == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11WEPDisabled; + else if ((strcmp(arg, "WEP") == 0) || (strcmp(arg, "wep") == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11WEPEnabled; + else if ((strcmp(arg, "TKIP") == 0) || (strcmp(arg, "tkip") == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11Encryption2Enabled; + else if ((strcmp(arg, "AES") == 0) || (strcmp(arg, "aes") == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11Encryption3Enabled; + else if ((strcmp(arg, "TKIPAES") == 0) || (strcmp(arg, "tkipaes") == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11Encryption4Enabled; +#ifdef WAPI_SUPPORT + else if ((strcmp(arg, "SMS4") == 0) || (strcmp(arg, "sms4") == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11EncryptionSMS4Enabled; +#endif /* WAPI_SUPPORT */ + else + return FALSE; + + if (pAd->ApCfg.MBSSID[apidx].WepStatus >= Ndis802_11Encryption2Enabled) + pAd->ApCfg.MBSSID[apidx].DefaultKeyId = 1; + + /* decide the group key encryption type */ + if (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11Encryption4Enabled) + pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus = Ndis802_11Encryption2Enabled; + else + pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus = pAd->ApCfg.MBSSID[apidx].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, pAd->ApCfg.MBSSID[apidx].WepStatus)); + + 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; + + /* + 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) + */ + if ((strncmp(arg, "WPA_AES_WPA2_TKIPAES", 20) == 0) || (strncmp(arg, "wpa_aes_wpa2_tkipaes", 20) == 0)) + pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher = WPA_AES_WPA2_TKIPAES; + else if ((strncmp(arg, "WPA_AES_WPA2_TKIP", 17) == 0) || (strncmp(arg, "wpa_aes_wpa2_tkip", 17) == 0)) + pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher = WPA_AES_WPA2_TKIP; + else if ((strncmp(arg, "WPA_TKIP_WPA2_AES", 17) == 0) || (strncmp(arg, "wpa_tkip_wpa2_aes", 17) == 0)) + pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher = WPA_TKIP_WPA2_AES; + else if ((strncmp(arg, "WPA_TKIP_WPA2_TKIPAES", 21) == 0) || (strncmp(arg, "wpa_tkip_wpa2_tkipaes", 21) == 0)) + pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher = WPA_TKIP_WPA2_TKIPAES; + else if ((strncmp(arg, "WPA_TKIPAES_WPA2_AES", 20) == 0) || (strncmp(arg, "wpa_tkipaes_wpa2_aes", 20) == 0)) + pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher = WPA_TKIPAES_WPA2_AES; + else if ((strncmp(arg, "WPA_TKIPAES_WPA2_TKIPAES", 24) == 0) || (strncmp(arg, "wpa_tkipaes_wpa2_tkipaes", 24) == 0)) + pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIPAES; + else if ((strncmp(arg, "WPA_TKIPAES_WPA2_TKIP", 21) == 0) || (strncmp(arg, "wpa_tkipaes_wpa2_tkip", 21) == 0)) + pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIP; + else + return FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Set_AP_WpaMixPairCipher_Proc=0x%02x\n", apidx, pAd->ApCfg.MBSSID[apidx].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; +} + +/* + ========================================================================== + 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; +} + +/* + ========================================================================== + 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].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].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].AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + RTMP_ASIC_SHARED_KEY_TABLE(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].AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + RTMP_ASIC_SHARED_KEY_TABLE(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].AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + RTMP_ASIC_SHARED_KEY_TABLE(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].AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + RTMP_ASIC_SHARED_KEY_TABLE(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")); + 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; + +#ifdef WSC_AP_SUPPORT + NdisZeroMemory(pMBSSStruct->WscControl.WpaPsk, 64); + pMBSSStruct->WscControl.WpaPskLen = 0; + pMBSSStruct->WscControl.WpaPskLen = strlen(arg); + if (P2P_GO_ON(pAd)) + pMBSSStruct->WscControl.WscConfStatus = WSC_SCSTATE_CONFIGURED; + NdisMoveMemory(pMBSSStruct->WscControl.WpaPsk, arg, pMBSSStruct->WscControl.WpaPskLen); +#endif /* WSC_AP_SUPPORT */ + +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + PRT_P2P_CONFIG pP2pCfg = &pAd->P2pCfg; + NdisZeroMemory(pP2pCfg->PhraseKey, 64); + pP2pCfg->PhraseKeyLen = 0; + pP2pCfg->PhraseKeyLen = strlen(arg); + NdisMoveMemory(pP2pCfg->PhraseKey, arg, pP2pCfg->PhraseKeyLen); + } +#endif /* P2P_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; + +} + +#endif /* AP_SCAN_SUPPORT */ + +INT Show_DriverInfo_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + printk("Driver version: %s\n", AP_DRIVER_VERSION); + + return TRUE; +} + +INT Show_MacTable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i;/*, QueIdx=0; */ + UINT32 RegValue; + ULONG DataRate=0; + /*PRXD_STRUC pRxD; */ + /*PTXD_STRUC pTxD; */ + /*PRTMP_TX_RING pTxRing = &pAd->TxRing[QueIdx]; */ + /*PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing; */ + /*PRTMP_RX_RING pRxRing = &pAd->RxRing; */ +#ifdef DPA_S //yiwei + UCHAR index; + BOOLEAN bFound; +#endif /* DPA_S */ + + 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 */ + +#ifdef DPA_S //yiwei + printk("\n%-19s%-4s%-4s%-4s%-4s%-8s%-7s%-7s%-7s%-10s%-6s%-6s%-6s%-6s%-7s%-7s%-32s\n", + "MAC", "AID", "BSS", "PSM", "WMM", "MIMOPS", "RSSI0", "RSSI1", + "RSSI2", "PhMd", "BW", "MCS", "SGI", "STBC", "Idle", "Rate", "DevName"); +#else /* DPA_S */ + 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"); +#endif /* !DPA_S */ + + for (i=0; iMacTab.Content[i]; + +#ifdef DPA_S + if ((IS_P2P_GO_ENTRY(pEntry) || IS_P2P_CLI_ENTRY(pEntry)) + && (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)) +#else /* DPA_S */ + if ((IS_ENTRY_CLIENT(pEntry) || IS_ENTRY_APCLI(pEntry)) + && (pEntry->Sst == SST_ASSOC)) +#endif /* !DPA_S */ + { + DataRate=0; + getRate(pEntry->HTPhyMode, &DataRate); + +#ifdef DPA_S //yiwei + if (IS_P2P_GO_ENTRY(pEntry)) + { + index = P2pGroupTabSearch(pAd, pEntry->Addr); + if(index != P2P_NOT_FOUND) + bFound = TRUE; + else + bFound = FALSE; + } + else + { + bFound = FALSE; + } +#endif + + 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->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", GetPhyMode(pEntry->HTPhyMode.field.MODE)); + printk("%-6s", GetBW(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); +#ifdef DPA_S //yiwei + printk("%-32s%\n", bFound ? &pAd->P2pTable.Client[index].DeviceName[0]:"N/A"); +#endif /* DPA_S */ + printk("\n"); + } + } + + return TRUE; +} + +INT Show_StaCount_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i;/*, QueIdx=0; */ + 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_StaSecurityInfo_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i; + UCHAR apidx; + + printk("\n"); + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + printk(" BSS(%d) AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s, WPAMixPairCipher(0x%02X)\n", + apidx, + pAd->ApCfg.MBSSID[apidx].AuthMode, + GetAuthMode(pAd->ApCfg.MBSSID[apidx].AuthMode), + pAd->ApCfg.MBSSID[apidx].WepStatus, + GetEncryptType(pAd->ApCfg.MBSSID[apidx].WepStatus), + pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus, + GetEncryptType(pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus), + pAd->ApCfg.MBSSID[apidx].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 ", + 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->apidx); + printk("%-15s", GetAuthMode(pEntry->AuthMode)); + printk("%-12s", GetEncryptType(pEntry->WepStatus)); + printk("\n"); + } + } + + return TRUE; +} + + +#ifdef DOT11_N_SUPPORT +INT Show_BaTable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT i, j; + BA_ORI_ENTRY *pOriBAEntry; + BA_REC_ENTRY *pRecBAEntry; + STRING tmpBuf[6]; + + for (i=0; iMacTab.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)) + 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", + pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], + pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5], 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 */ + + +#ifdef RTMP_MAC_PCI +#ifdef DBG_DIAGNOSE +INT Set_DiagOpt_Proc( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + INT32 i, QueIdx=0; + ULONG RegValue; + PRXD_STRUC pRxD; + PTXD_STRUC pTxD; +#ifdef RT_BIG_ENDIAN + PRXD_STRUC pDestRxD; + RXD_STRUC RxD; + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; +#endif /* RT_BIG_ENDIAN */ + PRTMP_TX_RING pTxRing = &pAd->TxRing[QueIdx]; + PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing; + PRTMP_RX_RING pRxRing = &pAd->RxRing; + + printk("\n"); + RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue); + printk("BackOff Slot : %s slot time, BKOFF_SLOT_CFG(0x1104) = 0x%08lx\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.RxSwReadIdx, + pAd->RxRing.RxCpuIdx, + pAd->RxRing.RxDmaIdx); + +#ifdef RT_BIG_ENDIAN + pDestRxD = (PRXD_STRUC) pRxRing->Cell[pAd->RxRing.RxSwReadIdx].AllocVa; + RxD = *pDestRxD; + pRxD = &RxD; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + pRxD = (PRXD_STRUC) pRxRing->Cell[pAd->RxRing.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.RxCpuIdx].AllocVa; + RxD = *pDestRxD; + pRxD = &RxD; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + pRxD = (PRXD_STRUC) pRxRing->Cell[pAd->RxRing.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.RxDmaIdx].AllocVa; + RxD = *pDestRxD; + pRxD = &RxD; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + pRxD = (PRXD_STRUC) pRxRing->Cell[pAd->RxRing.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", GetPhyMode(pEntry->HTPhyMode.field.MODE)); + printk("%-6s", GetBW(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; +} + +INT Show_Diag_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + RtmpDiagStruct *pDiag; + UCHAR i, start, stop, McsIdx, SwQNumLevel, TxDescNumLevel; + unsigned long irqFlags; + UCHAR McsMaxIdx = MAX_MCS_SET; + + + pDiag = &pAd->DiagStruct; + + if (pDiag->inited == FALSE) + return TRUE; + + RTMP_IRQ_LOCK(&pAd->irq_lock, irqFlags); + 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->TxDataCnt[i]); + } + printk("\n %-12s", "TxFailCnt"); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->TxFailCnt[i]); + } + printk("\n %-12s", "TxAggCnt"); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->TxAggCnt[i]); + } + printk("\n"); + + + 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->TxSWQueCnt[i][SwQNumLevel]); + } + printk("\n"); + } + + 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->TxDescCnt[i][TxDescNumLevel]); + } + printk("\n"); + } + +#ifdef DOT11_N_SUPPORT + 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->TxAMPDUCnt[i][McsIdx], pDiag->TxAMPDUCnt[i][McsIdx] ? (pDiag->TxAMPDUCnt[i][McsIdx] * 100 / pDiag->TxAggCnt[i]) : 0); + } +/* printk("\n\t%-6s", "R(%)"); */ +/* for (i = start, count=0; count < DIAGNOSE_TIME; i = (i+1) % DIAGNOSE_TIME, count++) */ +/* { */ +/* printk("%-5d", pDiag->TxAMPDUCnt[i][McsIdx] ? (pDiag->TxAMPDUCnt[i][McsIdx] * 100 / pDiag->TxTotalCnt[i]) : 0); */ +/* } */ + printk("\n"); + } +#endif /* DOT11_N_SUPPORT */ + + printk("\n %-12s\n", "TxMcsCnt"); + for (McsIdx =0 ; McsIdx < McsMaxIdx; McsIdx++) + { + printk("\t%-6d", McsIdx); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->TxMcsCnt[i][McsIdx]); + } + printk("\n"); + } + + printk("Rx Info\n"); + printk(" %-12s", "RxDataCnt"); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->RxDataCnt[i]); + } + printk("\n %-12s", "RxCrcErrCnt"); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->RxCrcErrCnt[i]); + } + printk("\n %-12s\n", "RxMcsCnt"); + for (McsIdx =0 ; McsIdx < McsMaxIdx; McsIdx++) /* 3*3 */ + { + printk("\t%-6d", McsIdx); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->RxMcsCnt[i][McsIdx]); + } + printk("\n"); + } + printk("\n-------------\n"); + + RTMP_IRQ_UNLOCK(&pAd->irq_lock, irqFlags); + + return TRUE; + +} +#endif /* DBG_DIAGNOSE */ +#endif /* RTMP_MAC_PCI */ + + +INT Show_Sat_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + /* Sanity check for calculation of sucessful count */ + + printk("TransmittedFragmentCount = %d\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); +#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 = %ld\n", (ULONG)pAd->ApCfg.MBSSID[apidx].RxCount); + printk("Packets Sent = %ld\n", (ULONG)pAd->ApCfg.MBSSID[apidx].TxCount); + printk("Bytes Received = %ld\n", (ULONG)pAd->ApCfg.MBSSID[apidx].ReceivedByteCount); + printk("Byte Sent = %ld\n", (ULONG)pAd->ApCfg.MBSSID[apidx].TransmittedByteCount); + printk("Error Packets Received = %ld\n", (ULONG)pAd->ApCfg.MBSSID[apidx].RxErrorCount); + printk("Drop Received Packets = %ld\n", (ULONG)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; + + + 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]); + } + } + } + } + } + } + +} + +#ifdef DOT11_N_SUPPORT +{ + TX_AGG_CNT_STRUC TxAggCnt; + TX_AGG_CNT0_STRUC TxAggCnt0; + TX_AGG_CNT1_STRUC TxAggCnt1; + TX_AGG_CNT2_STRUC TxAggCnt2; + TX_AGG_CNT3_STRUC TxAggCnt3; + UINT32 totalCount; + + 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); + + totalCount = TxAggCnt.field.NonAggTxCount + TxAggCnt.field.AggTxCount; + printk("Tx_Agg_Cnt->NonAggTxCount=%d!, AggTxCount=%d!\n", TxAggCnt.field.NonAggTxCount, TxAggCnt.field.AggTxCount); + printk("\tTx_Agg_Cnt 1 MPDU=%d(%d%%)!\n", TxAggCnt0.field.AggSize1Count, TxAggCnt0.field.AggSize1Count ? (TxAggCnt0.field.AggSize1Count * 100 / totalCount) : 0); + printk("\tTx_Agg_Cnt 2 MPDU=%d(%d%%)!\n", TxAggCnt0.field.AggSize2Count, TxAggCnt0.field.AggSize2Count ? (TxAggCnt0.field.AggSize2Count * 100 / totalCount) : 0); + printk("\tTx_Agg_Cnt 3 MPDU=%d(%d%%)!\n", TxAggCnt1.field.AggSize3Count, TxAggCnt1.field.AggSize3Count ? (TxAggCnt1.field.AggSize3Count * 100 / totalCount) : 0); + printk("\tTx_Agg_Cnt 4 MPDU=%d(%d%%)!\n", TxAggCnt1.field.AggSize4Count, TxAggCnt1.field.AggSize4Count ? (TxAggCnt1.field.AggSize4Count * 100 / totalCount) : 0); + printk("\tTx_Agg_Cnt 5 MPDU=%d(%d%%)!\n", TxAggCnt2.field.AggSize5Count, TxAggCnt2.field.AggSize5Count ? (TxAggCnt2.field.AggSize5Count * 100 / totalCount) : 0); + printk("\tTx_Agg_Cnt 6 MPDU=%d(%d%%)!\n", TxAggCnt2.field.AggSize6Count, TxAggCnt2.field.AggSize6Count ? (TxAggCnt2.field.AggSize6Count * 100 / totalCount) : 0); + printk("\tTx_Agg_Cnt 7 MPDU=%d(%d%%)!\n", TxAggCnt3.field.AggSize7Count, TxAggCnt3.field.AggSize7Count ? (TxAggCnt3.field.AggSize7Count * 100 / totalCount) : 0); + printk("\tTx_Agg_Cnt 8 MPDU=%d(%d%%)!\n", TxAggCnt3.field.AggSize8Count, (TxAggCnt3.field.AggSize8Count ? (TxAggCnt3.field.AggSize8Count * 100 / totalCount) : 0)); + printk("====================\n"); + +} +#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 = %d\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); +#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; +#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; + PMAC_TABLE_ENTRY pEntry; + + 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=15; 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=15; 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<16; j++) + { + pEntry->TXMCSExpected[j] = 0; + pEntry->TXMCSSuccessful[j] = 0; + pEntry->TXMCSFailed[j] = 0; + for(k=15; k>=0; k--) + { + pEntry->TXMCSAutoFallBack[j][k] = 0; + } + } + } + +#ifdef DOT11_N_SUPPORT +{ + TX_AGG_CNT_STRUC TxAggCnt; + TX_AGG_CNT0_STRUC TxAggCnt0; + TX_AGG_CNT1_STRUC TxAggCnt1; + TX_AGG_CNT2_STRUC TxAggCnt2; + TX_AGG_CNT3_STRUC TxAggCnt3; + UINT32 totalCount, ratio1, ratio2, ratio3, ratio4, ratio5, ratio6, ratio7, ratio8; + + 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); + + totalCount = TxAggCnt.field.NonAggTxCount + TxAggCnt.field.AggTxCount; + ratio1 = TxAggCnt0.field.AggSize1Count ? (TxAggCnt0.field.AggSize1Count * 100 / totalCount) : 0; + ratio2 = TxAggCnt0.field.AggSize2Count ? (TxAggCnt0.field.AggSize2Count * 100 / totalCount) : 0; + ratio3 = TxAggCnt1.field.AggSize3Count ? (TxAggCnt1.field.AggSize3Count * 100 / totalCount) : 0; + ratio4 = TxAggCnt1.field.AggSize4Count ? (TxAggCnt1.field.AggSize4Count * 100 / totalCount) : 0; + ratio5 = TxAggCnt2.field.AggSize5Count ? (TxAggCnt2.field.AggSize5Count * 100 / totalCount) : 0; + ratio6 = TxAggCnt2.field.AggSize6Count ? (TxAggCnt2.field.AggSize6Count * 100 / totalCount) : 0; + ratio7 = TxAggCnt3.field.AggSize7Count ? (TxAggCnt3.field.AggSize7Count * 100 / totalCount) : 0; + ratio8 = TxAggCnt3.field.AggSize8Count ? (TxAggCnt3.field.AggSize8Count * 100 / totalCount) : 0; + + printk("Tx_Agg_Cnt->NonAggTxCount=%d!, AggTxCount=%d!\n", TxAggCnt.field.NonAggTxCount, TxAggCnt.field.AggTxCount); + printk("\tTx_Agg_Cnt 1 MPDU=%d(%d%%)!\n", TxAggCnt0.field.AggSize1Count, ratio1); + printk("\tTx_Agg_Cnt 2 MPDU=%d(%d%%)!\n", TxAggCnt0.field.AggSize2Count, ratio2); + printk("\tTx_Agg_Cnt 3 MPDU=%d(%d%%)!\n", TxAggCnt1.field.AggSize3Count, ratio3); + printk("\tTx_Agg_Cnt 4 MPDU=%d(%d%%)!\n", TxAggCnt1.field.AggSize4Count, ratio4); + printk("\tTx_Agg_Cnt 5 MPDU=%d(%d%%)!\n", TxAggCnt2.field.AggSize5Count, ratio5); + printk("\tTx_Agg_Cnt 6 MPDU=%d(%d%%)!\n", TxAggCnt2.field.AggSize6Count, ratio6); + printk("\tTx_Agg_Cnt 7 MPDU=%d(%d%%)!\n", TxAggCnt3.field.AggSize7Count, ratio7); + printk("\tTx_Agg_Cnt 8 MPDU=%d(%d%%)!\n", TxAggCnt3.field.AggSize8Count, ratio8); + printk("\tRatio: 1(%d%%), 2(%d%%), 3(%d%%), 4(%d%%), 5(%d%%), 6(%d%%), 7(%d%%), 8(%d%%)!\n", + ratio1+ratio2+ratio3+ratio4+ratio5+ratio6+ratio7+ratio8, + ratio2+ratio3+ratio4+ratio5+ratio6+ratio7+ratio8, + ratio3+ratio4+ratio5+ratio6+ratio7+ratio8, + ratio4+ratio5+ratio6+ratio7+ratio8, + ratio5+ratio6+ratio7+ratio8, + ratio6+ratio7+ratio8, + ratio7+ratio8, + ratio8); + printk("====================\n"); + +} +#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); + + 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->IEEE8021X) ? 1 : 0; + + if (p1xBssInfo->ieee8021xWEP) + { + /* Default Key index, length and material */ + keyidx = pMbss->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; + + if ((pAd->ApCfg.MBSSID[pObj->ioctl_if].AuthMode == Ndis802_11AuthModeWPA) + || (pAd->ApCfg.MBSSID[pObj->ioctl_if].AuthMode == Ndis802_11AuthModeWPA2) + || (pAd->ApCfg.MBSSID[pObj->ioctl_if].AuthMode == Ndis802_11AuthModeWPA1WPA2) + || (pAd->ApCfg.MBSSID[pObj->ioctl_if].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].AuthMode >= Ndis802_11AuthModeWPA) + { + if ((pKey->KeyLength == 32) || (pKey->KeyLength == 64)) + { + if ((pEntry = MacTableLookup(pAd, pKey->addr)) != NULL) + { + INT k_offset = 0; + + + 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; + PUCHAR Key; + + 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].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; + Key = pAd->SharedKey[apidx][KeyIdx].Key; + + /* Set Group key material to Asic */ + RTMP_ASIC_SHARED_KEY_TABLE(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->Aid, + &pEntry->PairwiseKey); + + /* update WCID attribute table and IVEIV table for this entry */ + RTMPSetWcidSecurityInfo(pAd, + pEntry->apidx, + (UINT8)KeyIdx, + pEntry->PairwiseKey.CipherAlg, + pEntry->Aid, + 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].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].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 + { + UINT32 len; + + len = 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].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->Aid, + &pEntry->PairwiseKey); + + /* update WCID attribute table and IVEIV table for this entry */ + RTMPSetWcidSecurityInfo(pAd, + pEntry->apidx, + (UINT8)KeyIdx, + pEntry->PairwiseKey.CipherAlg, + pEntry->Aid, + 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; +} +#endif /* DOT1X_SUPPORT */ + +#ifdef DBG +/* + ========================================================================== + 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) +{ + 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, Status; + + + +/* mpool = (PSTRING)kmalloc(sizeof(CHAR)*(MAX_BBP_MSG_SIZE+256+12), MEM_ALLOC_FLAG); */ + 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; + bCopyMsg = ((wrq->u.data.flags & RTPRIV_IOCTL_FLAG_NOSPACE) == RTPRIV_IOCTL_FLAG_NOSPACE) ? FALSE : TRUE; + argLen = strlen((char *)(wrq->u.data.pointer)); + + + if (argLen > 1) + { + 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); + 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); + 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); + 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); + sprintf(msg+strlen(msg), "R%02d[0x%02X]:%02X ", bbpId, bbpId, regBBP); + if (bbpId%5 == 4) + sprintf(msg+strlen(msg), "\n"); + } + } + } + else + { + } + + if (bCopyMsg) + { + /* 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); + } + + if (!bAllowDump) + { + DBGPRINT(RT_DEBUG_TRACE, ("strlen(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")); +} + + +/* + ========================================================================== + 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 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; + UINT32 macAddr = 0; + UCHAR temp[16]; + STRING temp2[16]; + UINT32 macValue; + BOOLEAN bIsPrintAllMAC = FALSE, bFromUI; + + +/* 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; + } + + 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); + 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 */ + /* 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; */ + } + + /* 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(pAdapter, macAddr, &macValue); + if (!bFromUI) + DBGPRINT(RT_DEBUG_TRACE, ("MacAddr=0x%x, MacValue=0x%x\n", macAddr, macValue)); + sprintf(msg+strlen(msg), "[0x%08x]:%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; /*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[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) + { + pAdapter->BbpTuning.bEnable = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("turn on R17 tuning\n")); + } + else + { + UCHAR R66; + pAdapter->BbpTuning.bEnable = FALSE; + R66 = 0x26 + GET_LNA_GAIN(pAdapter); + /* todo AsicBBPWriteWithRxChain(pAd, BBP_R66, R66, RX_CHAIN_ALL); */ + if (!bFromUI) + DBGPRINT(RT_DEBUG_TRACE, ("turn off R66 tuning, restore to 0x%02x\n", R66)); + } + return; + } + if (!bFromUI) + DBGPRINT(RT_DEBUG_TRACE, ("MacAddr=%02x, MacValue=0x%x\n", macAddr, macValue)); + + RTMP_IO_WRITE32(pAdapter, macAddr, macValue); + sprintf(msg+strlen(msg), "[0x%08x]:%08x ", macAddr, macValue); + } + } + } + } else { + UINT32 IdMac; + + for(IdMac=0; IdMac<=0x1500; IdMac+=4) + { + if ((IdMac & 0x0f) == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("\n0x%04x: ", IdMac)); + } + + RTMP_IO_READ32(pAdapter, IdMac, &macValue); + DBGPRINT(RT_DEBUG_TRACE, ("%08x ", macValue)); + } + + bIsPrintAllMAC = TRUE; + } + + + 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_TRACE, ("<==RTMPIoctlMAC\n\n")); +} + + +#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); + + 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 + ATE_RF_IO_READ8_BY_REG_ID(pAdapter, rfId, ®RF); +#endif /* RT6352 */ + /* 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 + ATE_RF_IO_READ8_BY_REG_ID(pAdapter, rfId, ®RF); + ATE_RF_IO_WRITE8_BY_REG_ID(pAdapter, (UCHAR)rfId,(UCHAR) rfValue); +#endif + + + /* Read it back for showing. */ +#ifdef RT6352 + if (IS_RT6352(pAdapter)) + ATE_RF_IO_READ8_BY_REG_ID(pAdapter, pAdapter->RfBank, rfId, ®RF); +#else + ATE_RF_IO_READ8_BY_REG_ID(pAdapter, rfId, ®RF); +#endif /* RT6352 */ + /* 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 + ATE_RF_IO_READ8_BY_REG_ID(pAdapter, rfId, ®RF); +#endif /* RT6352 */ + /* 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"); + } + } + } + /* RtmpDrvAllRFPrint(NULL, msg, strlen(msg)); */ + /* 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 ((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 */ + + /* 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 & 0x7) == 0x7) + 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")); +} + + +/* + ========================================================================== + 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( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + INT Status; + PSTRING msg; +#ifdef WSC_AP_SUPPORT + UCHAR idx = 0; +#endif /* WSC_AP_SUPPORT */ +#ifdef P2P_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; +#endif /* P2P_SUPPORT */ + +/* 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, 1600); + sprintf(msg, "\n"); + +#ifdef RALINK_ATE + if(ATE_ON(pAd)) + { + sprintf(msg+strlen(msg), "Tx success = %ld\n", (ULONG)pAd->ate.TxDoneCount); + /*sprintf(msg+strlen(msg), "Tx success without retry = %ld\n", (ULONG)pAd->ate.TxDoneCount); */ + } + else +#endif /* RALINK_ATE */ + { + sprintf(msg+strlen(msg), "Tx success = %ld\n", (ULONG)pAd->WlanCounters.TransmittedFragmentCount.u.LowPart); + /*sprintf(msg+strlen(msg), "Tx success without retry = %ld\n", (ULONG)pAd->WlanCounters.TransmittedFragmentCount.u.LowPart - (ULONG)pAd->WlanCounters.RetryCount.u.LowPart); */ + } + 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); + +#ifdef RALINK_ATE + 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)); + } + } + else +#endif /* RALINK_ATE */ + { + 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)); + } + +#ifdef WSC_AP_SUPPORT + sprintf(msg+strlen(msg), "WPS Information:\n"); +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + if (pAd->ApCfg.ApCliTab[0].WscControl.WscEnrolleePinCodeLen == 8) + sprintf(msg+strlen(msg), "P2P Client PinCode %08u\n", + pAd->ApCfg.ApCliTab[0].WscControl.WscEnrolleePinCode); + else + sprintf(msg+strlen(msg), "P2P Client PinCode %04u\n", + pAd->ApCfg.ApCliTab[0].WscControl.WscEnrolleePinCode); + sprintf(msg+strlen(msg), "P2P Client WPS Profile Count = %d\n", + pAd->ApCfg.ApCliTab[0].WscControl.WscProfile.ProfileCnt); + } + else +#endif /* P2P_SUPPORT */ + { + 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); + } + } +#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 */ + sprintf(msg+strlen(msg), "P2P Information:\n"); + sprintf(msg+strlen(msg), "My Rule = %s\n", decodeMyRule(pAd->P2pCfg.Rule)); + sprintf(msg+strlen(msg), "Listen Channel = %d\n", pAd->P2pCfg.ListenChannel); + sprintf(msg+strlen(msg), "WPS Config Method = %s\n", decodeConfigMethod(pAd->P2pCfg.ConfigMethod)); + sprintf(msg+strlen(msg), "Peer PinCode = %c%c%c%c%c%c%c%c\n", pAd->P2pCfg.PinCode[0], pAd->P2pCfg.PinCode[1], pAd->P2pCfg.PinCode[2], pAd->P2pCfg.PinCode[3], + pAd->P2pCfg.PinCode[4], pAd->P2pCfg.PinCode[5], pAd->P2pCfg.PinCode[6], pAd->P2pCfg.PinCode[7]); + + /* 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); + + os_free_mem(NULL, msg); +/* kfree(msg); */ + 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)); + + 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)); + + ApCliIfDown(pAd); + + return TRUE; +} + +INT Set_ApCli_Ssid_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR ifIndex; + BOOLEAN apcliEn; + INT success = FALSE; + /*UCHAR keyMaterial[40]; */ + + 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) + { + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + + /* bring apcli interface down first */ + if(apcliEn == TRUE ) + { + pAd->ApCfg.ApCliTab[ifIndex].Enable = FALSE; + ApCliIfDown(pAd); + } + + 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); + success = TRUE; + + /* Upadte PMK and restart WPAPSK state machine for ApCli link */ + if (((pAd->ApCfg.ApCliTab[ifIndex].AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->ApCfg.ApCliTab[ifIndex].AuthMode == Ndis802_11AuthModeWPA2PSK)) && + pAd->ApCfg.ApCliTab[ifIndex].PSKLen > 0) + { + RT_CfgSetWPAPSKKey(pAd, (PSTRING)pAd->ApCfg.ApCliTab[ifIndex].PSK, + pAd->ApCfg.ApCliTab[ifIndex].PSKLen, + (PUCHAR)pAd->ApCfg.ApCliTab[ifIndex].CfgSsid, + pAd->ApCfg.ApCliTab[ifIndex].CfgSsidLen, + pAd->ApCfg.ApCliTab[ifIndex].PMK); + } + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_Ssid_Proc::(Len=%d,Ssid=%s)\n", ifIndex, + pAd->ApCfg.ApCliTab[ifIndex].CfgSsidLen, pAd->ApCfg.ApCliTab[ifIndex].CfgSsid)); + + pAd->ApCfg.ApCliTab[ifIndex].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; + 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( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG i; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex; + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + + if ((strcmp(arg, "WEPAUTO") == 0) || (strcmp(arg, "wepauto") == 0)) + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeAutoSwitch; + else if ((strcmp(arg, "SHARED") == 0) || (strcmp(arg, "shared") == 0)) + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeShared; + else if ((strcmp(arg, "WPAPSK") == 0) || (strcmp(arg, "wpapsk") == 0)) + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeWPAPSK; + else if ((strcmp(arg, "WPA2PSK") == 0) || + (strcmp(arg, "wpa2psk") == 0) || + (strcmp(arg, "WPAPSKWPA2PSK") == 0)) + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeWPA2PSK; + else + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeOpen; + + 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; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_ApCli_AuthMode_Proc::(AuthMode=%d)\n", ifIndex, pAd->ApCfg.ApCliTab[ifIndex].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; + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + pApCliEntry->WepStatus = Ndis802_11WEPDisabled; + if ((strcmp(arg, "WEP") == 0) || (strcmp(arg, "wep") == 0)) + { + if (pApCliEntry->AuthMode < Ndis802_11AuthModeWPA) + pApCliEntry->WepStatus = Ndis802_11WEPEnabled; + } + else if ((strcmp(arg, "TKIP") == 0) || (strcmp(arg, "tkip") == 0)) + { + if (pApCliEntry->AuthMode >= Ndis802_11AuthModeWPA) + pApCliEntry->WepStatus = Ndis802_11Encryption2Enabled; + } + else if ((strcmp(arg, "AES") == 0) || (strcmp(arg, "aes") == 0) || (strcmp(arg, "TKIPAES") == 0)) + { + if (pApCliEntry->AuthMode >= Ndis802_11AuthModeWPA) + pApCliEntry->WepStatus = Ndis802_11Encryption3Enabled; + } + else + { + pApCliEntry->WepStatus = Ndis802_11WEPDisabled; + } + + pApCliEntry->PairCipher = pApCliEntry->WepStatus; + pApCliEntry->GroupCipher = pApCliEntry->WepStatus; + pApCliEntry->bMixCipher = FALSE; + + if (pApCliEntry->WepStatus >= Ndis802_11Encryption2Enabled) + pApCliEntry->DefaultKeyId = 1; + + RTMPMakeRSNIE(pAd, pApCliEntry->AuthMode, pApCliEntry->WepStatus, (ifIndex + MIN_NET_DEVICE_FOR_APCLI)); + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_ApCli_EncrypType_Proc::(EncrypType=%d)\n", ifIndex, pApCliEntry->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; + UCHAR ifIndex; + PAPCLI_STRUCT pApCliEntry = NULL; + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + KeyIdx = simple_strtol(arg, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + pApCliEntry->DefaultKeyId = (UCHAR) (KeyIdx - 1 ); + else + return FALSE; /*Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_DefaultKeyID_Proc::(DefaultKeyID(0~3)=%d)\n", ifIndex, pApCliEntry->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; + + NdisMoveMemory(pApCliEntry->PSK, arg, strlen(arg)); + pApCliEntry->PSKLen = strlen(arg); + + 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; + 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->DesiredTransmitSetting.field.FixedTxMode = + RT_CfgSetFixedTxPhyMode(arg); + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_TxMode_Proc = %d\n", ifIndex, + pApCliEntry->DesiredTransmitSetting.field.FixedTxMode)); + + return TRUE; +} + +INT Set_ApCli_TxMcs_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->DesiredTransmitSetting.field.MCS = + RT_CfgSetTxMCSProc(arg, &pApCliEntry->bAutoTxRateSwitch); + + if (pApCliEntry->DesiredTransmitSetting.field.MCS == MCS_AUTO) + { + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_TxMcs_Proc = AUTO\n", ifIndex)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_TxMcs_Proc = %d\n", ifIndex, + pApCliEntry->DesiredTransmitSetting.field.MCS)); + } + + return TRUE; +} + +#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 */ +#endif /* APCLI_SUPPORT */ + + +#ifdef WSC_AP_SUPPORT +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 == TRUE) + { + 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_WscConfMode_Proc:: This command is from apcli interface now.\n", apidx)); + } + else +#endif /* APCLI_SUPPORT */ +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + if (P2P_CLI_ON(pAd)) + { + bFromApCli = TRUE; + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + } + else + { + bFromApCli = FALSE; + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_WscConfMode_Proc:: This command is from p2p interface now.\n", apidx)); + } + else +#endif /* P2P_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)); + } + + 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; + WscInit(pAd, TRUE, apidx); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_WscConfMode_Proc:: Ap Client only supports Enrollee mode.(ConfModeIdx=%d)\n", apidx, ConfModeIdx)); + return FALSE; + } + } + else +#endif /* APCLI_SUPPORT */ + { + pWscControl->WscConfMode = (ConfModeIdx & WSC_ENROLLEE_PROXY_REGISTRAR); + WscInit(pAd, FALSE, apidx | MIN_NET_DEVICE_FOR_P2P_GO); + } + pWscControl->WscStatus = STATUS_WSC_IDLE; + } + +#ifdef APCLI_SUPPORT + if (bFromApCli) + { + memcpy(mac_addr, &pAd->ApCfg.ApCliTab[apidx].CurrentAddress[0], MAC_ADDR_LEN); + } + else +#endif /* APCLI_SUPPORT */ + { + memcpy(mac_addr, &pAd->ApCfg.MBSSID[apidx].Bssid[0], MAC_ADDR_LEN); + } + + DBGPRINT(RT_DEBUG_TRACE, ("IF(%02X:%02X:%02X:%02X:%02X:%02X) Set_WscConfMode_Proc::(WscConfMode(0~7)=%d)\n", + mac_addr[0], + mac_addr[1], + mac_addr[2], + mac_addr[3], + mac_addr[4], + mac_addr[5], + 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 == TRUE) + { + 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 */ + +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + if (P2P_CLI_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_WscConfStatus_Proc:: P2P Client doesn't need this command.\n", apidx)); + return FALSE; + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_WscConfStatus_Proc:: This command is from p2p interface now.\n", apidx)); + } +#endif /* P2P_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 | MIN_NET_DEVICE_FOR_P2P_GO, 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", + pAd->ApCfg.MBSSID[apidx].Bssid[0], + pAd->ApCfg.MBSSID[apidx].Bssid[1], + pAd->ApCfg.MBSSID[apidx].Bssid[2], + pAd->ApCfg.MBSSID[apidx].Bssid[3], + pAd->ApCfg.MBSSID[apidx].Bssid[4], + pAd->ApCfg.MBSSID[apidx].Bssid[5], + 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 == TRUE) + { + 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 */ +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + if (P2P_CLI_ON(pAd)) + { + bFromApCli = TRUE; + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + } + else + { + bFromApCli = FALSE; + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_WscMode_Proc:: This command is from p2p interface now.\n", apidx)); + } + else +#endif /* P2P_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].CurrentAddress, MAC_ADDR_LEN); + } + else +#endif /* APCLI_SUPPORT */ + { + memcpy(mac_addr, pAd->ApCfg.MBSSID[apidx].Bssid, MAC_ADDR_LEN); + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(%02X:%02X:%02X:%02X:%02X:%02X) Set_WscMode_Proc::(WscMode=%d)\n", + mac_addr[0], + mac_addr[1], + mac_addr[2], + mac_addr[3], + mac_addr[4], + mac_addr[5], + 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 = pAd->ApCfg.ApCliTab[apidx].Enable; +#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 == TRUE) + { + 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 (apcliEn == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_WscMode_Proc:: ApCli is disabled.\n", apidx)); + return FALSE; + } + bFromApCli = TRUE; + apidx &= (~MIN_NET_DEVICE_FOR_APCLI); + 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 */ +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + if (P2P_CLI_ON(pAd)) + { + bFromApCli = TRUE; + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + } + else + { + bFromApCli = FALSE; + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_AP_WscGetConf_Proc:: This command is from p2p interface now.\n", apidx & 0x0F)); + } + else +#endif /* P2P_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)); + } + + 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; + } + WscInitRegistrarPair(pAd, pWscControl, apidx); + /* Enrollee 192 random bytes for DH key generation */ + for (idx = 0; idx < 192; idx++) + pWscControl->RegData.EnrolleeRandom[idx] = RandomByte(pAd); + +#ifdef APCLI_SUPPORT + if (bFromApCli) + { + /* bring apcli interface down first */ + pAd->ApCfg.ApCliTab[apidx].Enable = FALSE; + ApCliIfDown(pAd); + + NdisMoveMemory(pWscControl->RegData.SelfInfo.MacAddr, + pAd->ApCfg.ApCliTab[apidx].CurrentAddress, + 6); + + pAd->ApCfg.ApCliTab[apidx].Enable = apcliEn; + NdisMoveMemory(mac_addr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress, MAC_ADDR_LEN); + } + else +#endif /* APCLI_SUPPORT */ + { + INT WscDpid; +#ifdef P2P_SUPPORT + /* As become P2P GO, update the DPID in Beacon and Probe Rsp. */ + if (pAd->P2pCfg.Dpid != DEV_PASS_ID_NOSPEC) + WscDpid = pAd->P2pCfg.Dpid; + else +#endif /* P2P_SUPPORT */ + WscDpid = WscMode; + + WscBuildBeaconIE(pAd, IsAPConfigured, TRUE, WscDpid, pWscControl->WscConfigMethods, apidx, NULL, 0, AP_MODE); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, IsAPConfigured, TRUE, WscDpid, pWscControl->WscConfigMethods, (apidx | MIN_NET_DEVICE_FOR_P2P_GO), NULL, 0, AP_MODE); + APUpdateBeaconFrame(pAd, apidx); + NdisMoveMemory(mac_addr, pAd->ApCfg.MBSSID[apidx].Bssid, MAC_ADDR_LEN); + } + + { + /* 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) + { + WscAssignEntryMAC(pAd, pWscControl); + WscSendUPnPConfReqMsg(pAd, pWscControl->EntryIfIdx, + (PUCHAR)pAd->ApCfg.MBSSID[pWscControl->EntryIfIdx].Ssid, + pAd->ApCfg.MBSSID[apidx].Bssid, 3, 0, AP_MODE); + } + +#ifdef WSC_LED_SUPPORT +#ifdef CONFIG_WIFI_LED_SHARE + /* Change FW default mode to HUAWEI WPS 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_SHARE */ + WPSLEDStatus = LED_WPS_IN_PROCESS; + RTMPSetLED(pAd, WPSLEDStatus); +#endif /* WSC_LED_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("IF(%02X:%02X:%02X:%02X:%02X:%02X) Set_WscGetConf_Proc trigger WSC state machine, wscGetConfMode=%d\n", + mac_addr[0], + mac_addr[1], + mac_addr[2], + mac_addr[3], + mac_addr[4], + mac_addr[5], + wscGetConfMode)); + + return TRUE; +} + +INT Set_AP_WscPinCode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT PinCode = 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 == TRUE) + { + 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 */ +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + bFromApCli = FALSE; + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_WscMode_Proc:: This command is from p2p interface now.\n", apidx)); + } +#endif /* P2P_SUPPORT */ + + 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:%s)\n", arg)); + return FALSE; + } + else + { + pWscControl->WscPinCode = PinCode; + pWscControl->WscLastPinFromEnrollee = pWscControl->WscPinCode; + pWscControl->WscRejectSamePinFromEnrollee = FALSE; + /* PIN Code */ + if (strlen(arg) == 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); + } + } +#ifdef P2P_SUPPORT + if (pObj->ioctl_if_type == INT_P2P) + { + PWSC_CTRL pP2pCliWscCtrl; + pP2pCliWscCtrl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + pP2pCliWscCtrl->WscPinCodeLen = pWscControl->WscPinCodeLen; + pP2pCliWscCtrl->WscPinCode = pWscControl->WscPinCode; + WscGetRegDataPIN(pAd, pP2pCliWscCtrl->WscPinCode, pP2pCliWscCtrl); + } +#endif /* P2P_SUPPORT */ + } + 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].CurrentAddress, MAC_ADDR_LEN); + } + else +#endif /* APCLI_SUPPORT */ + { + memcpy(mac_addr, pAd->ApCfg.MBSSID[apidx].Bssid, MAC_ADDR_LEN); + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(%02X:%02X:%02X:%02X:%02X:%02X) Set_WscPinCode_Proc::(PinCode=%d)\n", + mac_addr[0], + mac_addr[1], + mac_addr[2], + mac_addr[3], + mac_addr[4], + mac_addr[5], + 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 == TRUE) + { + 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_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].Bssid[3], + pAd->ApCfg.MBSSID[apidx].Bssid[4], + pAd->ApCfg.MBSSID[apidx].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 == TRUE) + { + 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; + WscBuildBeaconIE(pAd, IsAPConfigured, FALSE, 0, 0, apidx, NULL, 0, AP_MODE); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, IsAPConfigured, FALSE, 0, 0, apidx | MIN_NET_DEVICE_FOR_P2P_GO, NULL, 0, AP_MODE); + APUpdateBeaconFrame(pAd, apidx); + WscStop(pAd, FALSE, pWscControl); + } + + 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; + +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[apidx].Hostapd == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + return; + } +#endif /*HOSTAPD_SUPPORT*/ + + + 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 (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + Profile.WscAuthMode = WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK; + else + Profile.WscAuthMode = WscGetAuthType(pAd->ApCfg.MBSSID[apidx].AuthMode); + if (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11Encryption4Enabled) + Profile.WscEncrypType = WSC_ENCRTYPE_TKIP |WSC_ENCRTYPE_AES; + else + Profile.WscEncrypType = WscGetEncryType(pAd->ApCfg.MBSSID[apidx].WepStatus); + NdisZeroMemory(Profile.WscWPAKey, 64 + 1); + + if (Profile.WscEncrypType == 2) + { + Profile.DefaultKeyIdx = pAd->ApCfg.MBSSID[apidx].DefaultKeyId + 1; + { + int i; + for (i=0; iSharedKey[apidx][pAd->ApCfg.MBSSID[apidx].DefaultKeyId].KeyLen; i++) + { + snprintf((PSTRING) Profile.WscWPAKey, sizeof(Profile.WscWPAKey), + "%s%02x", Profile.WscWPAKey, + pAd->SharedKey[apidx][pAd->ApCfg.MBSSID[apidx].DefaultKeyId].Key[i]); + } + Profile.WscWPAKey[(pAd->SharedKey[apidx][pAd->ApCfg.MBSSID[apidx].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; + } + + 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 (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + sprintf(msg+strlen(msg), "%-12s", "WPAPSKWPA2PSK"); + else + sprintf(msg+strlen(msg), "%-12s", WscGetAuthTypeStr(Profile.WscAuthMode)); + if (pAd->ApCfg.MBSSID[apidx].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); +} + +#ifdef INF_AR9 +#ifdef AR9_MAPI_SUPPORT + +/* + ========================================================================== + 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; + + 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 (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + Profile.WscAuthMode = WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK; + else + Profile.WscAuthMode = WscGetAuthType(pAd->ApCfg.MBSSID[apidx].AuthMode); + if (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11Encryption4Enabled) + Profile.WscEncrypType = WSC_ENCRTYPE_TKIP |WSC_ENCRTYPE_AES; + else + Profile.WscEncrypType = WscGetEncryType(pAd->ApCfg.MBSSID[apidx].WepStatus); + NdisZeroMemory(Profile.WscWPAKey, 64 + 1); + + if (Profile.WscEncrypType == 2) + { + Profile.DefaultKeyIdx = pAd->ApCfg.MBSSID[apidx].DefaultKeyId + 1; + { + int i; + for (i=0; iSharedKey[apidx][pAd->ApCfg.MBSSID[apidx].DefaultKeyId].KeyLen; i++) + { + snprintf((PSTRING) Profile.WscWPAKey, sizeof(Profile.WscWPAKey), + "%s%02x", Profile.WscWPAKey, + pAd->SharedKey[apidx][pAd->ApCfg.MBSSID[apidx].DefaultKeyId].Key[i]); + } + Profile.WscWPAKey[(pAd->SharedKey[apidx][pAd->ApCfg.MBSSID[apidx].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 (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + sprintf(msg+strlen(msg), "%-12s", "WPAPSKWPA2PSK"); + else + sprintf(msg+strlen(msg), "%-12s", WscGetAuthTypeStr(Profile.WscAuthMode)); + if (pAd->ApCfg.MBSSID[apidx].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); + 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); + 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 /*AR9_MAPI_SUPPORT*/ +#endif/* INF_AR9 */ +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_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].Bssid[3], + pAd->ApCfg.MBSSID[apidx].Bssid[4], + pAd->ApCfg.MBSSID[apidx].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 + 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; +} + +#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_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) + pWscControl->bSetupLock = FALSE; + else + pWscControl->bSetupLock = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscSetupLock_Proc::(bSetupLock=%d)\n", + pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl.bSetupLock)); + 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; + INT IsAPConfigured = pWscControl->WscConfStatus; + + 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].WepStatus == Ndis802_11WEPEnabled) || + (pAd->ApCfg.MBSSID[pObj->ioctl_if].WepStatus == Ndis802_11Encryption2Enabled) || + (pAd->ApCfg.MBSSID[pObj->ioctl_if].bHideSsid)) + WscOnOff(pAd, pObj->ioctl_if | MIN_NET_DEVICE_FOR_P2P_GO, TRUE); + else + WscOnOff(pAd, pObj->ioctl_if | MIN_NET_DEVICE_FOR_P2P_GO, FALSE); + APUpdateBeaconFrame(pAd, pObj->ioctl_if); + } + else + { + WscInit(pAd, FALSE, (pObj->ioctl_if | MIN_NET_DEVICE_FOR_P2P_GO)); + } + + 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; +} +#endif /* WSC_V2_SUPPORT */ +#endif /* WSC_AP_SUPPORT */ + +#ifdef EASY_CONFIG_SETUP +INT Set_AP_AutoProvisionEnable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PEASY_CONFIG_INFO pEasyConfig = &pAd->ApCfg.MBSSID[apidx].EasyConfigInfo; + BOOLEAN bEnable = FALSE; + + if (strcmp(arg, "0") == 0) + bEnable = FALSE; + else if (strcmp(arg, "1") == 0) + bEnable = TRUE; + else + return FALSE; + + if (pEasyConfig->bEnable != bEnable) + { + pEasyConfig->bEnable = bEnable; +#ifdef WSC_AP_SUPPORT + WscInit(pAd, FALSE, apidx); +#endif /* WSC_AP_SUPPORT */ + } + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_AP_AutoProvisionEnable_Proc::(AutoProvisionEnable=%d)\n", + apidx, pEasyConfig->bEnable)); + + return TRUE; +} + +INT Set_RssiThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + CHAR Value; + PEASY_CONFIG_INFO pEasyConfig = NULL; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + + if (apidx != MAIN_MBSSID) + { + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_RssiThreshold_Proc:: Only support ra0\n",apidx)); + return FALSE; + } + Value = (CHAR)simple_strtol(arg, 0, 10); + + pEasyConfig = &pAd->ApCfg.MBSSID[apidx].EasyConfigInfo; + + if (Value > 70 || Value < 40) + pEasyConfig->RssiThreshold = -50; + else + pEasyConfig->RssiThreshold = (CHAR)(-1)*Value; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_RssiThreshold_Proc::(RssiThreshold=%d)\n",pEasyConfig->RssiThreshold)); + + return TRUE; +} + +#endif /* EASY_CONFIG_SETUP */ + +#ifdef WAC_SUPPORT +INT Set_AP_WACEnable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PEASY_CONFIG_INFO pEasyConfig = &pAd->ApCfg.MBSSID[apidx].EasyConfigInfo; + BOOLEAN bEnable = FALSE; + + if (strcmp(arg, "0") == 0) + bEnable = FALSE; + else if (strcmp(arg, "1") == 0) + bEnable = TRUE; + else + return FALSE; + + pEasyConfig->bEnableWAC = bEnable; + APUpdateBeaconFrame(pAd, pObj->ioctl_if); + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_AP_WACEnable_Proc::(bEnableWAC=%d)\n", + apidx, pEasyConfig->bEnableWAC)); + + return TRUE; +} +#endif /* WAC_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); + 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; + UCHAR HashIdx; + 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, &macAddr[i++], 1); + } + + HashIdx = MAC_ADDR_HASH_INDEX(macAddr); + pEntry = pAd->MacTab.Hash[HashIdx]; + + if (pEntry) + { + MlmeDeAuthAction(pAd, pEntry, REASON_DISASSOC_STA_LEAVING, FALSE); +/* MacTableDeleteEntry(pAd, pEntry->Aid, Addr); */ + } + + return TRUE; +} + +INT Set_DisConnectAllSta_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + MacTableReset(pAd); + + 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; + + ieee8021x = simple_strtol(arg, 0, 10); + + if (ieee8021x == 1) + pAd->ApCfg.MBSSID[pObj->ioctl_if].IEEE8021X = TRUE; + else if (ieee8021x == 0) + pAd->ApCfg.MBSSID[pObj->ioctl_if].IEEE8021X = FALSE; + else + return FALSE; /*Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_IEEE8021X_Proc::(IEEE8021X=%d)\n", pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].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) +{ + if (simple_strtol(arg, 0, 10) != 0) + pAd->ApCfg.MBSSID[0].UapsdInfo.bAPSDCapable = TRUE; + else + pAd->ApCfg.MBSSID[0].UapsdInfo.bAPSDCapable = FALSE; + /* End of if */ + + 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; + break; +#ifdef DOT11_N_SUPPORT + case MCAST_HTMIX: /* HTMIX */ + pAd->CommonCfg.MCastPhyMode.field.MODE = MODE_HTMIX; + break; +#endif /* DOT11_N_SUPPORT */ + default: + printk("unknow Muticast PhyMode %d.\n", PhyMode); + printk("0:Disable 1:CCK, 2:OFDM, 3:HTMIX.\n"); + break; + } + + return TRUE; +} + +INT Set_McastMcs( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UCHAR Mcs = simple_strtol(arg, 0, 10); + + if (Mcs > 15) + printk("Mcs must in range of 0 to 15\n"); + + switch(pAd->CommonCfg.MCastPhyMode.field.MODE) + { + case MODE_CCK: + if ((Mcs <= 3) || (Mcs >= 8 && Mcs <= 11)) + pAd->CommonCfg.MCastPhyMode.field.MCS = Mcs; + else + printk("MCS must in range of 0 ~ 3 and 8 ~ 11 for CCK Mode.\n"); + break; + + case MODE_OFDM: + if (Mcs > 7) + printk("MCS must in range from 0 to 7 for CCK 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) +{ + printk("Mcast PhyMode =%d\n", pAd->CommonCfg.MCastPhyMode.field.MODE); + printk("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; +} +#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) +{ + if ((strcmp(arg, "WEPAUTO") == 0) || (strcmp(arg, "wepauto") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeAutoSwitch; + else if ((strcmp(arg, "OPEN") == 0) || (strcmp(arg, "open") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeOpen; + else if ((strcmp(arg, "SHARED") == 0) || (strcmp(arg, "shared") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeShared; + else if ((strcmp(arg, "WPAPSK") == 0) || (strcmp(arg, "wpapsk") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPAPSK; + else if ((strcmp(arg, "WPA2PSK") == 0) || (strcmp(arg, "wpa2psk") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPA2PSK; + else if ((strcmp(arg, "WPAPSKWPA2PSK") == 0) || (strcmp(arg, "wpapskwpa2psk") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPA1PSKWPA2PSK; +#ifdef DOT1X_SUPPORT + else if ((strcmp(arg, "WPA") == 0) || (strcmp(arg, "wpa") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPA; + else if ((strcmp(arg, "WPA2") == 0) || (strcmp(arg, "wpa2") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPA2; + else if ((strcmp(arg, "WPA1WPA2") == 0) || (strcmp(arg, "wpa1wpa2") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPA1WPA2; +#endif /* DOT1X_SUPPORT */ +#ifdef WAPI_SUPPORT + else if ((strcmp(arg, "WAICERT") == 0) || (strcmp(arg, "waicert") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWAICERT; + else if ((strcmp(arg, "WAIPSK") == 0) || (strcmp(arg, "waipsk") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWAIPSK; +#endif /* WAPI_SUPPORT */ + else + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeOpen; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d)::AuthMode=%d\n", apidx, pAd->ApCfg.MBSSID[apidx].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; +} + + +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 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; + + + 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].PhyMode; + DBGPRINT(RT_DEBUG_ERROR, ("\t%d\t\t", IdBss-1)); + } /* End of if */ + + switch(PhyMode) + { + case PHY_11BG_MIXED: + DBGPRINT(RT_DEBUG_ERROR, ("BG Mixed\n")); + break; + + case PHY_11B: + DBGPRINT(RT_DEBUG_ERROR, ("B Only\n")); + break; + + case PHY_11A: + DBGPRINT(RT_DEBUG_ERROR, ("A Only\n")); + break; + + case PHY_11ABG_MIXED: + DBGPRINT(RT_DEBUG_ERROR, ("ABG Mixed ==> BG Mixed\n")); + break; + + case PHY_11G: + DBGPRINT(RT_DEBUG_ERROR, ("G Only\n")); + break; + + case PHY_11ABGN_MIXED: + DBGPRINT(RT_DEBUG_ERROR, ("ABGN Mixed ==> BGN Mixed\n")); + break; + + case PHY_11N_2_4G: + DBGPRINT(RT_DEBUG_ERROR, ("2.4G N Only\n")); + break; + + case PHY_11GN_MIXED: + DBGPRINT(RT_DEBUG_ERROR, ("GN Mixed\n")); + break; + + case PHY_11AN_MIXED: + DBGPRINT(RT_DEBUG_ERROR, ("AN Mixed\n")); + break; + + case PHY_11BGN_MIXED: + DBGPRINT(RT_DEBUG_ERROR, ("BGN Mixed\n")); + break; + + case PHY_11AGN_MIXED: + DBGPRINT(RT_DEBUG_ERROR, ("AGN Mixed\n")); + break; + + case PHY_11N_5G: + DBGPRINT(RT_DEBUG_ERROR, ("5G N Only\n")); + break; + } /* End of switch */ + } /* End of for */ + + 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) pAd->CommonCfg.PhyMode; + wrq->u.data.length = 1; + /**(ULONG *)pData = (ULONG)pAd->CommonCfg.PhyMode; */ + 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; + +#ifdef DBG + 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 /* DBG */ + +#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: +#ifdef RTMP_RBUS_SUPPORT + RTMPIoctlGetMacTableStaInfo(pAd, wrq); +#endif /* RTMP_RBUS_SUPPORT */ + 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].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 */ + { + if (P2P_CLI_ON(pAd)) + { + pSSID->length = pAd->ApCfg.ApCliTab[pObj->ioctl_if].ApCliMlmeAux.SsidLen; + pSSID->pSsidStr = (char *)pAd->ApCfg.ApCliTab[pObj->ioctl_if].ApCliMlmeAux.Ssid; + } + else if (P2P_GO_ON(pAd)) + { + pSSID->length = pAd->ApCfg.MBSSID[pSSID->apidx].SsidLen; + pSSID->pSsidStr = (char *)pAd->ApCfg.MBSSID[pSSID->apidx].Ssid; + } + else + { + pSSID->length = 0; + pSSID->pSsidStr = NULL; + } + } + } + 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 */ +#endif /* APCLI_SUPPORT */ + WscInit(pAd, TRUE, Data); +#endif /* WSC_AP_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_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: + 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].Bssid[0]; + } + + if (pBssidStr != NULL) + { + memcpy(pBssidDest, pBssidStr, ETH_ALEN); + DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIWAP(=%02x:%02x:%02x:%02x:%02x:%02x)\n", + pBssidStr[0],pBssidStr[1],pBssidStr[2], pBssidStr[3],pBssidStr[4],pBssidStr[5])); + } + 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 MESH_SUPPORT + if (pRate->priv_flags == INT_MESH) + HtPhyMode = pAd->MeshTab.HTPhyMode; + else +#endif /* MESH_SUPPORT */ +#ifdef APCLI_SUPPORT + if (pRate->priv_flags == INT_APCLI) + HtPhyMode = pAd->ApCfg.ApCliTab[pObj->ioctl_if].HTPhyMode; + else +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (pRate->priv_flags == INT_WDS) + HtPhyMode = pAd->WdsTab.WdsEntry[pObj->ioctl_if].HTPhyMode; + else +#endif /* WDS_SUPPORT */ + { + HtPhyMode = pAd->ApCfg.MBSSID[pObj->ioctl_if].HTPhyMode; + +#ifdef MBSS_SUPPORT + /* reset phy mode for MBSS */ + MBSS_PHY_MODE_RESET(pObj->ioctl_if, HtPhyMode); +#endif /* MBSS_SUPPORT */ + } + RtmpDrvMaxRateGet(pAd, HtPhyMode.field.MODE, HtPhyMode.field.ShortGI, + HtPhyMode.field.BW, HtPhyMode.field.MCS, + (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; +} + +#ifdef P2P_SUPPORT +INT Set_P2p_OpMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT OpMode; + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return FALSE; + + OpMode = simple_strtol(arg, 0, 16); + + + if (OpMode == OPMODE_AP) + { +#ifdef DPA_S + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_SOFTAP_START, NULL, NULL, 0); +#endif /* DPA_S */ + if (P2P_CLI_ON(pAd)) + P2P_CliStop(pAd); + + if ((!P2P_GO_ON(pAd)) || (P2P_GO_ON(pAd))) + { + P2PCfgInit(pAd); + P2P_GoStartUp(pAd, MAIN_MBSSID); + } + } + else if (OpMode == OPMODE_APSTA) + { + if (P2P_GO_ON(pAd)) + P2P_GoStop(pAd); + + if ((!P2P_CLI_ON(pAd)) || (P2P_CLI_ON(pAd))) + { + P2PCfgInit(pAd); + P2P_CliStartUp(pAd); + AsicEnableBssSync(pAd); + } + } + else + { + if (P2P_CLI_ON(pAd)) + P2P_CliStop(pAd); + else if (P2P_GO_ON(pAd)) + { + P2P_GoStop(pAd); + if (INFRA_ON(pAd)) + AsicEnableBssSync(pAd); + } + P2PCfgInit(pAd); + } + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(p2p%d) Set_P2p_OpMode_Proc::(OpMode = %d)\n", pObj->ioctl_if, OpMode)); + + return TRUE; +} + +INT Set_P2pCli_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_P2P) + 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(p2p%d) Set_P2pCli_Enable_Proc::(enable = %d)\n", ifIndex, pAd->ApCfg.ApCliTab[ifIndex].Enable)); + + ApCliIfDown(pAd); + + return TRUE; +} + + +INT Set_P2pCli_Ssid_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR ifIndex; + BOOLEAN apcliEn; + INT success = FALSE; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return FALSE; + + ifIndex = pObj->ioctl_if; + + if(strlen(arg) <= MAX_LEN_OF_SSID) + { + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + + /* bring apcli interface down first */ + if(apcliEn == TRUE ) + { + pAd->ApCfg.ApCliTab[ifIndex].Enable = FALSE; + ApCliIfDown(pAd); + } + + 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); + + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscSsid.Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscSsid.Ssid, arg, strlen(arg)); + pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscSsid.SsidLength = (UCHAR)strlen(arg); + + success = TRUE; + + /* Upadte PMK and restart WPAPSK state machine for ApCli link */ + if (((pAd->ApCfg.ApCliTab[ifIndex].AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->ApCfg.ApCliTab[ifIndex].AuthMode == Ndis802_11AuthModeWPA2PSK)) && + pAd->ApCfg.ApCliTab[ifIndex].PSKLen > 0) + { + RT_CfgSetWPAPSKKey(pAd, (PSTRING)pAd->ApCfg.ApCliTab[ifIndex].PSK, pAd->ApCfg.ApCliTab[ifIndex].PSKLen, + (PUCHAR)pAd->ApCfg.ApCliTab[ifIndex].CfgSsid, + pAd->ApCfg.ApCliTab[ifIndex].CfgSsidLen, + pAd->ApCfg.ApCliTab[ifIndex].PMK); + } + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(p2p%d) Set_P2pCli_Ssid_Proc::(Len=%d,Ssid=%s)\n", ifIndex, + pAd->ApCfg.ApCliTab[ifIndex].CfgSsidLen, pAd->ApCfg.ApCliTab[ifIndex].CfgSsid)); + + pAd->ApCfg.ApCliTab[ifIndex].Enable = apcliEn; + } + else + success = FALSE; + + return success; +} + + +INT Set_P2pCli_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_P2P) + 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; + 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_P2pCli_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_P2pCli_AuthMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG i; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex; + + if (pObj->ioctl_if_type != INT_P2P) + return FALSE; + + ifIndex = pObj->ioctl_if; + + if ((strncmp(arg, "WEPAUTO", 7) == 0) || (strncmp(arg, "wepauto", 7) == 0)) + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeAutoSwitch; + else if ((strncmp(arg, "SHARED", 6) == 0) || (strncmp(arg, "shared", 6) == 0)) + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeShared; + else if ((strncmp(arg, "WPAPSK", 6) == 0) || (strncmp(arg, "wpapsk", 6) == 0)) + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeWPAPSK; + else if ((strncmp(arg, "WPA2PSK", 7) == 0) || (strncmp(arg, "wpa2psk", 7) == 0)) + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeWPA2PSK; + else + pAd->ApCfg.ApCliTab[ifIndex].AuthMode = Ndis802_11AuthModeOpen; + + 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; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_P2pCli_AuthMode_Proc::(AuthMode=%d)\n", ifIndex, pAd->ApCfg.ApCliTab[ifIndex].AuthMode)); + return TRUE; +} + + +/* + ========================================================================== + Description: + Set ApCli-IF Encryption Type + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_P2pCli_EncrypType_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex; + PAPCLI_STRUCT pApCliEntry = NULL; + + if (pObj->ioctl_if_type != INT_P2P) + return FALSE; + + ifIndex = pObj->ioctl_if; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + pApCliEntry->WepStatus = Ndis802_11WEPDisabled; + if ((strncmp(arg, "WEP", 3) == 0) || (strncmp(arg, "wep", 3) == 0)) + { + if (pApCliEntry->AuthMode < Ndis802_11AuthModeWPA) + pApCliEntry->WepStatus = Ndis802_11WEPEnabled; + } + else if ((strncmp(arg, "TKIP", 4) == 0) || (strncmp(arg, "tkip", 4) == 0)) + { + if (pApCliEntry->AuthMode >= Ndis802_11AuthModeWPA) + pApCliEntry->WepStatus = Ndis802_11Encryption2Enabled; + } + else if ((strncmp(arg, "AES", 3) == 0) || (strncmp(arg, "aes", 3) == 0)) + { + if (pApCliEntry->AuthMode >= Ndis802_11AuthModeWPA) + pApCliEntry->WepStatus = Ndis802_11Encryption3Enabled; + } + else + { + pApCliEntry->WepStatus = Ndis802_11WEPDisabled; + } + + pApCliEntry->PairCipher = pApCliEntry->WepStatus; + pApCliEntry->GroupCipher = pApCliEntry->WepStatus; + pApCliEntry->bMixCipher = FALSE; + + if (pApCliEntry->WepStatus >= Ndis802_11Encryption2Enabled) + pApCliEntry->DefaultKeyId = 1; + + RTMPMakeRSNIE(pAd, pApCliEntry->AuthMode, pApCliEntry->WepStatus, (ifIndex + MIN_NET_DEVICE_FOR_APCLI)); + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_P2pCli_EncrypType_Proc::(EncrypType=%d)\n", ifIndex, pApCliEntry->WepStatus)); + + return TRUE; +} + + + +/* + ========================================================================== + Description: + Set Default Key ID + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_P2pCli_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + ULONG KeyIdx; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex; + PAPCLI_STRUCT pApCliEntry = NULL; + + if (pObj->ioctl_if_type != INT_P2P) + return FALSE; + + ifIndex = pObj->ioctl_if; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + KeyIdx = simple_strtol(arg, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + pApCliEntry->DefaultKeyId = (UCHAR) (KeyIdx - 1 ); + else + return FALSE; /* Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_P2pCli_DefaultKeyID_Proc::(DefaultKeyID(0~3)=%d)\n", ifIndex, pApCliEntry->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_P2pCli_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_P2P) + return FALSE; + + ifIndex = pObj->ioctl_if; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(p2p%d) Set_P2pCli_WPAPSK_Proc::(WPAPSK=%s)\n", ifIndex, arg)); + + retval = RT_CfgSetWPAPSKKey(pAd, arg, strlen(arg), (PUCHAR)pApCliEntry->CfgSsid, pApCliEntry->CfgSsidLen, pApCliEntry->PMK); + if (retval == FALSE) + return FALSE; + + NdisMoveMemory(pApCliEntry->PSK, arg, strlen(arg)); + pApCliEntry->PSKLen = strlen(arg); + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set WEP KEY1 for ApCli-IF + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_P2pCli_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_P2P) + 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(p2p%d) Set_P2pCli_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_P2pCli_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_P2P) + 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(p2p%d) Set_P2pCli_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_P2pCli_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_P2P) + 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(p2p%d) Set_P2pCli_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_P2pCli_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_P2P) + 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(p2p%d) Set_P2pCli_Key4_Proc::(Key4=%s) success!\n", ifIndex, arg)); + + return retVal; +} + +INT Set_P2pCli_TxMode_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_P2P) + return FALSE; + + ifIndex = pObj->ioctl_if; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + pApCliEntry->DesiredTransmitSetting.field.FixedTxMode = + RT_CfgSetFixedTxPhyMode(arg); + DBGPRINT(RT_DEBUG_TRACE, ("I/F(p2p%d) Set_P2pCli_TxMode_Proc = %d\n", ifIndex, + pApCliEntry->DesiredTransmitSetting.field.FixedTxMode)); + + return TRUE; +} + +INT Set_P2pCli_TxMcs_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_P2P) + return FALSE; + + ifIndex = pObj->ioctl_if; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + pApCliEntry->DesiredTransmitSetting.field.MCS = + RT_CfgSetTxMCSProc(arg, &pApCliEntry->bAutoTxRateSwitch); + + if (pApCliEntry->DesiredTransmitSetting.field.MCS == MCS_AUTO) + { + DBGPRINT(RT_DEBUG_TRACE, ("I/F(p2p%d) Set_P2pCli_TxMcs_Proc = AUTO\n", ifIndex)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("I/F(p2p%d) Set_P2pCli_TxMcs_Proc = %d\n", ifIndex, + pApCliEntry->DesiredTransmitSetting.field.MCS)); + } + + return TRUE; +} + +#ifdef WSC_AP_SUPPORT +INT Set_P2pCli_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_P2P) + 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, ("I/F(p2p%d) Set_P2pCli_WscSsid_Proc:: (Select SsidLen=%d,Ssid=%s)\n", ifIndex, + pWscControl->WscSsid.SsidLength, pWscControl->WscSsid.Ssid)); + } + else + return FALSE; /* Invalid argument */ + + return TRUE; + +} +#endif /* WSC_AP_SUPPORT */ + + +INT Set_P2P_ProvAccept_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PRT_P2P_CLIENT_ENTRY pP2pEntry; + ULONG FrameLen; + UCHAR p2pindex; + UINT bAccept; + USHORT PeerWscMethod; + + bAccept = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_P2P_ProvAccept_Proc = %d\n", bAccept )); + + if ( pP2PCtrl->bProvAutoRsp == TRUE ) + { + DBGPRINT(RT_DEBUG_TRACE, ("pP2PCtrl->bProvAutoRsp == TRUE\n" )); + return TRUE; + } + + p2pindex = pP2PCtrl->P2pProvIndex; + if (p2pindex == P2P_NOT_FOUND ) + { + DBGPRINT(RT_DEBUG_TRACE, ("P2P_NOT_FOUND\n" )); + return TRUE; + } + else + pP2pEntry = &pAd->P2pTable.Client[p2pindex]; + + pP2pEntry->P2pClientState = P2PSTATE_SENT_PROVISION_RSP; + + if (bAccept) + { + /* Update My WPS Configuration. */ + P2P_SetWscRule(pAd, p2pindex, &PeerWscMethod); + /* Update Sigma.ConfigMethod after finished provision procedure. */ + P2P_SET_FLAG(&pAd->P2pTable.Client[p2pindex], P2PFLAG_PROVISIONED); + pP2pEntry->ReTransmitCnt = 0; + pP2PCtrl->P2pProvUserNotify = 1; + P2PSendProvisionRsp(pAd, pP2PCtrl->P2pProvConfigMethod, pP2PCtrl->P2pProvToken, pP2PCtrl->ConnectingMAC, &FrameLen); + if (P2P_GO_ON(pAd)) + P2pSetWps(pAd, pP2pEntry); + DBGPRINT(RT_DEBUG_ERROR, ("Accept Provision Req ==>ConfigMethod = %s \n", decodeConfigMethod(pP2PCtrl->P2pProvConfigMethod))); + + } + else + { + pP2PCtrl->P2pProvIndex = P2P_NOT_FOUND; + pP2pEntry->ReTransmitCnt = 0; + pAd->P2pCfg.P2pCounter.UserAccept = 0; + pP2PCtrl->P2pProvUserNotify = 2; + P2PSendProvisionRsp(pAd, 0, pP2PCtrl->P2pProvToken, pP2PCtrl->ConnectingMAC, &FrameLen); + } + return TRUE; +} + +#endif /* P2P_SUPPORT */ diff --git a/mt7620/src/common/p2p_ctrl.c b/mt7620/src/common/p2p_ctrl.c new file mode 100644 index 0000000..dd1cb6e --- /dev/null +++ b/mt7620/src/common/p2p_ctrl.c @@ -0,0 +1,215 @@ +/* + *************************************************************************** + * 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: + p2p_ctrl.c + + Abstract: + Peer to peer is also called Wifi Direct. P2P is a Task Group of WFA. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + +*/ +#include "rt_config.h" + +static VOID P2PCtrlDiscoveryAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID P2PCtrlDiscoveryCancelAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID P2PCtrlDiscoveryDoneAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID P2PCtrlGroupFormationAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID P2PCtrlGroupFormationDoneAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +/* + ========================================================================== + Description: + The mesh control state machine, + Parameters: + Sm - pointer to the state machine + Note: + the state machine looks like the following + ========================================================================== + */ + + #ifdef RELEAE_EXCLUDE +/* + Scan command P2P Periodic P2P Scan CntlOidScanProc MlmeCntlMachinePerformAction P2P Periodic + P2P_ENABLE_LISTEN_ONLY ---------------> P2P_IDLE -----------> P2P_SEARCH ---------> P2P_SEARCH_COMMAND ---------------> P2P_SEARCH ---------------------------> P2P_SEARCH_COMPLETE -----------> P2P_IDLE + MeshCtrlJoinAction : + . Init Bss Table + . Init Mesh Channel + . enqueue SYNC_STATE_MACHINE with MT2_MLME_SCAN_REQ + ScanNextChannel : + . scan done, enequeue MESH_CTRL_STATE_MACHINE with APMT2_MLME_SCAN_FINISH + + P2PCtrlJoinAction + . Init P2P Table + . Init random timer + . enqueeue SYNC_STATE_MACHINE with MT2_MLME_SCAN_REQ + ScanNextChannel : + . scan done, enequeue P2P_CTRL_STATE_MACHINE with P2P_SCAN_FINISH + P2PCtrlFinishDiscoveryAction : + . Init ScanNextRound + . change in P2P_IDLE +*/ + +/* + + P2P_CTRL_IDLE : do not scan / search / listen. + p2p interface up then in IDLE state, or after change as P2P Client / P2P GO in IDLE state. + P2P_CTRL_DISCOVERY : do scan / search / listen in an period. + Use P2PDiscMachine do such things and after times up, P2PDiscMachine and P2PCtrlMachine in IDLE state. + If we have Device Name / Device Address and WSC config method, P2PPeriodicExec should MlmeEnqueue + P2P_CTRL_GROUP_FORMATION in P2PCtrlMachine. + P2P_CTRL_GROUP_FORMATION : do Group Negotiation and Provision. + Use P2PGoFormMachine do such things in ConfigTimeout periodic. + P2P_CTRL_DONE : Group Formation has finish , interface will up as AP or STA code. + After AsicKey write done, can change to IDLE state. + +*/ +#endif /* RELEASE_EXCLUDE */ + +VOID P2PCtrlStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, (ULONG)P2P_CTRL_MAX_STATES, + (ULONG)P2P_CTRL_MAX_EVENTS, (STATE_MACHINE_FUNC)Drop, P2P_CTRL_IDLE, P2P_CTRL_IDLE); + + /* P2P_CTRL_IDLE state */ + StateMachineSetAction(Sm, P2P_CTRL_IDLE, P2P_CTRL_DISC_EVT, (STATE_MACHINE_FUNC)P2PCtrlDiscoveryAction); + StateMachineSetAction(Sm, P2P_CTRL_IDLE, P2P_CTRL_GO_NEGO_EVT, (STATE_MACHINE_FUNC)P2PCtrlGroupFormationAction); + + /* P2P_CTRL_DISCOVERY state */ + StateMachineSetAction(Sm, P2P_CTRL_DISCOVERY, P2P_CTRL_DISC_EVT, (STATE_MACHINE_FUNC)P2PCtrlDiscoveryAction); + StateMachineSetAction(Sm, P2P_CTRL_DISCOVERY, P2P_CTRL_DISC_CANL_EVT, (STATE_MACHINE_FUNC)P2PCtrlDiscoveryCancelAction); + StateMachineSetAction(Sm, P2P_CTRL_DISCOVERY, P2P_CTRL_DISC_DONE_EVT, (STATE_MACHINE_FUNC)P2PCtrlDiscoveryDoneAction); + StateMachineSetAction(Sm, P2P_CTRL_DISCOVERY, P2P_CTRL_GO_NEGO_EVT, (STATE_MACHINE_FUNC)P2PCtrlGroupFormationAction); + + /* P2P_CTRL_GROUP_FORMATION state */ + StateMachineSetAction(Sm, P2P_CTRL_GROUP_FORMATION, P2P_CTRL_GO_NEGO_EVT, (STATE_MACHINE_FUNC)P2PCtrlGroupFormationAction); + StateMachineSetAction(Sm, P2P_CTRL_GROUP_FORMATION, P2P_CTRL_GO_NEGO_CANL_EVT, (STATE_MACHINE_FUNC)P2PCtrlGroupFormationDoneAction); + StateMachineSetAction(Sm, P2P_CTRL_GROUP_FORMATION, P2P_CTRL_DISC_CANL_EVT, (STATE_MACHINE_FUNC)P2PCtrlDiscoveryDoneAction); + StateMachineSetAction(Sm, P2P_CTRL_GROUP_FORMATION, P2P_CTRL_GO_NEGO_DONE_EVT, (STATE_MACHINE_FUNC)P2PCtrlGroupFormationDoneAction); + StateMachineSetAction(Sm, P2P_CTRL_GROUP_FORMATION, P2P_CTRL_DISC_EVT, (STATE_MACHINE_FUNC)P2PCtrlDiscoveryAction); + + /* P2P_CTRL_DONE state */ + /*StateMachineSetAction(Sm, P2P_CTRL_DONE, Event, (STATE_MACHINE_FUNC)Action); */ + + /* init all P2P ctrl state. */ + pAd->P2pCfg.CtrlCurrentState = P2P_CTRL_IDLE; + + return; +} + +/* Ctrl Action */ +static VOID P2PCtrlDiscoveryAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + P2P_CTRL_STATE *pCurrState = &(pAd->P2pCfg.CtrlCurrentState); + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: \n", __FUNCTION__)); + + if (P2P_GO_ON(pAd)) + MlmeEnqueue(pAd, P2P_DISC_STATE_MACHINE, P2P_DISC_LISTEN_CMD_EVT, 0, NULL, 0); + else + MlmeEnqueue(pAd, P2P_DISC_STATE_MACHINE, P2P_DISC_SCAN_CMD_EVT, 0, NULL, 0); + + *pCurrState = P2P_CTRL_DISCOVERY; +} + +static VOID P2PCtrlDiscoveryCancelAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + P2P_CTRL_STATE *pCurrState = &(pAd->P2pCfg.CtrlCurrentState); + + DBGPRINT(RT_DEBUG_TRACE, ("%s::\n", __FUNCTION__)); + /* update Discovery State Machine state. */ + MlmeEnqueue(pAd, P2P_DISC_STATE_MACHINE, P2P_DISC_CANL_CMD_EVT, 0, NULL, 0); + MlmeHandler(pAd); + + *pCurrState = P2P_CTRL_IDLE; +} + +static VOID P2PCtrlDiscoveryDoneAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + /*PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg;*/ + P2P_CTRL_STATE *pCurrState = &(pAd->P2pCfg.CtrlCurrentState); + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: P2P Device Discovery Finished, found total %d p2p devices.\n", __FUNCTION__, pAd->P2pTable.ClientNumber)); + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + BOOLEAN bCancelled; + /* Stop Scan and resume */ + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &bCancelled); + pAd->MlmeAux.Channel = 0; + ScanNextChannel(pAd, OPMODE_STA); + } + + P2PInitDevDiscTimer(pAd, 0); + P2PInitListenTimer(pAd, 0); + P2PInitNextScanTimer(pAd, 0); + /* update Discovery State Machine state. */ + MlmeEnqueue(pAd, P2P_DISC_STATE_MACHINE, P2P_DISC_CANL_CMD_EVT, 0, NULL, 0); + *pCurrState = P2P_CTRL_IDLE; +} + +static VOID P2PCtrlGroupFormationAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + P2P_CTRL_STATE *pCurrState = &(pAd->P2pCfg.CtrlCurrentState); + + DBGPRINT(RT_DEBUG_TRACE, ("%s::\n", __FUNCTION__)); + *pCurrState = P2P_CTRL_GROUP_FORMATION; +} + +static VOID P2PCtrlGroupFormationDoneAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + /*PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg;*/ + P2P_CTRL_STATE *pCurrState = &(pAd->P2pCfg.CtrlCurrentState); + + DBGPRINT(RT_DEBUG_ERROR, ("%s::\n", __FUNCTION__)); + /*pAd->StaCfg.bAutoReconnect = TRUE;*/ + DBGPRINT(RT_DEBUG_ERROR, ("auto re-conect to GO[%s]\n", pAd->MlmeAux.Ssid)); + + *pCurrState = P2P_CTRL_DONE; +} + + diff --git a/mt7620/src/common/p2p_dbg.c b/mt7620/src/common/p2p_dbg.c new file mode 100644 index 0000000..8510ca9 --- /dev/null +++ b/mt7620/src/common/p2p_dbg.c @@ -0,0 +1,1265 @@ +#ifdef P2P_SUPPORT + + +#include "rt_config.h" + +extern UCHAR WILDP2PSSID[]; +extern UCHAR WILDP2PSSIDLEN; + +extern INT Set_AP_WscPinCode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Print_Cfg( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + if (P2P_INF_ON(pAd)) + { + DBGPRINT(RT_DEBUG_ERROR, ("P2P Device Config :\n")); + DBGPRINT(RT_DEBUG_ERROR, ("=====================================================================\n")); + DBGPRINT(RT_DEBUG_ERROR,("Device Name[%ld] = %s.\n", pP2PCtrl->DeviceNameLen, pP2PCtrl->DeviceName)); + DBGPRINT(RT_DEBUG_ERROR,("Device Addr = %02x:%02x:%02x:%02x:%02x:%02x.\n", PRINT_MAC(pP2PCtrl->CurrentAddress))); + DBGPRINT(RT_DEBUG_ERROR, ("OpChannel = %d. Listen Channel = %d. \n", pP2PCtrl->GroupChannel, pP2PCtrl->ListenChannel)); + DBGPRINT(RT_DEBUG_ERROR, ("My Go Intent = %d.\n", pP2PCtrl->GoIntentIdx)); + /*DBGPRINT(RT_DEBUG_ERROR, ("WscMode = %s. ConfigMethod = %s.\n", (pP2PCtrl->WscMode == 1) ? "PIN" : "PBC", decodeConfigMethod(pP2PCtrl->ConfigMethod))); */ + if (pP2PCtrl->WscMode == 1) + DBGPRINT(RT_DEBUG_ERROR, ("WscMode = PIN.\n")); + else if (pP2PCtrl->WscMode == 2) + DBGPRINT(RT_DEBUG_ERROR, ("WscMode = PBC.\n")); + else + DBGPRINT(RT_DEBUG_ERROR, ("WscMode = ***Unknown***.\n")); + + DBGPRINT(RT_DEBUG_ERROR, ("WscConfigMethod = %s.\n", decodeConfigMethod(pP2PCtrl->ConfigMethod))); + DBGPRINT(RT_DEBUG_ERROR, ("WscDpid = %s.\n", decodeDpid(pP2PCtrl->Dpid))); + if (pP2PCtrl->ConfigMethod == WSC_CONFMET_DISPLAY) + DBGPRINT(RT_DEBUG_ERROR, ("My Self PIN Code = %08u\n", pAd->ApCfg.ApCliTab[0].WscControl.WscEnrolleePinCode)); + else if (pP2PCtrl->ConfigMethod == WSC_CONFMET_KEYPAD) + { + UINT PinCode = simple_strtol(pP2PCtrl->PinCode, 0, 10); + DBGPRINT(RT_DEBUG_ERROR, ("Peer PIN Code = %08u\n", PinCode)); + } + + DBGPRINT(RT_DEBUG_ERROR, ("SSID[%d] = %s.\n", pP2PCtrl->SSIDLen, pP2PCtrl->SSID)); + DBGPRINT(RT_DEBUG_ERROR, ("NoA_Count = %d. NoA_Duration = %ld. NoA_Interval = %ld. StartTime = %ld.\n", + pP2PCtrl->GONoASchedule.Count, pP2PCtrl->GONoASchedule.Duration, pP2PCtrl->GONoASchedule.Interval, pP2PCtrl->GONoASchedule.StartTime)); + DBGPRINT(RT_DEBUG_INFO, ("ExtListenPeriod = %d. ExtListenInterval = %d.\n", pP2PCtrl->ExtListenPeriod, pP2PCtrl->ExtListenInterval)); + DBGPRINT(RT_DEBUG_INFO, ("Intra-Bss = %d. \n", pP2PCtrl->bIntraBss)); + DBGPRINT(RT_DEBUG_ERROR, ("ConenctMAC = %02x:%02x:%02x:%02x:%02x:%02x.\n", PRINT_MAC(pP2PCtrl->ConnectingMAC))); + DBGPRINT(RT_DEBUG_ERROR, ("p2pControl = %u8. Persistent = %s. Invite = %s. ClientDiscovery = %s. IntraBss = %s. ExtListen = %s.\n", pP2PCtrl->P2pControl.word, (IS_PERSISTENT_ON(pAd))? "ON" : "OFF", (IS_INVITE_ON(pAd))? "ON" : "OFF", + (IS_CLIENT_DISCOVERY_ON(pAd))? "ON" : "OFF", (IS_INTRA_BSS_ON(pAd))? "ON" : "OFF", (IS_EXT_LISTEN_ON(pAd))? "ON" : "OFF")); + DBGPRINT(RT_DEBUG_ERROR, (" Opps = %s. SwNoATimer = %s.\n", (IS_OPPS_ON(pAd))? "ON" : "OFF", (IS_SW_NOA_TIMER(pAd))? "ON" : "OFF")); + + } + + return TRUE; +} + +INT Set_P2P_Enable( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UINT32 enable = 0; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + enable = (UCHAR) simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_ERROR, ("%s:: P2P Enable = %d.\n", __FUNCTION__, enable)); + return TRUE; +} + +INT Set_P2P_Listen_Channel( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UINT32 channel; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + channel = (UCHAR) simple_strtol(arg, 0, 10); + /* check if this channel is valid */ + if (ChannelSanity(pAd, channel) == TRUE) + { + pAd->P2pCfg.ListenChannel = channel; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Listen Channel out of range, using default.\n")); + pAd->P2pCfg.ListenChannel = 1; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: Listen Channel = %d.\n", __FUNCTION__, pAd->P2pCfg.ListenChannel)); + return TRUE; +} + +INT Set_P2P_Operation_Channel( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UINT32 channel; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + channel = (UCHAR) simple_strtol(arg, 0, 10); + /* check if this channel is valid */ + if (ChannelSanity(pAd, channel) == TRUE) + { + pAd->P2pCfg.GroupChannel = channel; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Opertation Channel out of range, using default.\n")); + pAd->P2pCfg.GroupChannel = 1; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: Op Channel = %d.\n", __FUNCTION__, pAd->P2pCfg.GroupChannel)); + return TRUE; +} + + +INT Set_P2P_GO_Intent( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UINT32 intent; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + intent = simple_strtol(arg, 0, 10); + if (intent <= 15) + pAd->P2pCfg.GoIntentIdx = intent; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("GO Intent out of range 0 ~ 15, using default.\n")); + pAd->P2pCfg.GoIntentIdx = 0; + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: GO Intent = %d.\n", __FUNCTION__, pAd->P2pCfg.GoIntentIdx)); + return TRUE; +} + + +INT Set_P2P_Device_Name( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + if (strlen(arg) <= 32) + { + pAd->P2pCfg.DeviceNameLen = (UCHAR) strlen(arg); + NdisZeroMemory(pAd->P2pCfg.DeviceName, 32); + NdisMoveMemory(pAd->P2pCfg.DeviceName, arg, pAd->P2pCfg.DeviceNameLen); + DBGPRINT(RT_DEBUG_ERROR, ("Set P2P Device Name - %s", pAd->P2pCfg.DeviceName)); + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Device Name = %s.\n", __FUNCTION__, pAd->P2pCfg.DeviceName)); + return TRUE; +} + +INT Set_P2P_WSC_Mode( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + int wscMode; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + wscMode = simple_strtol(arg, 0, 10); + if (wscMode <= 2 && wscMode >= 1) + pAd->P2pCfg.WscMode= wscMode; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("WscMode is invalid, using default and accept wsc method from peer's provision request action frame.\n")); + pAd->P2pCfg.WscMode = WSC_PIN_MODE; /* PIN */ + pAd->P2pCfg.Dpid = DEV_PASS_ID_NOSPEC; + pAd->P2pCfg.ConfigMethod = (WSC_CONFMET_PBC | WSC_CONFMET_KEYPAD | WSC_CONFMET_DISPLAY); + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: WscMode = %s.\n", __FUNCTION__, (wscMode == 1) ? "PIN" : "PBC")); + return TRUE; +} + +INT Set_P2P_WSC_ConfMethod( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + int method; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + method = simple_strtol(arg, 0, 10); + + if (pAd->P2pCfg.WscMode == WSC_PIN_MODE) + { + if (method == 1) + { + /* Display PIN */ + pAd->P2pCfg.Dpid = DEV_PASS_ID_REG; + pAd->P2pCfg.ConfigMethod = WSC_CONFMET_DISPLAY; + DBGPRINT(RT_DEBUG_TRACE, (" *************************************************\n")); + DBGPRINT(RT_DEBUG_TRACE, (" * *\n")); + DBGPRINT(RT_DEBUG_TRACE, (" * PIN Code = %08u *\n", pAd->ApCfg.ApCliTab[0].WscControl.WscEnrolleePinCode)); + DBGPRINT(RT_DEBUG_TRACE, (" * *\n")); + DBGPRINT(RT_DEBUG_TRACE, (" *************************************************\n")); + + } + else if (method == 2) + { + /* Enter PIN */ + pAd->P2pCfg.Dpid = DEV_PASS_ID_USER; + pAd->P2pCfg.ConfigMethod = WSC_CONFMET_KEYPAD; + } + } + else if (pAd->P2pCfg.WscMode == WSC_PBC_MODE) + { + if (method == 3) + { + pAd->P2pCfg.Dpid = DEV_PASS_ID_PBC; + pAd->P2pCfg.ConfigMethod = WSC_CONFMET_PBC; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: Config Method = %s.\n", __FUNCTION__, decodeConfigMethod(pAd->P2pCfg.ConfigMethod))); + return TRUE; +} + +INT Set_P2P_NoA_Count( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + pAd->P2pCfg.GONoASchedule.Count = simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s:: NoA Count = %d\n", __FUNCTION__, pAd->P2pCfg.GONoASchedule.Count)); + return TRUE; +} + +INT Set_P2P_NoA_Duration( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + pAd->P2pCfg.GONoASchedule.Duration = simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s:: NoA Duration = %ld\n", __FUNCTION__, pAd->P2pCfg.GONoASchedule.Duration)); + return TRUE; +} + +INT Set_P2P_NoA_Interval( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + pAd->P2pCfg.GONoASchedule.Interval = simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s:: NoA Interval = %ld\n", __FUNCTION__, pAd->P2pCfg.GONoASchedule.Interval)); + return TRUE; +} + +INT Set_P2P_Extend_Listen( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR ExtListen; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + ExtListen = simple_strtol(arg, 0, 10); + if (ExtListen) + pAd->P2pCfg.bExtListen = TRUE; + else + pAd->P2pCfg.bExtListen = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("%s:: Exted Listen = %d\n", __FUNCTION__, pAd->P2pCfg.bExtListen)); + return TRUE; +} + +INT Set_P2P_Extend_Listen_Periodic( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + pAd->P2pCfg.ExtListenPeriod = simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s:: Extend Listen Interval = %d\n", __FUNCTION__, pAd->P2pCfg.ExtListenPeriod)); + return TRUE; +} + +INT Set_P2P_Extend_Listen_Interval( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + pAd->P2pCfg.ExtListenInterval = simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s:: Extend Listen Interval = %d\n", __FUNCTION__, pAd->P2pCfg.ExtListenInterval)); + return TRUE; +} + +INT Set_P2P_Intra_Bss( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR IntraBss; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + IntraBss = simple_strtol(arg, 0, 10); + if (IntraBss) + pAd->P2pCfg.bIntraBss = TRUE; + else + pAd->P2pCfg.bIntraBss = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("%s:: IntraBss = %d\n", __FUNCTION__, pAd->P2pCfg.bIntraBss)); + return TRUE; +} + +INT Set_P2P_Scan( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + int bScan; + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + bScan = simple_strtol(arg, 0, 10); + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + + if (bScan) + { + pAd->StaCfg.bAutoReconnect = FALSE; + pP2PCtrl->bSentProbeRSP = TRUE; + P2pGroupTabInit(pAd); + P2pScan(pAd); + } + else + { +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + pAd->StaCfg.bAutoReconnect = FALSE; +#else + pAd->StaCfg.bAutoReconnect = TRUE; +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + pP2PCtrl->bSentProbeRSP = FALSE; + P2pStopScan(pAd); + } + return TRUE; +} + +INT Set_P2P_Print_GroupTable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + int i, j; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + RTMP_SEM_LOCK(&pAd->P2pTableSemLock); + DBGPRINT(RT_DEBUG_ERROR, ("%s:: P2pTable ClientNum = %d\n", __FUNCTION__, pAd->P2pTable.ClientNumber)); + for (i=0; i < pAd->P2pTable.ClientNumber; i++) + { + PRT_P2P_CLIENT_ENTRY pP2pEntry = &pAd->P2pTable.Client[i]; + DBGPRINT(RT_DEBUG_ERROR, ("Table.Client[%d]: DeviceName[%d][%s]\n", i, pP2pEntry->DeviceNameLen, pP2pEntry->DeviceName)); + DBGPRINT(RT_DEBUG_ERROR, (" Addr[%02x:%02x:%02x:%02x:%02x:%02x]\n", PRINT_MAC(pP2pEntry->addr))); + DBGPRINT(RT_DEBUG_ERROR, (" BSSID[%02x:%02x:%02x:%02x:%02x:%02x]\n", PRINT_MAC(pP2pEntry->bssid))); + DBGPRINT(RT_DEBUG_ERROR, (" InterfaceAddr[%02x:%02x:%02x:%02x:%02x:%02x]\n", PRINT_MAC(pP2pEntry->InterfaceAddr))); + DBGPRINT(RT_DEBUG_ERROR, (" SSID[")); + for (j=0; jSsidLen;j++) + DBGPRINT(RT_DEBUG_ERROR, ("%c ", pP2pEntry->Ssid[j])); + DBGPRINT(RT_DEBUG_ERROR, ("]\n")); + DBGPRINT(RT_DEBUG_ERROR, (" OpChannel = %d. ListenChannel = %d.\n", pP2pEntry->OpChannel, pP2pEntry->ListenChannel)); + DBGPRINT(RT_DEBUG_ERROR, (" P2pClientState = %s. MyGOIndex = %d.\n", decodeP2PClientState(pP2pEntry->P2pClientState), pP2pEntry->MyGOIndex)); + DBGPRINT(RT_DEBUG_ERROR, (" Dpid = %s. Rule = %s.\n", decodeDpid(pP2pEntry->Dpid), decodeMyRule(pP2pEntry->Rule))); + + if (pP2pEntry->WscMode == 1) + DBGPRINT(RT_DEBUG_ERROR, (" WscMode = PIN. PIN = %02x %02x %02x %02x %02x %02x %02x %02x.\n", + pP2pEntry->PIN[0], pP2pEntry->PIN[1], pP2pEntry->PIN[2], pP2pEntry->PIN[3], + pP2pEntry->PIN[4], pP2pEntry->PIN[5], pP2pEntry->PIN[6], pP2pEntry->PIN[7])); + else if (pAd->P2pTable.Client[i].WscMode == 2) + DBGPRINT(RT_DEBUG_ERROR, (" WscMode = PBC.\n")); + else + DBGPRINT(RT_DEBUG_ERROR, (" WscMode = ***Unknown***.\n")); + DBGPRINT(RT_DEBUG_ERROR, (" CfgMethod = %s. GoIntent = %d.\n", decodeConfigMethod(pAd->P2pTable.Client[i].ConfigMethod), pAd->P2pTable.Client[i].GoIntent)); + decodeDeviceCap(pP2pEntry->DevCapability); + decodeGroupCap(pP2pEntry->GroupCapability); + DBGPRINT(RT_DEBUG_ERROR, (" Rssi = %d.\n", pP2pEntry->Rssi)); + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + } + + RTMP_SEM_UNLOCK(&pAd->P2pTableSemLock); + return TRUE; +} + +INT Set_P2P_Print_PersistentTable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + int i; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: P2pTable ClientNum = %d\n", __FUNCTION__, pAd->P2pTable.PerstNumber)); + for (i=0; i < pAd->P2pTable.PerstNumber; i++) + { + DBGPRINT(RT_DEBUG_ERROR, ("Table.PerstEntry[%d]: Rule = %s\n", i, decodeMyRule(pAd->P2pTable.PerstEntry[i].MyRule))); + DBGPRINT(RT_DEBUG_ERROR, (" DevAddr = %02x:%02x:%02x:%02x:%02x:%02x.\n", PRINT_MAC(pAd->P2pTable.PerstEntry[i].Addr))); + DBGPRINT(RT_DEBUG_ERROR, (" SSID[%d] = %s.\n", pAd->P2pTable.PerstEntry[i].Profile.SSID.SsidLength, pAd->P2pTable.PerstEntry[i].Profile.SSID.Ssid)); + DBGPRINT(RT_DEBUG_ERROR, (" MACAddr = %02x:%02x:%02x:%02x:%02x:%02x.\n", PRINT_MAC(pAd->P2pTable.PerstEntry[i].Profile.MacAddr))); + DBGPRINT(RT_DEBUG_ERROR, (" Key[%d] = %02x %02x %02x %02x %02x %02x %02x %02x.\n", pAd->P2pTable.PerstEntry[i].Profile.KeyIndex, pAd->P2pTable.PerstEntry[i].Profile.Key[0], pAd->P2pTable.PerstEntry[i].Profile.Key[1], + pAd->P2pTable.PerstEntry[i].Profile.Key[2], pAd->P2pTable.PerstEntry[i].Profile.Key[3], pAd->P2pTable.PerstEntry[i].Profile.Key[4], pAd->P2pTable.PerstEntry[i].Profile.Key[5], + pAd->P2pTable.PerstEntry[i].Profile.Key[6], pAd->P2pTable.PerstEntry[i].Profile.Key[7])); + DBGPRINT(RT_DEBUG_ERROR, (" %02x %02x %02x %02x %02x %02x %02x %02x.\n", pAd->P2pTable.PerstEntry[i].Profile.Key[8], pAd->P2pTable.PerstEntry[i].Profile.Key[9], + pAd->P2pTable.PerstEntry[i].Profile.Key[10], pAd->P2pTable.PerstEntry[i].Profile.Key[11], pAd->P2pTable.PerstEntry[i].Profile.Key[12], pAd->P2pTable.PerstEntry[i].Profile.Key[13], + pAd->P2pTable.PerstEntry[i].Profile.Key[14], pAd->P2pTable.PerstEntry[i].Profile.Key[15])); + } + return TRUE; +} + +INT Set_P2P_Provision_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR p2pindex; + PUCHAR pAddr; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + p2pindex = simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_ERROR, ("%s: TabIdx[%d]\n", __FUNCTION__, p2pindex)); + if (p2pindex < pAd->P2pTable.ClientNumber) + { +/* P2PPrintP2PEntry(pAd, P2pTabIdx); */ + pAddr = &pAd->P2pTable.Client[p2pindex].addr[0]; +/* pAd->P2pTable.Client[P2pTabIdx].StateCount = 10; */ +/* pAd->P2pTable.Client[P2pTabIdx].bValid = TRUE; */ +/* P2pProvision(pAd, pAddr); */ + P2pConnectPrepare(pAd, pAddr, P2PSTATE_PROVISION_COMMAND); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("Table Idx out of range!\n")); + + return TRUE; + +} + +INT Set_P2P_Invite_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR p2pindex; + PUCHAR pAddr; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + p2pindex = simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_ERROR, ("%s:: TabIdx[%d]\n", __FUNCTION__, p2pindex)); + + if (p2pindex < pAd->P2pTable.ClientNumber) + { + pAddr = &pAd->P2pTable.Client[p2pindex].addr[0]; + P2pConnectPrepare(pAd, pAddr, P2PSTATE_INVITE_COMMAND); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("Table Idx out of range!\n")); + + return TRUE; +} + +INT Set_P2P_Device_Discoverability_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR p2pindex; + UCHAR MyGOIdx; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + p2pindex = simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_ERROR, ("%s:: TabIdx[%d]\n", __FUNCTION__, p2pindex)); + P2PPrintP2PEntry(pAd, p2pindex); + if (p2pindex < MAX_P2P_GROUP_SIZE) + { + MyGOIdx = pAd->P2pTable.Client[p2pindex].MyGOIndex; + if (MyGOIdx != P2P_NOT_FOUND) + { + DBGPRINT(RT_DEBUG_TRACE, ("Start P2P Device Discoverability = %02x:%02x:%02x:%02x:%02x:%02x. \n", PRINT_MAC(pAd->P2pTable.Client[p2pindex].addr))); + pAd->P2pTable.Client[p2pindex].GeneralToken++; + pAd->P2pTable.Client[MyGOIdx].P2pClientState = P2PSTATE_GO_DISCO_COMMAND; + pAd->P2pTable.Client[p2pindex].P2pClientState = P2PSTATE_CLIENT_DISCO_COMMAND; + P2pSetListenIntBias(pAd, 12); + } + } + else + DBGPRINT(RT_DEBUG_ERROR, ("Table Idx out of range!\n")); + + return TRUE; +} + +INT Set_P2P_Connect_GoIndex_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR p2pindex; + PUCHAR pAddr; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + p2pindex = simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_ERROR, ("%s:: TabIdx[%d]\n", __FUNCTION__, p2pindex)); + + + if (p2pindex < pAd->P2pTable.ClientNumber) + { + /* + P2PPrintP2PEntry(pAd, P2pTabIdx); + pAd->P2pCfg.ConnectingIndex = 0; + if (pAd->P2pTable.Client[P2pTabIdx].P2pClientState == P2PSTATE_DISCOVERY) + pAd->P2pTable.Client[P2pTabIdx].P2pClientState = P2PSTATE_CONNECT_COMMAND; + COPY_MAC_ADDR(pAd->P2pCfg.ConnectingMAC, pAd->P2pTable.Client[P2pTabIdx].addr); + pAd->P2pTable.Client[P2pTabIdx].StateCount = 10; + pAd->P2pTable.Client[P2pTabIdx].bValid = TRUE; + P2pConnect(pAd); + */ + pAddr = &pAd->P2pTable.Client[p2pindex].addr[0]; + P2pConnectPrepare(pAd, pAddr, P2PSTATE_CONNECT_COMMAND); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("Table Idx out of range!\n")); + + return TRUE; +} + + +INT Set_P2P_Connect_Dev_Addr_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR p2pindex = P2P_NOT_FOUND; + PUCHAR pAddr; + UCHAR ConnAddr[6]; + UINT32 i; + extern UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN]; + extern UCHAR BROADCAST_ADDR[MAC_ADDR_LEN]; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Connect to DevAddr[%s]\n", __FUNCTION__, arg)); + + + /* + 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. + */ + + NdisMoveMemory(&ConnAddr[0], &ZERO_MAC_ADDR[0], MAC_ADDR_LEN); + if (rtstrmactohex(arg, (PSTRING) &ConnAddr[0]) == FALSE) + return FALSE; + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: DevMac = %02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, PRINT_MAC(ConnAddr))); + + if (MAC_ADDR_EQUAL(ConnAddr, ZERO_MAC_ADDR)) + { + P2pLinkDown(pAd, P2P_CONNECT_FAIL); + return TRUE; + } + + for (i=0; i < pAd->P2pTable.ClientNumber; i++) + { + if (MAC_ADDR_EQUAL(pAd->P2pTable.Client[i].addr, ConnAddr) || + MAC_ADDR_EQUAL(pAd->P2pTable.Client[i].bssid, ConnAddr) || + MAC_ADDR_EQUAL(pAd->P2pTable.Client[i].InterfaceAddr, ConnAddr)) + { + p2pindex = i; + break; + } + } + + if ((p2pindex < pAd->P2pTable.ClientNumber) && (p2pindex != P2P_NOT_FOUND)) + { + pAddr = &pAd->P2pTable.Client[p2pindex].addr[0]; + P2pConnectPrepare(pAd, pAddr, P2PSTATE_CONNECT_COMMAND); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("Table Idx out of range!\n")); + + return TRUE; +} + +INT Set_P2P_Provision_Dev_Addr_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR p2pindex = P2P_NOT_FOUND; + PUCHAR pAddr; + UCHAR ConnAddr[6]; + UINT32 i; + UINT16 retry_cnt = 0; + extern UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN]; + extern UCHAR BROADCAST_ADDR[MAC_ADDR_LEN]; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Connect to DevAddr[%s]\n", __FUNCTION__, arg)); + + + /* + 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. + */ + + if( pAd->P2pTable.ClientNumber == 0) + { + DBGPRINT( RT_DEBUG_ERROR, ("P2P Table is Empty! Scan First!\n")); + P2pScan(pAd); + OS_WAIT(2000); + } + + NdisMoveMemory(&ConnAddr[0], &ZERO_MAC_ADDR[0], MAC_ADDR_LEN); + if (rtstrmactohex(arg, (PSTRING) &ConnAddr[0]) == FALSE) + return FALSE; + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: DevMac = %02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, PRINT_MAC(ConnAddr))); + + if (MAC_ADDR_EQUAL(ConnAddr, ZERO_MAC_ADDR)) + { + P2pLinkDown(pAd, P2P_CONNECT_FAIL); + return TRUE; + } + +retry: + + for (i=0; i < pAd->P2pTable.ClientNumber; i++) + { + if (MAC_ADDR_EQUAL(pAd->P2pTable.Client[i].addr, ConnAddr) || + MAC_ADDR_EQUAL(pAd->P2pTable.Client[i].bssid, ConnAddr) || + MAC_ADDR_EQUAL(pAd->P2pTable.Client[i].InterfaceAddr, ConnAddr)) + { + p2pindex = i; + break; + } + } + + DBGPRINT(RT_DEBUG_TRACE,("pAd->P2pTable.ClientNumber = %d, p2pindex = %d\n", pAd->P2pTable.ClientNumber, p2pindex)); + if ((p2pindex < pAd->P2pTable.ClientNumber) && (p2pindex != P2P_NOT_FOUND)) + { + pAddr = &pAd->P2pTable.Client[p2pindex].addr[0]; + P2pConnectPrepare(pAd, pAddr, P2PSTATE_PROVISION_COMMAND); + } + else + { + retry_cnt ++; + if ( retry_cnt < 5 ) + { + OS_WAIT(2000); + goto retry; + } + DBGPRINT(RT_DEBUG_ERROR, ("Table Idx out of range!\n")); +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT + P2pSendWirelessEvent(pAd, RT_P2P_CONNECT_FAIL, NULL, NULL); +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ + } + + return TRUE; +} + +INT Set_P2P_State_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + DBGPRINT(RT_DEBUG_ERROR, ("P2P Current State\n")); + DBGPRINT(RT_DEBUG_ERROR, ("=====================================================================\n")); + DBGPRINT(RT_DEBUG_ERROR, ("My Rule = %s\n", decodeMyRule(pP2PCtrl->Rule))); + DBGPRINT(RT_DEBUG_ERROR, ("p2p_OpStatus = %04x\n", pAd->flg_p2p_OpStatusFlags)); + DBGPRINT(RT_DEBUG_ERROR, ("CTRL Machine State = %s.\n", decodeCtrlState(pP2PCtrl->CtrlCurrentState))); + DBGPRINT(RT_DEBUG_ERROR, ("DISC Machine State = %s.\n", decodeDiscoveryState(pP2PCtrl->DiscCurrentState))); + DBGPRINT(RT_DEBUG_ERROR, ("GO_FORM Machine State = %s.\n", decodeGroupFormationState(pP2PCtrl->GoFormCurrentState))); + DBGPRINT(RT_DEBUG_ERROR, ("AutoReconn = %d\n", pAd->StaCfg.bAutoReconnect)); + /*DBGPRINT(RT_DEBUG_ERROR, ("P2PDiscoProvState = %s\n", decodeP2PState(pP2PCtrl->P2PDiscoProvState))); */ + DBGPRINT(RT_DEBUG_ERROR, ("P2PConnectState = %s\n", decodeP2PState(pP2PCtrl->P2PConnectState))); + + return TRUE; +} + +INT Set_P2P_Reset_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + /*UINT32 DiscPerd = 0;*/ + POS_COOKIE pObj; + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + if (P2P_CLI_ON(pAd)) + P2P_CliStop(pAd); + else if (P2P_GO_ON(pAd)) + { + P2P_GoStop(pAd); + if (INFRA_ON(pAd)) + AsicEnableBssSync(pAd); + } + P2PCfgInit(pAd); + P2pGroupTabInit(pAd); + pP2PCtrl->Rule = P2P_IS_DEVICE; + pAd->flg_p2p_OpStatusFlags = P2P_DISABLE; + pP2PCtrl->ConfigMethod = 0x188; + pAd->ApCfg.MBSSID[MAIN_MBSSID].WscControl.WscConfStatus = WSC_SCSTATE_UNCONFIGURED; + pP2PCtrl->GoFormCurrentState = P2P_GO_FORM_IDLE; + pP2PCtrl->DiscCurrentState = P2P_DISC_IDLE; + pP2PCtrl->CtrlCurrentState = P2P_CTRL_IDLE; + NdisZeroMemory(&pP2PCtrl->P2pCounter, sizeof(P2P_COUNTER_STRUCT)); + P2pSetListenIntBias(pAd, 3); + RTMPZeroMemory(pAd->P2pCfg.SSID, MAX_LEN_OF_SSID); + RTMPMoveMemory(pAd->P2pCfg.SSID, WILDP2PSSID, WILDP2PSSIDLEN); + pP2PCtrl->SSIDLen = WILDP2PSSIDLEN; + /* Set Dpid to "not specified". it means, GUI doesn't set for connection yet. */ + pP2PCtrl->Dpid = DEV_PASS_ID_NOSPEC; + RTMPZeroMemory(pAd->P2pCfg.ConnectingMAC, MAC_ADDR_LEN); + return TRUE; +} + +INT Set_P2P_Default_Config_Method_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) + +{ + UINT32 ConfigMethod = 0; + POS_COOKIE pObj; + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + ConfigMethod = simple_strtol(arg, 0, 10); + if ((ConfigMethod >= 1) && (ConfigMethod <= 3)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Default Config Method is %d.\n", __FUNCTION__, ConfigMethod)); + DBGPRINT(RT_DEBUG_ERROR, (" 1: DISPLAY. 2: KEYPAD. 3. PBC\n")); + pP2PCtrl->DefaultConfigMethod = ConfigMethod; + } + return TRUE; +} + +INT Set_P2P_Link_Down_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) + +{ + POS_COOKIE pObj; + + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + P2pLinkDown(pAd, P2P_DISCONNECTED); + return TRUE; +} + +INT Set_P2P_Sigma_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) + +{ + UINT32 SigmaEnabled = 0; + POS_COOKIE pObj; + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + SigmaEnabled = simple_strtol(arg, 0, 10); + pP2PCtrl->bSigmaEnabled = ((SigmaEnabled == 0) ? FALSE : TRUE); + DBGPRINT(RT_DEBUG_ERROR, ("%s:: P2P Sigma Enable = %d.\n", __FUNCTION__, pP2PCtrl->bSigmaEnabled)); + + return TRUE; +} + +INT Set_P2P_QoS_NULL_Legacy_Rate_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) + +{ + UINT32 QoSNull = 0; + POS_COOKIE pObj; + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + QoSNull = simple_strtol(arg, 0, 10); + pP2PCtrl->bLowRateQoSNULL = ((QoSNull == 0) ? FALSE : TRUE); + DBGPRINT(RT_DEBUG_ERROR, ("%s:: P2P QoS NULL using Legacy Rate Enable = %d.\n", __FUNCTION__, pP2PCtrl->bLowRateQoSNULL)); + + return TRUE; +} + +INT Set_P2P_CLIENT_PM_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) + +{ + UINT32 P2pClientPm = 0; + POS_COOKIE pObj; + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + P2pClientPm = simple_strtol(arg, 0, 10); + pP2PCtrl->bP2pCliPmEnable= ((P2pClientPm == 0) ? FALSE : TRUE); + DBGPRINT(RT_DEBUG_ERROR, ("%s:: P2P CLIENT PM Enable = %d.\n", __FUNCTION__, pP2PCtrl->bP2pCliPmEnable)); + + return TRUE; +} + +INT Set_P2P_Enter_WSC_PIN_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) + +{ + POS_COOKIE pObj; + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + if ((strlen(arg) != 4) && (strlen(arg) != 8)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Reject this PIN (%s.)\n", __FUNCTION__, arg)); + return 0; + } + + NdisZeroMemory(&pP2PCtrl->PinCode[0], sizeof(pP2PCtrl->PinCode)); + RTMPMoveMemory(&pP2PCtrl->PinCode[0], arg, strlen(arg)); + Set_AP_WscPinCode_Proc(pAd, arg); + DBGPRINT(RT_DEBUG_ERROR, ("%s:: P2P Enter Peer PIN Code = %s.\n", __FUNCTION__, pP2PCtrl->PinCode)); + + return TRUE; +} + +INT Set_P2P_Persistent_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) + +{ + UINT32 PersistentEnabled = 0; + POS_COOKIE pObj; + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + PersistentEnabled = simple_strtol(arg, 0, 10); + pP2PCtrl->P2pControl.field.EnablePresistent = PersistentEnabled; + if ( PersistentEnabled == TRUE ) + { + pP2PCtrl->P2pCapability[1] |= GRPCAP_PERSISTENT; + pP2PCtrl->P2pCapability[1] |= GRPCAP_PERSISTENT_RECONNECT; + pP2PCtrl->ExtListenInterval = P2P_EXT_LISTEN_INTERVAL; + pP2PCtrl->ExtListenPeriod = P2P_EXT_LISTEN_PERIOD; + } + else + { + pP2PCtrl->P2pCapability[1] &= 0xDD; /* Set GRPCAP_PERSISTENT and GRPCAP_PERSISTENT_RECONNECT bits to 0 */ + pP2PCtrl->ExtListenInterval = 0; + pP2PCtrl->ExtListenPeriod = 0; + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: P2P Persistent Enable = %d.\n", __FUNCTION__, pP2PCtrl->P2pControl.field.EnablePresistent)); + + return TRUE; +} + +INT Set_P2P_Dev_Discoverability_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) + +{ + UINT32 DevDiscoverEnabled = 0; + POS_COOKIE pObj; + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + DevDiscoverEnabled = simple_strtol(arg, 0, 10); + pP2PCtrl->P2pControl.field.ClientDiscovery = DevDiscoverEnabled; + DBGPRINT(RT_DEBUG_ERROR, ("%s:: P2P Device Discoverability Enable = %d.\n", __FUNCTION__, pP2PCtrl->P2pControl.field.ClientDiscovery)); + + return TRUE; +} + +INT Set_P2P_DelDevByAddr_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR DevAddr[6] = {0}; + PMAC_TABLE_ENTRY pEntry = NULL; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + if (rtstrmactohex(arg, (PSTRING) &DevAddr[0]) == FALSE) + return FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: DevMac = %02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, PRINT_MAC(DevAddr))); + + pEntry = MacTableLookup(pAd, DevAddr); + + if (pEntry) + { + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + USHORT Reason = REASON_NO_LONGER_VALID; + HEADER_802_11 DeAuthHdr; + + MlmeAllocateMemory(pAd, &pOutBuffer); + + if (pOutBuffer) + { + DBGPRINT(RT_DEBUG_WARN, ("Send DEAUTH - Reason = %d frame tO %02x:%02x:%02x:%02x:%02x:%02x \n", + Reason, PRINT_MAC(DevAddr))); + + MgtMacHeaderInit(pAd, &DeAuthHdr, SUBTYPE_DEAUTH, 0, + pEntry->HdrAddr1, + pEntry->HdrAddr2, + pEntry->HdrAddr3); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DeAuthHdr, + 2, &Reason, + END_OF_ARGS); + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr); + P2pGroupTabDelete(pAd, P2P_NOT_FOUND, DevAddr); + } + } + + return TRUE; + +} + +INT Set_P2P_DevDiscPeriod_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return 0; + + pP2PCtrl->DevDiscPeriod = (UINT32)simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: P2P Device Discovery Period = %lu.\n", __FUNCTION__, pP2PCtrl->DevDiscPeriod)); + return TRUE; +} + +INT Set_P2P_PriDeviceType_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return FALSE; + + if (strlen(arg) != 16) + return FALSE; + + AtoH(arg, pP2PCtrl->DevInfo.PriDeviceType, 8); + + hex_dump("Set_P2P_PriDeviceType_Proc:: PriDeviceType", pP2PCtrl->DevInfo.PriDeviceType, 8); + return TRUE; +} + +/* + Usage Example: + Reference P2P Spec. v1.1 Table 29 , Device Info attribute format. + 1). 01 = length , 0007 == > Category ID (Display), 0050F204 ==>WFA OUI, 0001 ==> Sub Category ID + iwpriv p2p0 set p2p2ndDevTypeList=0100070050F2040001 + + 2). 02 = length , 0007 == > Category ID (Display), 0050F204 ==>WFA OUI, 0001 ==> Sub Category ID ; 0007 == > Category ID (Display), 0050F204 ==>WFA OUI, 0002 ==> Sub Category ID ; + iwpriv p2p0 set p2p2ndDevTypeList=0200070050F204000100070050F2040002 + + 3). clean up 2nd Device Type List + iwpriv p2p0 set p2p2ndDevTypeList= +*/ + +INT Set_P2P_SecDevTypeList_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + UCHAR len=0; + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return FALSE; + + len = strlen(arg); + + if (len == 0) //reset to zero + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: reset 2nd Device Type List!\n", __FUNCTION__)); + pP2PCtrl->DevInfo.SecDevTypList[0]=0x00; /* length is zero, so no don't need following 8 bytes*/ + } + else if((len >= (9*2))) /* 9 = 1 (length) + 8 (Category ID + WFA OUI + Sub-Category ID */ + { + if ((len % (8*2))==2) + + { + UCHAR tpylen=0; + AtoH(arg, (PUCHAR)&tpylen, 1); + AtoH(arg, pP2PCtrl->DevInfo.SecDevTypList, (tpylen*8)+1); + hex_dump("Set_P2P_SecDevTypeList_Proc : p2p2ndDevTypList",pP2PCtrl->DevInfo.SecDevTypList, (tpylen*8)+1); + + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: arg length incorrect\n", __FUNCTION__)); + return FALSE; + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: arg length is not enough!\n", __FUNCTION__)); + return FALSE; + } + + return TRUE; +} + +INT Set_P2P_Cancel_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + POS_COOKIE pObj; + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PWSC_CTRL pWscControl = NULL; + INT val = (INT)simple_strtol(arg, 0, 10); + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_P2P) + return FALSE; + + if (val == 1) + { + pP2PCtrl->P2PConnectState = P2P_CONNECT_IDLE; + if (!MAC_ADDR_EQUAL(&ZERO_MAC_ADDR[0], &pP2PCtrl->ConnectingMAC[0])) + { + UCHAR p2pindex; + + p2pindex = P2pGroupTabSearch(pAd, pP2PCtrl->ConnectingMAC); + if (p2pindex < MAX_P2P_GROUP_SIZE) + { + if (pAd->P2pTable.Client[p2pindex].Rule == P2P_IS_GO) + pAd->P2pTable.Client[p2pindex].P2pClientState = P2PSTATE_DISCOVERY_GO; + else + pAd->P2pTable.Client[p2pindex].P2pClientState = P2PSTATE_DISCOVERY; + pAd->P2pTable.Client[p2pindex].StateCount = 0; + } + NdisZeroMemory(pP2PCtrl->ConnectingMAC, MAC_ADDR_LEN); + } + + if (P2P_GO_ON(pAd)) + { + UINT32 i, p2pEntryCnt=0; + MAC_TABLE_ENTRY *pEntry; + INT IsAPConfigured; + + pWscControl = &pAd->ApCfg.MBSSID[MAIN_MBSSID].WscControl; + IsAPConfigured = pWscControl->WscConfStatus; + if (pWscControl->bWscTrigger) + { + WscStop(pAd, FALSE, pWscControl); + pWscControl->WscPinCode = 0; + WscBuildBeaconIE(pAd, IsAPConfigured, FALSE, 0, 0, MAIN_MBSSID, NULL, 0, AP_MODE); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, IsAPConfigured, FALSE, 0, 0, (MAIN_MBSSID | MIN_NET_DEVICE_FOR_P2P_GO), NULL, 0, AP_MODE); + APUpdateBeaconFrame(pAd, pObj->ioctl_if); + } + + for (i=0; iMacTab.Content[i]; + if (IS_P2P_GO_ENTRY(pEntry) && (pEntry->WpaState == AS_PTKINITDONE)) + p2pEntryCnt++; + } + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Total= %d. p2pEntry = %d.\n", __FUNCTION__, pAd->MacTab.Size, p2pEntryCnt)); + if ((p2pEntryCnt == 0) && (pAd->flg_p2p_OpStatusFlags == P2P_GO_UP)) + { + } + } + else if (P2P_CLI_ON(pAd)) + { + pWscControl = &pAd->ApCfg.MBSSID[MAIN_MBSSID].WscControl; + pWscControl->WscPinCode = 0; + if (pWscControl->bWscTrigger) + WscStop(pAd, TRUE, pWscControl); + P2pLinkDown(pAd, P2P_DISCONNECTED); + } + P2pStopScan(pAd); + pP2PCtrl->bPeriodicListen = TRUE; + pP2PCtrl->bConfirmByUI = FALSE; + + if (INFRA_ON(pAd) || P2P_GO_ON(pAd) || P2P_CLI_ON(pAd)) + { + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + UCHAR BBPValue = 0; + UINT32 Data = 0, macStatus; + UINT32 MTxCycle; + + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + + /* 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, &BBPValue); + BBPValue &= (~0x18); + BBPValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + + /* Enable MAC Tx/Rx */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Data); + Data |= 0x0C; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Data); + } + else + { + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + } + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: Cancel P2P action\n", __FUNCTION__, val)); + return TRUE; +} + +#endif /* P2P_SUPPORT */ + diff --git a/mt7620/src/common/p2p_disc_mng.c b/mt7620/src/common/p2p_disc_mng.c new file mode 100644 index 0000000..bfade65 --- /dev/null +++ b/mt7620/src/common/p2p_disc_mng.c @@ -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-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: + p2p_ctrl.c + + Abstract: + Peer to peer is also called Wifi Direct. P2P is a Task Group of WFA. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + +*/ +#include "rt_config.h" + + +static VOID P2PDiscScanAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID P2PDiscListenAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID P2PDiscSearchAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID P2PDiscCanlAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + + +/* + ========================================================================== + Description: + The mesh control state machine, + Parameters: + Sm - pointer to the state machine + Note: + the state machine looks like the following + ========================================================================== + */ + + #ifdef RELEAE_EXCLUDE +/* + Scan command P2P Periodic P2P Scan CntlOidScanProc MlmeCntlMachinePerformAction P2P Periodic + P2P_ENABLE_LISTEN_ONLY ---------------> P2P_IDLE -----------> P2P_SEARCH ---------> P2P_SEARCH_COMMAND ---------------> P2P_SEARCH ---------------------------> P2P_SEARCH_COMPLETE -----------> P2P_IDLE + MeshCtrlJoinAction : + . Init Bss Table + . Init Mesh Channel + . enqueue SYNC_STATE_MACHINE with MT2_MLME_SCAN_REQ + ScanNextChannel : + . scan done, enequeue MESH_CTRL_STATE_MACHINE with APMT2_MLME_SCAN_FINISH + + P2PCtrlJoinAction + . Init P2P Table + . Init random timer + . enqueeue SYNC_STATE_MACHINE with MT2_MLME_SCAN_REQ + ScanNextChannel : + . scan done, enequeue P2P_CTRL_STATE_MACHINE with P2P_SCAN_FINISH + P2PCtrlFinishDiscoveryAction : + . Init ScanNextRound + . change in P2P_IDLE +*/ + +/* + + P2P_CTRL_IDLE : do not scan / search / listen. + p2p interface up then in IDLE state, or after change as P2P Client / P2P GO in IDLE state. + P2P_CTRL_DISCOVERY : do scan / search / listen in an period. + Use P2PDiscMachine do such things and after times up, P2PDiscMachine and P2PCtrlMachine in IDLE state. + If we have Device Name / Device Address and WSC config method, P2PPeriodicExec should MlmeEnqueue + P2P_CTRL_GROUP_FORMATION in P2PCtrlMachine. + P2P_CTRL_GROUP_FORMATION : do Group Negotiation and Provision. + Use P2PGoFormMachine do such things in ConfigTimeout periodic. + P2P_CTRL_DONE : Group Formation has finish , interface will up as AP or STA code. + After AsicKey write done, can change to IDLE state. + +*/ +#endif /* RELEASE_EXCLUDE */ +VOID P2PDiscoveryStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, (ULONG)P2P_DISC_MAX_STATES, + (ULONG)P2P_DISC_MAX_EVENTS, (STATE_MACHINE_FUNC)Drop, P2P_DISC_IDLE, P2P_DISC_IDLE); + + /* P2P_DISC_IDLE state */ + StateMachineSetAction(Sm, P2P_DISC_IDLE, P2P_DISC_SCAN_CMD_EVT, (STATE_MACHINE_FUNC)P2PDiscScanAction); + StateMachineSetAction(Sm, P2P_DISC_IDLE, P2P_DISC_LISTEN_CMD_EVT, (STATE_MACHINE_FUNC)P2PDiscListenAction); + StateMachineSetAction(Sm, P2P_DISC_IDLE, P2P_DISC_PEER_PROB_REQ, (STATE_MACHINE_FUNC)PeerP2pProbeReq); + StateMachineSetAction(Sm, P2P_DISC_IDLE, P2P_DISC_PEER_PROB_RSP, (STATE_MACHINE_FUNC)PeerP2pBeaconProbeRspAtScan); + + /* P2P_DISC_SCAN state */ + StateMachineSetAction(Sm, P2P_DISC_SCAN, P2P_DISC_LISTEN_CMD_EVT, (STATE_MACHINE_FUNC)P2PDiscListenAction); + StateMachineSetAction(Sm, P2P_DISC_SCAN, P2P_DISC_CANL_CMD_EVT, (STATE_MACHINE_FUNC)P2PDiscCanlAction); + StateMachineSetAction(Sm, P2P_DISC_SCAN, P2P_DISC_PEER_PROB_RSP, (STATE_MACHINE_FUNC)PeerP2pBeaconProbeRspAtScan); + + /* P2P_DISC_LISTEN state */ + StateMachineSetAction(Sm, P2P_DISC_LISTEN, P2P_DISC_SEARCH_CMD_EVT, (STATE_MACHINE_FUNC)P2PDiscSearchAction); + StateMachineSetAction(Sm, P2P_DISC_LISTEN, P2P_DISC_CANL_CMD_EVT, (STATE_MACHINE_FUNC)P2PDiscCanlAction); + StateMachineSetAction(Sm, P2P_DISC_LISTEN, P2P_DISC_PEER_PROB_REQ, (STATE_MACHINE_FUNC)PeerP2pProbeReq); + StateMachineSetAction(Sm, P2P_DISC_LISTEN, P2P_DISC_SCAN_CMD_EVT, (STATE_MACHINE_FUNC)P2PDiscScanAction); + + /* P2P_DISC_SEARCH state */ + StateMachineSetAction(Sm, P2P_DISC_SEARCH, P2P_DISC_LISTEN_CMD_EVT, (STATE_MACHINE_FUNC)P2PDiscListenAction); + StateMachineSetAction(Sm, P2P_DISC_SEARCH, P2P_DISC_CANL_CMD_EVT, (STATE_MACHINE_FUNC)P2PDiscCanlAction); + StateMachineSetAction(Sm, P2P_DISC_SEARCH, P2P_DISC_PEER_PROB_RSP, (STATE_MACHINE_FUNC)PeerP2pBeaconProbeRspAtScan); + + /* init Device Discovery Timer */ + P2PInitDevDiscTimer(pAd, 0); + P2PInitNextScanTimer(pAd, 0); + P2PInitListenTimer(pAd, 0); + + /* init all P2P ctrl state. */ + pAd->P2pCfg.DiscCurrentState = P2P_DISC_IDLE; + + return; +} + +/* Device Discovery Action */ +static VOID P2PDiscScanAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + P2P_DISC_STATE *pCurrState = &(pAd->P2pCfg.DiscCurrentState); + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + MLME_SCAN_REQ_STRUCT ScanReq; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("%s::\n", __FUNCTION__)); + /* If I just finish group formation as GO. don't do scan . If I am auto GO, I should support P2P scan too. So check GoIntentIdx != 16. */ + if ((pP2PCtrl->P2PConnectState == P2P_ANY_IN_FORMATION_AS_GO) && (pP2PCtrl->GoIntentIdx <= 15)) + { + pP2PCtrl->P2pCounter.Counter100ms = 0; + } + + /* Stop Scan and resume */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + /*pAd->StaCfg.bSkipAutoScanConn = TRUE;*/ + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); + pAd->MlmeAux.Channel = 0; + ScanNextChannel(pAd, OPMODE_STA); + } + +#ifdef DPA_S + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_DISCOVER_START_80211_SCAN, NULL, NULL, 0); +#endif /* DPA_S */ + + /* Scan Type is SCAN_P2P for SYNC State Machine */ + ScanParmFill(pAd, &ScanReq, "", 0, BSS_ANY, SCAN_P2P); + 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; + *pCurrState = P2P_DISC_SCAN; +/* pAd->StaCfg.bSkipAutoScanConn = FALSE;*/ +} + +static VOID P2PDiscCanlAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + P2P_DISC_STATE *pCurrState = &(pAd->P2pCfg.DiscCurrentState); + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + UCHAR channel = pP2PCtrl->ListenChannel; + UCHAR p2pindex; + BOOLEAN bGoBack = TRUE; + + /* + Go back to working channel + */ + if (INFRA_ON(pAd) || (pAd->flg_p2p_OpStatusFlags != P2P_DISABLE)) + { + if ((pAd->CommonCfg.Channel != pAd->CommonCfg.CentralChannel) && (pAd->CommonCfg.BBPCurrentBW == BW_40)) + channel = pAd->CommonCfg.CentralChannel; + else + channel = pAd->CommonCfg.Channel; + } + + p2pindex = P2pGroupTabSearch(pAd, pAd->P2pCfg.ConnectingMAC); + if (p2pindex != P2P_NOT_FOUND) + { + if (pAd->P2pTable.Client[p2pindex].P2pClientState > P2PSTATE_DISCOVERY_UNKNOWN) + bGoBack = FALSE; + } + + if (bGoBack && (channel != pAd->LatchRfRegs.Channel)) + { + UINT32 Data = 0, macStatus; + UINT32 MTxCycle, MRxCycle; + + /* 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; + } + + AsicSwitchChannel(pAd, channel, FALSE); + AsicLockChannel(pAd, channel); + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + UCHAR BBPValue = 0; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + BBPValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + } + + //Enable MAC Tx/Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Data); + Data |= 0x0C; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Data); + DBGPRINT(RT_DEBUG_TRACE, ("P2PDiscCanlAction - Restore to channel %d\n",channel)); + } + + *pCurrState = P2P_DISC_IDLE; +} + +static VOID P2PDiscScanCanlAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + P2P_DISC_STATE *pCurrState = &(pAd->P2pCfg.DiscCurrentState); + /*PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg;*/ + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: The Device Discovery time has expired, stop!!\n", __FUNCTION__)); + *pCurrState = P2P_DISC_LISTEN; +} + +static VOID P2PDiscListenAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + P2P_DISC_STATE *pCurrState = &(pAd->P2pCfg.DiscCurrentState); + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + + if (pP2PCtrl->P2pCounter.bStartScan == TRUE) + pP2PCtrl->P2pCounter.ListenInterval = (RandomByte(pAd) % 3) + pP2PCtrl->P2pCounter.ListenIntervalBias; /* 1~3 */ + else + pP2PCtrl->P2pCounter.ListenInterval = 5; + + /* ExtListenInterval is in ms. So /100 */ + if (IS_P2P_SUPPORT_EXT_LISTEN(pAd)) + pP2PCtrl->P2pCounter.ListenInterval = pP2PCtrl->ExtListenPeriod/100; + + if (pAd->LatchRfRegs.Channel != pP2PCtrl->ListenChannel) + { + UINT32 Data = 0, macStatus; + UINT32 MTxCycle, MRxCycle; + UCHAR BBPValue = 0; + + /* 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; + } + + AsicSwitchChannel(pAd, pP2PCtrl->ListenChannel, FALSE); + AsicLockChannel(pAd, pP2PCtrl->ListenChannel); + + /* Let BBP register at 20MHz */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + + /* Enable MAC Tx/Rx */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Data); + Data |= 0x0C; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Data); + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: Listen interval - %d\n", __FUNCTION__, pP2PCtrl->P2pCounter.ListenInterval)); + + pP2PCtrl->P2pCounter.bListen = TRUE; + *pCurrState = P2P_DISC_LISTEN; +} + +static VOID P2PDiscListenCanlAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + P2P_DISC_STATE *pCurrState = &(pAd->P2pCfg.DiscCurrentState); + /*PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg;*/ + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: The Device Discovery time has expired, stop!!\n", __FUNCTION__)); + *pCurrState = P2P_DISC_LISTEN; +} + +static VOID P2PDiscSearchAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + P2P_DISC_STATE *pCurrState = &(pAd->P2pCfg.DiscCurrentState); + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + MLME_SCAN_REQ_STRUCT ScanReq; + + if (pP2PCtrl->P2pCounter.bStartScan) + { + DBGPRINT(RT_DEBUG_INFO, ("%s::\n", __FUNCTION__)); + ScanParmFill(pAd, &ScanReq, "", 0, BSS_ANY, SCAN_P2P_SEARCH); + 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; + *pCurrState = P2P_DISC_SEARCH; +} +} + +static VOID P2PDiscSearchCanlAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + P2P_DISC_STATE *pCurrState = &(pAd->P2pCfg.DiscCurrentState); + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: The Device Discovery time has expired, stop!!\n", __FUNCTION__)); + *pCurrState = P2P_DISC_LISTEN; +} diff --git a/mt7620/src/common/p2p_inf.c b/mt7620/src/common/p2p_inf.c new file mode 100644 index 0000000..cecbaa9 --- /dev/null +++ b/mt7620/src/common/p2p_inf.c @@ -0,0 +1,259 @@ +/* + *************************************************************************** + * 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: + p2p_inf.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + +*/ +#define RTMP_MODULE_OS + +#ifdef P2P_SUPPORT + +/*#include "rt_config.h" */ +/*#include "p2p_inf.h" */ +#include "rtmp_comm.h" +#include "rt_os_util.h" +#include "rt_os_net.h" + + +/* +======================================================================== +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. +======================================================================== +*/ +VOID RTMP_P2P_Init( + IN VOID *pAd, + IN PNET_DEV main_dev_p) +{ + /*PNET_DEV pDevNew; */ + /*INT status;*/ + RTMP_OS_NETDEV_OP_HOOK netDevHook; + /*APCLI_STRUCT *pApCliEntry; */ + + + DBGPRINT(RT_DEBUG_TRACE, ("%s --->\n", __FUNCTION__)); + + /* init operation functions and flags */ + NdisZeroMemory(&netDevHook, sizeof(netDevHook)); + netDevHook.open = P2P_VirtualIF_Open; /* device opem hook point */ + netDevHook.stop = P2P_VirtualIF_Close; /* device close hook point */ + netDevHook.xmit = P2P_VirtualIF_PacketSend; /* hard transmit hook point */ + netDevHook.ioctl = P2P_VirtualIF_Ioctl; /* ioctl hook point */ + +#if WIRELESS_EXT >= 12 + netDevHook.iw_handler = (void *)&rt28xx_ap_iw_handler_def; +#endif /* WIRELESS_EXT >= 12 */ + RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_P2P_INIT, + 0, &netDevHook, 0); + + DBGPRINT(RT_DEBUG_TRACE, ("%s <---\n", __FUNCTION__)); + +} + +/* +======================================================================== +Routine Description: + Open a virtual network interface. + +Arguments: + dev_p which WLAN network interface + +Return Value: + 0: open successfully + otherwise: open fail + +Note: +======================================================================== +*/ +INT P2P_VirtualIF_Open( + IN PNET_DEV dev_p) +{ + VOID *pAd; + /*PMULTISSID_STRUCT pMbss; */ + + 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 (RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_P2P_OPEN_PRE, 0, + dev_p, 0) != NDIS_STATUS_SUCCESS) + return -1; + + if (VIRTUAL_IF_UP(pAd) != 0) + return -1; + + /* increase MODULE use count */ + RT_MOD_INC_USE_COUNT(); + + RTMP_OS_NETDEV_START_QUEUE(dev_p); + + if (RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_P2P_OPEN_POST, 0, + dev_p, 0) != NDIS_STATUS_SUCCESS) + return -1; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: <=== %s\n", __FUNCTION__, RTMP_OS_NETDEV_GET_DEVNAME(dev_p))); + + 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 P2P_VirtualIF_Close( + IN 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))); + + /* stop p2p. */ + RTMP_OS_NETDEV_STOP_QUEUE(dev_p); + + RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_P2P_CLOSE, 0, dev_p, 0); + + VIRTUAL_IF_DOWN(pAd); + + RT_MOD_DEC_USE_COUNT(); + + return 0; +} + + +/* +======================================================================== +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 P2P_VirtualIF_PacketSend( + IN PNDIS_PACKET skb_p, + IN PNET_DEV dev_p) +{ + /*PRTMP_ADAPTER pAd; */ + /*PAPCLI_STRUCT pApCli; */ + + + MEM_DBG_PKT_ALLOC_INC(skb_p); + + if(!(RTMP_OS_NETDEV_STATE_RUNNING(dev_p))) + { + /* the interface is down */ + RELEASE_NDIS_PACKET(NULL, skb_p, NDIS_STATUS_FAILURE); + return 0; + } + + return P2P_PacketSend(skb_p, dev_p, rt28xx_packet_xmit); + +} /* End of P2P_VirtualIF_PacketSend */ + + +VOID RTMP_P2P_Remove( + IN VOID *pAd) +{ + /*MULTISSID_STRUCT *pMbss; */ + + + RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_P2P_REMOVE, 0, NULL, 0); + + +} /* End of RTMP_P2P_Remove */ + +/* +======================================================================== +Routine Description: + IOCTL to WLAN. + +Arguments: + dev_p which WLAN network interface + rq_p command information + cmd command ID + +Return Value: + 0: IOCTL successfully + otherwise: IOCTL fail + +Note: + SIOCETHTOOL 8946 New drivers use this ETHTOOL interface to + report link failure activity. +======================================================================== +*/ +INT P2P_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; +*/ + return rt28xx_ioctl(dev_p, rq_p, cmd); + +} /* End of P2P_VirtualIF_Ioctl */ + + +#endif /* P2P_SUPPORT */ + diff --git a/mt7620/src/common/p2p_nego_mng.c b/mt7620/src/common/p2p_nego_mng.c new file mode 100644 index 0000000..8c58f4f --- /dev/null +++ b/mt7620/src/common/p2p_nego_mng.c @@ -0,0 +1,581 @@ +/* + *************************************************************************** + * 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: + p2p_ctrl.c + + Abstract: + Peer to peer is also called Wifi Direct. P2P is a Task Group of WFA. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + +*/ +#include "rt_config.h" + + +/* Group Formation Action */ + +VOID P2pPeerGoNegoReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pPeerGoNegoRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pPeerGoNegoConfirmAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + + +VOID P2pPeerProvisionReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pPeerProvisionRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + + +VOID P2pPeerDeviceDiscRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pPeerInvitesReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pPeerInvitesRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pStartCommunicateAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pSendProvisionCmd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pSendInviteCmd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pSendDevDiscCmd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pSendServDiscCmd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pSendStartGroupFormCmd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pPeerDevDiscoverReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pSendPassedAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidP2PGoNegoState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static p2p_cmd_handler rt_p2p_handler[] = +{ + (p2p_cmd_handler) NULL, /* P2PSTATE_NONE, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_DISCOVERY, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_DISCOVERY_GO, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_DISCOVERY_CLIENT, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_DISCOVERY_UNKNOWN, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_CLIENT_DISCO_COMMAND, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_WAIT_GO_DISCO_ACK, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_WAIT_GO_DISCO_ACK_SUCCESS, */ + (p2p_cmd_handler) P2pSendDevDiscCmd, /* P2PSTATE_GO_DISCO_COMMAND, */ + (p2p_cmd_handler) P2pSendInviteCmd, /* P2PSTATE_INVITE_COMMAND, */ + (p2p_cmd_handler) P2pSendStartGroupFormCmd, /* P2PSTATE_CONNECT_COMMAND, */ + (p2p_cmd_handler) P2pSendProvisionCmd, /* P2PSTATE_PROVISION_COMMAND, */ + (p2p_cmd_handler) P2pSendServDiscCmd, /* P2PSTATE_SERVICE_DISCO_COMMAND, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_SERVICE_COMEBACK_COMMAND, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_SENT_INVITE_REQ, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_SENT_PROVISION_REQ, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_SENT_PROVISION_RSP, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_WAIT_REVOKEINVITE_RSP_ACK, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_REVOKEINVITE_RSP_ACK_SUCCESS, */ + (p2p_cmd_handler) P2pSendStartGroupFormCmd, /* P2PSTATE_SENT_GO_NEG_REQ, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_GOT_GO_RSP_INFO_UNAVAI, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_WAIT_GO_COMFIRM, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_WAIT_GO_COMFIRM_ACK, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_GOT_GO_COMFIRM, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_GO_COMFIRM_ACK_SUCCESS, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_REINVOKEINVITE_TILLCONFIGTIME, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_GO_DONE, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_GO_WPS, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_GO_AUTH, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_GO_ASSOC, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_CLIENT_WPS, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_CLIENT_WPS_DONE, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_CLIENT_AUTH, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_CLIENT_ASSOC, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_CLIENT_OPERATING, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_CLIENT_ABSENCE, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_CLIENT_SCAN, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_CLIENT_FIND, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_GO_OPERATING, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_GO_ABSENCE, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_GO_SCAN, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_GO_FIND, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_NONP2P_PSK, */ + (p2p_cmd_handler) NULL, /* P2PSTATE_NONP2P_WPS, */ +}; + +/* + ========================================================================== + Description: + The mesh control state machine, + Parameters: + Sm - pointer to the state machine + Note: + the state machine looks like the following + ========================================================================== + */ +VOID P2PGoFormationStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, (ULONG)P2P_GO_FORM_MAX_STATES, + (ULONG)P2P_GO_NEGO_MAX_EVENTS, (STATE_MACHINE_FUNC)Drop, P2P_GO_FORM_IDLE, P2P_GO_FORM_IDLE); + + /* P2P_GO_FORM_IDLE state */ + /*StateMachineSetAction(Sm, P2P_GO_FORM_IDLE, P2P_GO_NEGO_REQ_CMD_EVT, (STATE_MACHINE_FUNC)P2PStartGroupFormsAction); */ + StateMachineSetAction(Sm, P2P_GO_FORM_IDLE, P2P_PEER_GO_NEGO_REQ_EVT, (STATE_MACHINE_FUNC)P2pPeerGoNegoReqAction); + StateMachineSetAction(Sm, P2P_GO_FORM_IDLE, P2P_PEER_GO_NEGO_RSP_EVT, (STATE_MACHINE_FUNC)P2pPeerGoNegoRspAction); + StateMachineSetAction(Sm, P2P_GO_FORM_IDLE, P2P_PEER_GO_NEGO_PROV_REQ_EVT, (STATE_MACHINE_FUNC)P2pPeerProvisionReqAction); + /*StateMachineSetAction(Sm, P2P_GO_FORM_IDLE, P2P_GO_NEGO_PROV_REQ_CMD_EVT, (STATE_MACHINE_FUNC)P2pProvisionReqAction); */ + /*StateMachineSetAction(Sm, P2P_GO_FORM_IDLE, P2P_DEV_DISC_REQ_CMD_EVT, (STATE_MACHINE_FUNC)P2pDeviceDiscReqAction); */ + StateMachineSetAction(Sm, P2P_GO_FORM_IDLE, P2P_PEER_INVITE_REQ_EVT, (STATE_MACHINE_FUNC)P2pPeerInvitesReqAction); + StateMachineSetAction(Sm, P2P_GO_FORM_IDLE, P2P_START_COMMUNICATE_CMD_EVT, (STATE_MACHINE_FUNC)P2pStartCommunicateAction); + StateMachineSetAction(Sm, P2P_GO_FORM_IDLE, P2P_PEER_DEV_DISC_REQ_EVT, (STATE_MACHINE_FUNC)P2pPeerDevDiscoverReqAction); + StateMachineSetAction(Sm, P2P_GO_FORM_IDLE, P2P_SEND_PASSED_CMD_EVT, (STATE_MACHINE_FUNC)P2pSendPassedAction); + StateMachineSetAction(Sm, P2P_GO_FORM_IDLE, P2P_PEER_GO_NEGO_PROV_RSP_EVT, (STATE_MACHINE_FUNC)P2pPeerProvisionRspAction); + + /* P2P_WAIT_GO_FORM_RSP state */ + StateMachineSetAction(Sm, P2P_WAIT_GO_FORM_RSP, P2P_PEER_GO_NEGO_RSP_EVT, (STATE_MACHINE_FUNC)P2pPeerGoNegoRspAction); + StateMachineSetAction(Sm, P2P_WAIT_GO_FORM_RSP, P2P_START_COMMUNICATE_CMD_EVT, (STATE_MACHINE_FUNC)InvalidP2PGoNegoState); + + /* P2P_WAIT_GO_FORM_CONF state */ + StateMachineSetAction(Sm, P2P_WAIT_GO_FORM_CONF, P2P_PEER_GO_NEGO_CONFIRM_EVT, (STATE_MACHINE_FUNC)P2pPeerGoNegoConfirmAction); + StateMachineSetAction(Sm, P2P_WAIT_GO_FORM_CONF, P2P_SEND_PASSED_CMD_EVT, (STATE_MACHINE_FUNC)P2pSendPassedAction); + StateMachineSetAction(Sm, P2P_WAIT_GO_FORM_CONF, P2P_PEER_GO_NEGO_REQ_EVT, (STATE_MACHINE_FUNC)P2pPeerGoNegoReqAction); // carella : 2011-06-13. + + /* P2P_GO_FORM_PROV state */ + StateMachineSetAction(Sm, P2P_WAIT_GO_FORM_PROV_RSP, P2P_PEER_GO_NEGO_PROV_RSP_EVT, (STATE_MACHINE_FUNC)P2pPeerProvisionRspAction); + + /* P2P_GO_FORM_DEV_DISC state */ + StateMachineSetAction(Sm, P2P_WAIT_GO_FORM_DEV_DISC_RSP, P2P_PEER_DEV_DISC_RSP_EVT, (STATE_MACHINE_FUNC)P2pPeerDeviceDiscRspAction); + + /* P2P_WAIT_GO_FORM_INVITE_RSP state */ + StateMachineSetAction(Sm, P2P_WAIT_GO_FORM_INVITE_RSP, P2P_PEER_INVITE_RSP_EVT, (STATE_MACHINE_FUNC)P2pPeerInvitesRspAction); + + /* init all P2P ctrl state. */ + pAd->P2pCfg.GoFormCurrentState = P2P_GO_FORM_IDLE; + + return; +} + +/* Group Formation Acrtion */ + +VOID P2pPeerGoNegoReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + if (pAd->P2pCfg.GoFormCurrentState != P2P_GO_FORM_IDLE && pAd->P2pCfg.GoFormCurrentState != P2P_WAIT_GO_FORM_CONF ) + return; + P2P_GO_FORM_STATE *pCurrState = &(pAd->P2pCfg.GoFormCurrentState); + + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + if ( pP2PCtrl->bProvAutoRsp == FALSE ) + { + BOOLEAN Cancelled; + + if (pP2PCtrl->bP2pReSendTimerRunning) + { + pP2PCtrl->bP2pReSendTimerRunning = FALSE; + pAd->P2pTable.Client[pP2PCtrl->P2pProvIndex].ReTransmitCnt = 0; + RTMPCancelTimer(&pP2PCtrl->P2pReSendTimer, &Cancelled); + } + + pP2PCtrl->P2pProvIndex = P2P_NOT_FOUND; + pP2PCtrl->P2pProvUserNotify = FALSE; + pAd->P2pCfg.P2pCounter.UserAccept = 0; + } + +#ifdef DPA_S + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_GROUP_OWNER_NEGOTIATION_START, NULL, NULL, 0); +#endif /* DPA_S */ + /* + Skip auto scan conn in STAMlmePeriodicExec + */ + pAd->StaCfg.bSkipAutoScanConn = TRUE; + P2pReceGoNegoReqAction(pAd, Elem); + + *pCurrState = P2P_WAIT_GO_FORM_CONF; +} + +VOID P2pPeerGoNegoRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + if (pAd->P2pCfg.GoFormCurrentState != P2P_GO_FORM_IDLE && pAd->P2pCfg.GoFormCurrentState != P2P_WAIT_GO_FORM_RSP ) + return; + + P2P_GO_FORM_STATE *pCurrState = &(pAd->P2pCfg.GoFormCurrentState); + *pCurrState = P2P_GO_FORM_IDLE; + + DBGPRINT(RT_DEBUG_ERROR, ("%s::\n", __FUNCTION__)); + P2pReceGoNegoRspAction(pAd, Elem); + +} + +VOID P2pPeerGoNegoConfirmAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + P2P_GO_FORM_STATE *pCurrState = &(pAd->P2pCfg.GoFormCurrentState); + + if (pAd->P2pCfg.GoFormCurrentState != P2P_WAIT_GO_FORM_CONF) + return; + + P2pReceGoNegoConfirmAction(pAd, Elem); + /* + DO NOT skip auto scan conn in STAMlmePeriodicExec + */ + pAd->StaCfg.bSkipAutoScanConn = FALSE; + *pCurrState = P2P_GO_FORM_IDLE; +} + + +VOID P2pPeerProvisionReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + P2P_GO_FORM_STATE *pCurrState = &(pAd->P2pCfg.GoFormCurrentState); + + if (pAd->P2pCfg.GoFormCurrentState != P2P_GO_FORM_IDLE) + return; + + /* + Skip auto scan conn in STAMlmePeriodicExec + */ + pAd->StaCfg.bSkipAutoScanConn = TRUE; + + P2pReceProvisionReqAction(pAd, Elem); + + *pCurrState = P2P_GO_FORM_IDLE; +} + +VOID P2pPeerProvisionRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + P2P_GO_FORM_STATE *pCurrState = &(pAd->P2pCfg.GoFormCurrentState); + + if (pAd->P2pCfg.GoFormCurrentState != P2P_WAIT_GO_FORM_PROV_RSP && pAd->P2pCfg.GoFormCurrentState != P2P_GO_FORM_IDLE) + + return; + + P2pReceProvisionRspAction(pAd, Elem); + MlmeEnqueue(pAd, P2P_DISC_STATE_MACHINE, P2P_DISC_CANL_CMD_EVT, 0, NULL, 0); + + /* + DO NOT skip auto scan conn in STAMlmePeriodicExec + */ + pAd->StaCfg.bSkipAutoScanConn = FALSE; + *pCurrState = P2P_GO_FORM_IDLE; +} + + +VOID P2pPeerDeviceDiscRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + P2P_GO_FORM_STATE *pCurrState = &(pAd->P2pCfg.GoFormCurrentState); + + if (pAd->P2pCfg.GoFormCurrentState != P2P_WAIT_GO_FORM_DEV_DISC_RSP) + return; + + P2pReceDevDisRspAction(pAd, Elem); + + *pCurrState = P2P_GO_FORM_IDLE; +} + +VOID P2pPeerInvitesReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + P2P_GO_FORM_STATE *pCurrState = &(pAd->P2pCfg.GoFormCurrentState); + + if (pAd->P2pCfg.GoFormCurrentState != P2P_GO_FORM_IDLE ) + + return; + + /* + Skip auto scan conn in STAMlmePeriodicExec + */ + pAd->StaCfg.bSkipAutoScanConn = TRUE; + P2pReceInviteReqAction(pAd, Elem); + + *pCurrState = P2P_GO_FORM_IDLE; +} + +VOID P2pPeerInvitesRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + P2P_GO_FORM_STATE *pCurrState = &(pAd->P2pCfg.GoFormCurrentState); + + if (pAd->P2pCfg.GoFormCurrentState != P2P_WAIT_GO_FORM_INVITE_RSP) + return; + + P2pReceInviteRspAction(pAd, Elem); + MlmeEnqueue(pAd, P2P_DISC_STATE_MACHINE, P2P_DISC_CANL_CMD_EVT, 0, NULL, 0); + + /* + DO NOT skip auto scan conn in STAMlmePeriodicExec + */ + pAd->StaCfg.bSkipAutoScanConn = FALSE; + *pCurrState = P2P_GO_FORM_IDLE; +} + +VOID P2pPeerDevDiscoverReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + P2P_GO_FORM_STATE *pCurrState = &(pAd->P2pCfg.GoFormCurrentState); + + if (pAd->P2pCfg.GoFormCurrentState != P2P_GO_FORM_IDLE) + return; + + P2pReceDevDisReqAction(pAd, Elem); + + *pCurrState = P2P_GO_FORM_IDLE; +} + +VOID InvalidP2PGoNegoState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + P2P_GO_FORM_STATE *pCurrState = &(pAd->P2pCfg.GoFormCurrentState); + *pCurrState = P2P_GO_FORM_IDLE; +} + +VOID P2pStartCommunicateAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + p2p_cmd_handler p2p_handler; + + p2p_handler = rt_p2p_handler[Elem->Priv]; + if (p2p_handler) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s:: CMD_ID = %ld\n", __FUNCTION__, Elem->Priv)); + p2p_handler(pAd, Elem); + } +} + +VOID P2pSendProvisionCmd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + P2P_GO_FORM_STATE *pCurrState = &(pAd->P2pCfg.GoFormCurrentState); + PP2P_CMD_STRUCT pP2pCmd = (PP2P_CMD_STRUCT)Elem->Msg; + UCHAR p2pIdx; + ULONG FrameLen; + USHORT PeerWscMethod; + UCHAR Addr[6] = {0}; + DBGPRINT(RT_DEBUG_ERROR, ("%s::\n", __FUNCTION__)); + DBGPRINT(RT_DEBUG_ERROR, ("Addr = %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pP2pCmd->Addr))); + p2pIdx = P2pGroupTabSearch(pAd, pP2pCmd->Addr); + P2PPrintP2PEntry(pAd, p2pIdx); + + if (p2pIdx == P2P_NOT_FOUND) + return; + + if (pAd->P2pTable.Client[p2pIdx].Rule == P2P_IS_GO) + RTMPMoveMemory(&Addr, pAd->P2pTable.Client[p2pIdx].bssid, sizeof(Addr)); + else + RTMPMoveMemory(&Addr, pAd->P2pTable.Client[p2pIdx].addr, sizeof(Addr)); + + if (pAd->P2pCfg.Dpid != DEV_PASS_ID_NOSPEC) + { + if ((pAd->P2pCfg.Dpid == DEV_PASS_ID_USER) && ((pAd->P2pTable.Client[p2pIdx].ConfigMethod & WSC_CONFMET_DISPLAY) != 0)) + { + pAd->P2pTable.Client[p2pIdx].P2pClientState = P2PSTATE_SENT_PROVISION_REQ; + P2PSendProvisionReq(pAd, WSC_CONFMET_DISPLAY, pAd->P2pTable.Client[p2pIdx].GeneralToken, pAd->P2pTable.Client[p2pIdx].addr, &FrameLen); + DBGPRINT(RT_DEBUG_ERROR, ("Request : CONFIG_METHOD_DISPLAY \n")); + } + else if ((pAd->P2pCfg.Dpid == DEV_PASS_ID_PBC) && ((pAd->P2pTable.Client[p2pIdx].ConfigMethod & WSC_CONFMET_PBC) != 0)) + { + pAd->P2pTable.Client[p2pIdx].P2pClientState = P2PSTATE_SENT_PROVISION_REQ; + P2PSendProvisionReq(pAd, WSC_CONFMET_PBC, pAd->P2pTable.Client[p2pIdx].GeneralToken, pAd->P2pTable.Client[p2pIdx].addr, &FrameLen); + DBGPRINT(RT_DEBUG_TRACE, ("Request : CONFIG_METHOD_PUSHBUTTON \n")); + } + else if ((pAd->P2pCfg.Dpid == DEV_PASS_ID_REG) && ((pAd->P2pTable.Client[p2pIdx].ConfigMethod&WSC_CONFMET_KEYPAD) != 0)) + { + pAd->P2pTable.Client[p2pIdx].P2pClientState = P2PSTATE_SENT_PROVISION_REQ; + P2PSendProvisionReq(pAd, WSC_CONFMET_KEYPAD, pAd->P2pTable.Client[p2pIdx].GeneralToken, pAd->P2pTable.Client[p2pIdx].addr, &FrameLen); + DBGPRINT(RT_DEBUG_ERROR, ("Request : CONFIG_METHOD_KEYPAD \n")); + } + else + { + pAd->P2pTable.Client[p2pIdx].P2pClientState = P2PSTATE_SENT_PROVISION_REQ; + if (pAd->P2pCfg.ConfigMethod == WSC_CONFMET_DISPLAY) + P2PSendProvisionReq(pAd, WSC_CONFMET_KEYPAD, pAd->P2pTable.Client[p2pIdx].GeneralToken, Addr/*pAd->P2pTable.Client[p2pIdx].addr*/, &FrameLen); + else if (pAd->P2pCfg.ConfigMethod == WSC_CONFMET_KEYPAD) + P2PSendProvisionReq(pAd, WSC_CONFMET_DISPLAY, pAd->P2pTable.Client[p2pIdx].GeneralToken, Addr/*pAd->P2pTable.Client[p2pIdx].addr*/, &FrameLen); + else + P2PSendProvisionReq(pAd, WSC_CONFMET_PBC, pAd->P2pTable.Client[p2pIdx].GeneralToken, Addr/*pAd->P2pTable.Client[p2pIdx].addr*/, &FrameLen); + } + } + else + { + P2P_SetWscRule(pAd, pP2pCmd->Idx, &PeerWscMethod); + pAd->P2pTable.Client[p2pIdx].P2pClientState = P2PSTATE_SENT_PROVISION_REQ; + P2PSendProvisionReq(pAd, PeerWscMethod, pAd->P2pTable.Client[p2pIdx].GeneralToken, pAd->P2pTable.Client[p2pIdx].addr, &FrameLen); + DBGPRINT(RT_DEBUG_ERROR, ("Request : CONFIG_METHOD_KEYPAD \n")); + } + + *pCurrState = P2P_WAIT_GO_FORM_PROV_RSP; +} + + +VOID P2pSendInviteCmd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + P2P_GO_FORM_STATE *pCurrState = &(pAd->P2pCfg.GoFormCurrentState); + PP2P_CMD_STRUCT pP2pCmd = (PP2P_CMD_STRUCT)Elem->Msg; + UCHAR perstindex, p2pIndex; + + DBGPRINT(RT_DEBUG_ERROR, ("%s::\n", __FUNCTION__)); + DBGPRINT(RT_DEBUG_ERROR, ("Addr = %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pP2pCmd->Addr))); + + p2pIndex = pP2pCmd->Idx; + if (pP2PCtrl->Rule == P2P_IS_GO) + { + /* Invite Case 1 : I am Auto GO to invite a P2P Device or when I am P2P Client */ + P2pInvite(pAd, pP2pCmd->Addr, MAX_P2P_TABLE_SIZE, p2pIndex); + } + else if (IS_P2P_CONNECT_IDLE(pAd)) + { + /* since I am idle, */ + perstindex = P2pPerstTabSearch(pAd, pAd->P2pTable.Client[p2pIndex].addr, pAd->P2pTable.Client[p2pIndex].bssid, pAd->P2pTable.Client[p2pIndex].InterfaceAddr); + if ((perstindex < MAX_P2P_TABLE_SIZE) && (IS_PERSISTENT_ON(pAd))) + { + /* + I have credential, my persistent is enabled, peer 's persistent is enabled. + So use Reinvoke method to start P2P group. + */ + P2pInvite(pAd, pAd->P2pTable.Client[p2pIndex].addr, perstindex, p2pIndex); + pAd->P2pCfg.P2PConnectState = P2P_INVITE; + } + } + + *pCurrState = P2P_WAIT_GO_FORM_INVITE_RSP; +} + +VOID P2pSendDevDiscCmd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + P2P_GO_FORM_STATE *pCurrState = &(pAd->P2pCfg.GoFormCurrentState); + PP2P_CMD_STRUCT pP2pCmd = (PP2P_CMD_STRUCT)Elem->Msg; + UCHAR p2pIdx; + DBGPRINT(RT_DEBUG_ERROR, ("%s::\n", __FUNCTION__)); + DBGPRINT(RT_DEBUG_ERROR, ("Addr = %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pP2pCmd->Addr))); + p2pIdx = P2pGroupTabSearch(pAd, pP2pCmd->Addr); + P2PPrintP2PEntry(pAd, p2pIdx); + + if (p2pIdx == P2P_NOT_FOUND) + return; + + P2pClientDiscovery(pAd, pAd->P2pTable.Client[p2pIdx].addr, p2pIdx); + *pCurrState = P2P_WAIT_GO_FORM_DEV_DISC_RSP; +} + +VOID P2pSendServDiscCmd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + P2P_GO_FORM_STATE *pCurrState = &(pAd->P2pCfg.GoFormCurrentState); + PP2P_CMD_STRUCT pP2pCmd = (PP2P_CMD_STRUCT)Elem->Msg; + UCHAR p2pIdx; + DBGPRINT(RT_DEBUG_ERROR, ("%s::\n", __FUNCTION__)); + DBGPRINT(RT_DEBUG_ERROR, ("Addr = %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pP2pCmd->Addr))); + p2pIdx = P2pGroupTabSearch(pAd, pP2pCmd->Addr); + P2PPrintP2PEntry(pAd, p2pIdx); + + if (p2pIdx == P2P_NOT_FOUND) + return; + + P2pSendServiceReqCmd(pAd, pAd->P2pTable.Client[p2pIdx].addr, p2pIdx); + pAd->P2pTable.Client[p2pIdx].P2pClientState = P2PSTATE_DISCOVERY; + *pCurrState = P2P_WAIT_GO_FORM_SRV_DISC_RSP; +} + +VOID P2pSendStartGroupFormCmd( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + P2P_GO_FORM_STATE *pCurrState = &(pAd->P2pCfg.GoFormCurrentState); + PP2P_CMD_STRUCT pP2pCmd = (PP2P_CMD_STRUCT)Elem->Msg; + USHORT PeerWscMethod; + + DBGPRINT(RT_DEBUG_ERROR, ("%s::\n", __FUNCTION__)); + DBGPRINT(RT_DEBUG_ERROR, ("Addr = %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pP2pCmd->Addr))); + P2PPrintP2PEntry(pAd, pP2pCmd->Idx); + *pCurrState = P2P_WAIT_GO_FORM_RSP; + if (pP2PCtrl->Dpid == DEV_PASS_ID_NOSPEC) + P2P_SetWscRule(pAd, pP2pCmd->Idx, &PeerWscMethod); + P2pStartGroupForm(pAd, pAd->P2pTable.Client[pP2pCmd->Idx].addr, pP2pCmd->Idx); +} + +VOID P2pSendPassedAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + P2P_GO_FORM_STATE *pCurrState = &(pAd->P2pCfg.GoFormCurrentState); + PP2P_CMD_STRUCT pP2pCmd = (PP2P_CMD_STRUCT)Elem->Msg; + UCHAR index = pP2pCmd->Idx; + + DBGPRINT(RT_DEBUG_ERROR, ("%s::\n", __FUNCTION__)); + DBGPRINT(RT_DEBUG_ERROR, ("Addr = %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pP2pCmd->Addr))); + + P2pConnectPrepare(pAd, pP2pCmd->Addr, P2PSTATE_CONNECT_COMMAND); + *pCurrState = P2P_GO_FORM_IDLE; +} + diff --git a/mt7620/src/common/p2p_packet.c b/mt7620/src/common/p2p_packet.c new file mode 100644 index 0000000..d0fe54f --- /dev/null +++ b/mt7620/src/common/p2p_packet.c @@ -0,0 +1,6042 @@ +/* + *************************************************************************** + * 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: + p2p_packet.c + + Abstract: + Peer to peer is also called Wifi Direct. P2P is a Task Group of WFA. this file contains all functions that handles p2p packets + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Jan Lee 2010-03-08 created for Peer-to-Peer(Wifi Direct) +*/ +#include "rt_config.h" + +extern UCHAR OutMsgBuf[]; /* buffer to create message contents */ +extern UCHAR WILDP2PSSID[]; +extern UCHAR WILDP2PSSIDLEN; +extern UCHAR WIFIDIRECT_OUI[]; +extern UCHAR P2POUIBYTE[]; +extern UCHAR ZERO_MAC_ADDR[]; +extern UCHAR WPS_OUI[]; +extern UCHAR STA_Wsc_Pri_Dev_Type[]; +extern UCHAR AP_Wsc_Pri_Dev_Type[]; + +extern INT Set_P2p_OpMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +extern INT Set_P2pCli_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + + +/* + ========================================================================== + Description: + Publiac action frame. But with ACtion is GAS_INITIAL_REQ (11). + 802.11u. 7.4.7.10 + + Parameters: + Note: + + ========================================================================== + */ +VOID PeerGASIntialReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + /*UCHAR Action = Elem->Msg[LENGTH_802_11+1]; */ + /*PUCHAR pAdProtocolElem; */ + /*PUCHAR pQueryReq; */ + + DBGPRINT(RT_DEBUG_TRACE,("P2pPeer GASIntialReqAction = %ld, \n", Elem->MsgLen)); +} + +/* + ========================================================================== + Description: + Publiac action frame. But with ACtion is GAS_INITIAL_RSP (12). + 802.11u. 7.4.7.11 + + Parameters: + Note: + + ========================================================================== + */ +VOID PeerGASIntialRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + /*UCHAR Action = Elem->Msg[LENGTH_802_11+1]; */ + /*UCHAR StatusCode; */ + /*USHORT ComeBackDelay; */ + /*PUCHAR pAdProtocolElem; */ + /*PUCHAR pQueryRsp; */ + ULONG i; + PUCHAR pDest; + + DBGPRINT(RT_DEBUG_TRACE,("P2pPeer PeerGASIntialRspAction = %ld, \n", Elem->MsgLen)); + pDest = &Elem->Msg[0]; + for (i = 0; i MsgLen; ) + { + DBGPRINT(RT_DEBUG_TRACE,(": %x %x %x %x %x %x %x %x %x %x \n", *(pDest+i), *(pDest+i+1), *(pDest+i+2), + *(pDest+i+3), *(pDest+i+4), *(pDest+i+5), *(pDest+i+6), *(pDest+i+7), *(pDest+i+8), *(pDest+i+9))); + i = i + 10; + } +} + +/* + ========================================================================== + + Description: + Receive Public Action frame that set to verdor specific and with OUI type = WFA P2P + ========================================================================== + */ +VOID P2PPublicAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + DBGPRINT(RT_DEBUG_ERROR, ("!!!!! Should not in here !!!!!\n")); +} + +/* + ========================================================================== + 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 P2PMakeFakeNoATlv( + IN PRTMP_ADAPTER pAd, + IN ULONG StartTime, + IN PUCHAR pOutBuffer) +{ + PUCHAR pDest; + + 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) = pAd->P2pCfg.GONoASchedule.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) = pAd->P2pCfg.GONoASchedule.Count; + /* Duration */ + RTMPMoveMemory((pDest+6), &pAd->P2pCfg.GONoASchedule.Duration, 4); + /* Interval */ + RTMPMoveMemory((pDest+10), &pAd->P2pCfg.GONoASchedule.Interval, 4); + RTMPMoveMemory((pDest+14), &StartTime, 4); + +} + +/* + ========================================================================== + Description: + Insert P2P subelement P2P Group Info format in Probe Response. it contains device information of + P2P Clients that are members of my P2P group. + + Parameters: + pInBuffer : pointer to data that contains data to put in + pOutBuffer : pointer to buffer that should put data to. + Note: + + ========================================================================== + */ +ULONG InsertP2PGroupInfoTlv( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pOutBuffer) +{ + PUCHAR pDest, pContent; + UCHAR Length; + UCHAR i; + UCHAR NoOfClient = 0; + P2P_CLIENT_INFO_DESC ClientInfo; + RT_P2P_CLIENT_ENTRY *pClient; + UCHAR ZeroType[P2P_DEVICE_TYPE_LEN]; + UCHAR DevCapability; + USHORT config_method = 0; + + pDest = pOutBuffer; + RTMPZeroMemory(pDest, 255); + RTMPZeroMemory(ZeroType, P2P_DEVICE_TYPE_LEN); + *pDest = SUBID_P2P_GROUP_INFO; + *(pDest + 2) = 0; /* Set length to 0 first. Need to update to real length in the end of this function. */ + pContent = pDest + 3; /* pContent points to payload. */ + Length = 0; + + for (i = 0;i < MAX_P2P_GROUP_SIZE;i++) + { + pClient = &pAd->P2pTable.Client[i]; + + /* if (IS_P2P_PEER_CLIENT_OP(pClient)) */ + if (pClient->P2pClientState == P2PSTATE_CLIENT_WPS_DONE) + { + NoOfClient++; + RTMPZeroMemory(&ClientInfo, sizeof(ClientInfo)); + RTMPMoveMemory(ClientInfo.DevAddr, pClient->addr, MAC_ADDR_LEN); + DBGPRINT(RT_DEBUG_INFO, (" -- InsertP2PGroupInfoTlv( ) (Mac %02x:%02x:%02x:%02x:%02x:%02x.\n", PRINT_MAC(pClient->addr))); + RTMPMoveMemory(ClientInfo.InterfaceAddr, pClient->InterfaceAddr, MAC_ADDR_LEN); + DevCapability = pClient->DevCapability; + if (P2P_TEST_FLAG(pClient, P2PFLAG_DEVICE_DISCOVERABLE)) + DevCapability |= DEVCAP_CLIENT_DISCOVER; + + ClientInfo.Capability = DevCapability; + config_method = cpu2be16(pClient->ConfigMethod); + RTMPMoveMemory(ClientInfo.ConfigMethod, &config_method, 2); + RTMPMoveMemory(ClientInfo.PrimaryDevType, pClient->PrimaryDevType, P2P_DEVICE_TYPE_LEN); + ClientInfo.NumSecondaryType = pClient->NumSecondaryType; + /* JANTEMP set to zero first. will add soon. */ + ClientInfo.NumSecondaryType = 0; + RTMPMoveMemory(ClientInfo.PrimaryDevType, pClient->PrimaryDevType, P2P_DEVICE_TYPE_LEN); + ClientInfo.Length = SIZE_OF_FIXED_CLIENT_INFO_DESC - 1 + pClient->DeviceNameLen + 4; + RTMPMoveMemory(pContent, &ClientInfo, SIZE_OF_FIXED_CLIENT_INFO_DESC); + pContent += SIZE_OF_FIXED_CLIENT_INFO_DESC; + /* Length is accumulated length for this attirbute. */ + Length += SIZE_OF_FIXED_CLIENT_INFO_DESC; + /* Insert WPS Device Name TLV */ + *((PUSHORT) pContent) = cpu2be16(WSC_ID_DEVICE_NAME); + *((PUSHORT) (pContent + 2)) = cpu2be16(pClient->DeviceNameLen); + RTMPMoveMemory(pContent + 4, pClient->DeviceName, pClient->DeviceNameLen); + Length += (UCHAR)pClient->DeviceNameLen + 4; + pContent += (pClient->DeviceNameLen + 4); + /* Assign this client info descriptor's length. Length is accumulated length. so can't use Length. */ + /*if (!RTMPEqualMemory(pClient->SecondaryDevType, &ZeroType, P2P_DEVICE_TYPE_LEN)) + { + // JANTEMP. force to support add only one secondary device type first. will improve later. + *pContent = 1; + RTMPMoveMemory(pContent+1, pClient->SecondaryDevType, P2P_DEVICE_TYPE_LEN); + Length += (1+P2P_DEVICE_TYPE_LEN); + ClientInfo.Length += (1+P2P_DEVICE_TYPE_LEN); + }*/ + DBGPRINT(RT_DEBUG_INFO, (" ----- InsertP2PGroupInfoTlv(%d) (Total Len now = %d) DevNameLen = %ld.\n", i, Length, pClient->DeviceNameLen)); + } + } + + /* Because the length field doesn't count itself. So when update Attribute length, need to add number of client descriptor. */ + //Length += NoOfClient; + + *(pDest + 1) = Length; /* Set to real length */ + + return (Length + 3); + +} + + +/* + ========================================================================== + Description: + Used to insert P2P subelement TLV format. + + Parameters: + pInBuffer : pointer to data that contains data to put in + pOutBuffer : pointer to buffer that should put data to. + Note: + + ========================================================================== + */ +ULONG InsertP2PSubelmtTlv( + IN PRTMP_ADAPTER pAd, + IN UCHAR SubId, + IN PUCHAR pInBuffer, + IN PUCHAR pOutBuffer) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PUCHAR pDest; + ULONG Length; + + pDest = pOutBuffer; + RTMPZeroMemory(pDest, 255); + *pDest = SubId; + pDest += 1; + Length = 0; + switch(SubId) + { + case SUBID_P2P_INVITE_FLAG: + *pDest = 1; + *(pDest + 1) = 0; + *(pDest + 2) = *pInBuffer; + + Length = 4; + break; + case SUBID_P2P_STATUS: /* 0 */ + *pDest = 1; + *(pDest + 1) = 0; + *(pDest + 2) = *pInBuffer; + + Length = 4; + break; + case SUBID_P2P_MINOR_REASON: /* 0 */ + break; + case SUBID_P2P_CAP: /* 2 */ + *pDest = 2; + *(pDest + 1) = 0; + RTMPMoveMemory(pDest + 2, pInBuffer, 2); + Length = 5; + break; + case SUBID_P2P_DEVICE_ID: /* 3 this is Device Address! */ + case SUBID_P2P_GROUP_BSSID: /* 6 group Bssid */ + case SUBID_P2P_INTERFACE_ADDR: /* 9 */ + *pDest = 6; + *(pDest + 1) = 0; + RTMPMoveMemory(pDest + 2, pInBuffer, MAC_ADDR_LEN); + /* DEvice Type */ + /*RTMPMoveMemory(pDest + 7, pAd->CurrentAddress, 8); */ + + Length = 9; + break; + case SUBID_P2P_OWNER_INTENT: /* 4 */ + *pDest = 1; + *(pDest + 1) = 0; + *(pDest + 2) = *pInBuffer; + Length = 4; + break; + + case SUBID_P2P_CONFIG_TIMEOUT: /* 5 */ + *pDest = 2; + *(pDest + 1) = 0; + RTMPMoveMemory(pDest + 2, pInBuffer, 2); + Length = 5; + break; + case SUBID_P2P_CHANNEL_LIST: /* 11 */ + *(pDest + 1) = 0; + /*country string . Two ASCII + one more byte */ + *(pDest + 2) = 0x55; + *(pDest + 3) = 0x53; + *(pDest + 4) = 0x04; + InsertP2pChannelList(pAd, *pInBuffer, &Length, (pDest + 5)); + *pDest = Length + 3; + Length += 6; + break; + case SUBID_P2P_OP_CHANNEL: + case SUBID_P2P_LISTEN_CHANNEL: /* 6 */ + *pDest = 5; + *(pDest + 1) = 0; + /*Annex J. 802.11ERVmb_D3/0.pdf */ + *(pDest + 2) = 0x55; + *(pDest + 3) = 0x53; + *(pDest + 4) = 0x04; + *(pDest + 5) = ChannelToClass(*pInBuffer, 1/*COUNTRY_USA*/); + *(pDest + 6) = *pInBuffer; + Length = 8; + break; + case SUBID_P2P_EXT_LISTEN_TIMING: /* 8 */ + *pDest = 4; + *(pDest + 1) = 0; + *((PUSHORT) (pDest + 2)) = (P2P_EXT_LISTEN_PERIOD); + *((PUSHORT) (pDest + 4)) = (P2P_EXT_LISTEN_INTERVAL); + Length = 7; + break; + case SUBID_P2P_MANAGEABILITY: /* 10 */ + break; + case SUBID_P2P_NOA: /* 12 */ + break; + case SUBID_P2P_DEVICE_INFO: /* 13 */ + *pDest = 17 + pP2PCtrl->DeviceNameLen + 4 + (8*pP2PCtrl->DevInfo.SecDevTypList[0]); + *(pDest + 1) = 0; + + RTMPMoveMemory(pDest + 2, pInBuffer, MAC_ADDR_LEN); + /* DEvice Type */ + *((PUSHORT) (pDest + 8)) = cpu2be16(pP2PCtrl->ConfigMethod); + RTMPMoveMemory(pDest + 10, &pP2PCtrl->DevInfo.PriDeviceType[0], 8); + + { + *(pDest + 18) = pP2PCtrl->DevInfo.SecDevTypList[0]; + NdisMoveMemory((pDest + 19), &pP2PCtrl->DevInfo.SecDevTypList[1], (8*(pP2PCtrl->DevInfo.SecDevTypList[0]))); + pDest += (19 + (8*pP2PCtrl->DevInfo.SecDevTypList[0])); + } + + *((PUSHORT) pDest) = cpu2be16(WSC_ID_DEVICE_NAME); + *((PUSHORT) (pDest + 2)) = cpu2be16(pP2PCtrl->DeviceNameLen); + RTMPMoveMemory(pDest + 4, &pP2PCtrl->DeviceName[0], pP2PCtrl->DeviceNameLen); + + Length = 20+ (8*(pP2PCtrl->DevInfo.SecDevTypList[0])) + pP2PCtrl->DeviceNameLen + 4; + break; + case SUBID_P2P_GROUP_INFO: /* 14 */ + break; + case SUBID_P2P_GROUP_ID: /* 15 */ + RTMPMoveMemory(pDest, &pInBuffer[0], (pInBuffer[0] + 2)); + Length = 1 + (pInBuffer[0] + 2); + DBGPRINT(RT_DEBUG_ERROR, (" -----Insert SUBID_P2P_GROUP_ID (Len = %ld) \n", Length)); + break; + case SUBID_P2P_INTERFACE: /* 16 */ + break; + default: + *pDest = 0; + Length = 0; + break; + } + + return Length; +} + +/* + ========================================================================== + Description: + Used to insert P2P Channel list attribute. + + Parameters: + ChannelListLen : output for total length. + pDest : pointer to buffer that should put data to. + Note: + + ========================================================================== + */ +VOID InsertP2pChannelList( + IN PRTMP_ADAPTER pAd, + IN UCHAR OpChannel, + OUT ULONG *ChannelListLen, + OUT PUCHAR pDest) +{ + UCHAR i, pos; + UCHAR LastRegClass = 0xff, CurRegClass; + PUCHAR pLastLenPos; + UCHAR LastNum = 0; + + pLastLenPos = pDest + 1; + pos = 2; + for (i = 0; i < pAd->ChannelListNum; i++) + { + CurRegClass = ChannelToClass(pAd->ChannelList[i].Channel, 1); + /* 0. Decide current regulatory class. 11y */ + /* Insert RegClass if necessary */ + if (LastRegClass == 0xff) + { + /* case 0 : initilize */ + LastRegClass = CurRegClass; + *(pDest) = CurRegClass; + } + else if ((CurRegClass != LastRegClass) && (LastRegClass != 0xff)) + { + /* case 1 : change regulatory class */ + *(pDest + pos) = CurRegClass; + *pLastLenPos = LastNum; + + LastNum = 0; + LastRegClass = CurRegClass; + pLastLenPos = pDest + pos + 1; + pos = pos + 2; + } + + /* Insert */ + *(pDest + pos) = pAd->ChannelList[i].Channel; + LastNum++; + pos++; + + /* Last item. Update Num. */ + if (i == pAd->ChannelListNum -1) + { + *pLastLenPos = LastNum; + } + } + + *ChannelListLen = pos; + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: Channel List ==> output length is %ld \n", __FUNCTION__, *ChannelListLen)); + for (i = 0; i <*ChannelListLen; ) + { + DBGPRINT(RT_DEBUG_TRACE, (": %x %x %x %x %x %x %x %x %x \n", *(pDest+i), *(pDest+i+1), *(pDest+i+2), + *(pDest+i+3), *(pDest+i+4), *(pDest+i+5), *(pDest+i+6), *(pDest+i+7), *(pDest+i+8))); + i = i + 9; + } + +} + +/* + ========================================================================== + Description: + Parse P2P subelement content to fill into the correct output buffer + + Parameters: + return : TRUE if the pSearchAddr is in GroupInfoAttribute. + Note: + + ========================================================================== + */ +BOOLEAN P2pParseGroupInfoAttribute( + IN PRTMP_ADAPTER pAd, + IN UCHAR P2pindex, + IN VOID *Msg, + IN ULONG MsgLen) +{ + PEID_STRUCT pEid; + ULONG Length = 0; + LONG GroupInfoLen; + UCHAR i; + UCHAR idx; + PUCHAR pData; + UCHAR ThisDescLen; + BOOLEAN brc = TRUE; + P2P_CLIENT_INFO_DESC *pClient; + USHORT WscType, WscLen; + ULONG LeftLength; + PP2PEID_STRUCT pP2pEid; + ULONG AttriLen; + UCHAR SmallerP2Pidx; + BOOLEAN bSendP2pEvent = FALSE; + + pEid = (PEID_STRUCT) Msg; + + Length = 0; + 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. */ + /* To check Octet[1] is because Ralink add one byte itself for P2P IE. So the IE content shift one byte afterward. */ + if (RTMPEqualMemory(&pEid->Octet[0], WIFIDIRECT_OUI, 4)) + { + /* To check Octet[5] for first P2PEid */ + /* is because Ralink add one byte itself for P2P IE. So the IE content shift one byte afterward. */ + pP2pEid = (PP2PEID_STRUCT) &pEid->Octet[4]; + AttriLen = pP2pEid->Len[0] + pP2pEid->Len[1] *8; + Length = 0; + while ((Length + 3 + AttriLen) <= pEid->Len) + { + switch(pP2pEid->Eid) + { + case SUBID_P2P_GROUP_INFO: + GroupInfoLen = AttriLen; + pData = &pP2pEid->Octet[0]; + DBGPRINT(RT_DEBUG_INFO, ("SUBID_P2P_GROUP_INFO - Go index=%d\n", P2pindex)); + while(GroupInfoLen > 0) + { + pClient = (P2P_CLIENT_INFO_DESC*)pData; + ThisDescLen = pClient->Length; + if ((ThisDescLen < 23) || (ThisDescLen > GroupInfoLen)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Error parsing P2P IE group info attribute. This Client -%d/%ld\n", ThisDescLen, GroupInfoLen)); + break; + } + + idx = P2pGroupTabSearch(pAd, pClient->DevAddr); + if ((idx < MAX_P2P_GROUP_SIZE) + && (pAd->P2pTable.Client[idx].P2pClientState != P2PSTATE_DISCOVERY_CLIENT) + && (pAd->P2pTable.Client[idx].P2pClientState != P2PSTATE_CLIENT_DISCO_COMMAND)) + { + /* P2P topology changed. Reset the P2P Table and rescan. */ + if (idx > P2pindex) + SmallerP2Pidx = P2pindex + 1; /* don't delete GO */ + else + SmallerP2Pidx = idx; /* this method also delete GO. :( */ + DBGPRINT(RT_DEBUG_TRACE, ("!P2P topology changed[P2pClientState = %d] when parsing P2P IE group info attribute. Delete from index : %d\n", pAd->P2pTable.Client[idx].P2pClientState, SmallerP2Pidx )); + /*P2PPrintP2PEntry(pAd, idx); */ + for (i = (SmallerP2Pidx); i < MAX_P2P_GROUP_SIZE;i++) + { + + if ((pAd->P2pTable.Client[i].P2pClientState == P2PSTATE_PROVISION_COMMAND) + || (pAd->P2pTable.Client[i].P2pClientState == P2PSTATE_CONNECT_COMMAND) + || (pAd->P2pTable.Client[i].P2pClientState > P2PSTATE_DISCOVERY_CLIENT)) + { + DBGPRINT(RT_DEBUG_ERROR, ("!break right away because we have another connect command to continue. update topology is not so important to do right now.\n" )); + break; + } + else + { + P2pGroupTabDelete(pAd, i, pAd->P2pTable.Client[i].addr); + } + /* Don't update this now. */ + if (pAd->P2pTable.ClientNumber == SmallerP2Pidx) + return FALSE; + } + /* because we check idx in following code, */ + /* So need to Search again after topology changed */ + idx = P2pGroupTabSearch(pAd, pClient->DevAddr); + + } + + if ((idx == P2P_NOT_FOUND) && ( pAd->P2pTable.ClientNumber < (MAX_P2P_GROUP_SIZE - 1)) + && (!RTMPEqualMemory(pClient->DevAddr, pAd->P2pCfg.CurrentAddress, MAC_ADDR_LEN))) + { + idx = P2pGroupTabInsert(pAd, pClient->DevAddr, P2PSTATE_DISCOVERY_CLIENT, NULL, 0, 0, 0); + + DBGPRINT(RT_DEBUG_TRACE, ("Insert a P2P Client to P2P table [%d] .\n", idx)); + /* Insert a P2P Client followi ng the GO that we received. Need to delete ALL following client that is already in P2P table. */ + /* Because the number of client that is in the p2p group might be changed. */ + bSendP2pEvent = TRUE; + } + + if (idx < MAX_P2P_GROUP_SIZE) + { + pAd->P2pTable.Client[idx].DevCapability = pClient->Capability; + /* Don't update state when it's in P2PSTATE_CLIENT_DISCO_COMMAND */ + if (pAd->P2pTable.Client[idx].P2pClientState != P2PSTATE_CLIENT_DISCO_COMMAND) + pAd->P2pTable.Client[idx].P2pClientState = P2PSTATE_DISCOVERY_CLIENT; + pAd->P2pTable.Client[idx].ConfigMethod = *((PUSHORT) pClient->ConfigMethod); + pAd->P2pTable.Client[idx].ConfigMethod = be2cpu16(pAd->P2pTable.Client[idx].ConfigMethod); + RTMPMoveMemory(pAd->P2pTable.Client[idx].PrimaryDevType, pClient->PrimaryDevType, P2P_DEVICE_TYPE_LEN); + pAd->P2pTable.Client[idx].NumSecondaryType = pClient->NumSecondaryType; + WscType = cpu2be16(*((PUSHORT) &pClient->Octet[pClient->NumSecondaryType*P2P_DEVICE_TYPE_LEN])); + WscLen = cpu2be16(*((PUSHORT) (&pClient->Octet[2 + pClient->NumSecondaryType*P2P_DEVICE_TYPE_LEN]))); + RTMPMoveMemory(&pAd->P2pTable.Client[idx].DeviceName[0], &pClient->Octet[4+(pClient->NumSecondaryType*P2P_DEVICE_TYPE_LEN)], 32); + if (WscLen <= 32) + pAd->P2pTable.Client[idx].DeviceNameLen = WscLen; + pAd->P2pTable.Client[idx].MyGOIndex = P2pindex; + pAd->P2pTable.Client[idx].DeviceName[pAd->P2pTable.Client[idx].DeviceNameLen] = 0x0; +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT + if (bSendP2pEvent) + P2pSendWirelessEvent(pAd, RT_P2P_DEVICE_FIND, &pAd->P2pTable.Client[idx], NULL); +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ + if (pAd->P2pCfg.ConnectingIndex < MAX_P2P_GROUP_SIZE) + { + if (RTMPEqualMemory(pAd->P2pTable.Client[idx].addr, &pAd->P2pCfg.ConnectingMAC[0], MAC_ADDR_LEN)) + P2pConnectAfterScan(pAd, FALSE, idx); + } + } + GroupInfoLen -= (ThisDescLen + 1); + pData += (ThisDescLen + 1); + }; + break; + default: + break; + + } + Length = Length + 3 + AttriLen; /* Eid[1] + Len[1]+ content[Len] */ + pP2pEid = (PP2PEID_STRUCT)((UCHAR*)pP2pEid + 3 + AttriLen); + AttriLen = pP2pEid->Len[0] + pP2pEid->Len[1] *8; + } + /* We already get what we want. so break. */ + break; + } + LeftLength = LeftLength - pEid->Len - 2; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + return brc; + +} + +/* + ========================================================================== + Description: + Parse P2P NoA subelement content to make appropriate action for NoA schedule. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pParseNoASubElmt( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN UCHAR wcidindex, + IN UINT32 Sequence) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + ULONG Length = 0; + PP2PEID_STRUCT pP2pEid; + ULONG AttriLen; + ULONG LeftLength; + PEID_STRUCT pEid; + BOOLEAN brc; + BOOLEAN 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], WIFIDIRECT_OUI, 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_INFO,("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 = 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 (P2P_TEST_BIT(pAd->P2pCfg.CTWindows, P2P_OPPS_BIT)) + { + DBGPRINT(RT_DEBUG_TRACE,("Beacon and no NoA Attribute! \n")); + P2pStopOpPS(pAd); + } + if ((pAd->MacTab.Content[wcidindex].P2pInfo.NoADesc[0].bValid == TRUE)) + { + DBGPRINT(RT_DEBUG_TRACE,("Beacon and no NoA Attribute!Stop active NoA [%d]\n", Sequence)); + P2pStopNoA(pAd, &pAd->MacTab.Content[wcidindex]); + } + } + +} + + +/* + ========================================================================== + Description: + Parse P2P NoA subelement content to make appropriate action for NoA schedule. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pParseExtListenSubElmt( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT USHORT *ExtListenPeriod, + OUT USHORT *ExtListenInterval) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + ULONG Length = 0; + PP2PEID_STRUCT pP2pEid; + ULONG AttriLen; + /*UCHAR offset; */ + ULONG LeftLength; + PEID_STRUCT pEid; + USHORT ExtTime; + /*BOOLEAN brc; */ + /*PUCHAR pData; */ + + /* 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], WIFIDIRECT_OUI, 4)) + { + /* Get Request content capability */ + pP2pEid = (PP2PEID_STRUCT) &pEid->Octet[4]; + AttriLen = pP2pEid->Len[0] + pP2pEid->Len[1] *8; + Length = 0; + while ((Length + 3 + AttriLen) <= pEid->Len) + { + switch(pP2pEid->Eid) + { + case SUBID_P2P_EXT_LISTEN_TIMING: + if (AttriLen == 4) + { + ExtTime = *(PUSHORT)&pP2pEid->Octet[0]; + DBGPRINT(RT_DEBUG_TRACE, (" - (Ext Listen Period %x = %d) \n", ExtTime, ExtTime)); + if (ExtTime > 0) + pP2PCtrl->ExtListenPeriod = ExtTime; + ExtTime = *(PUSHORT)&pP2pEid->Octet[2]; + DBGPRINT(RT_DEBUG_TRACE, (" - (Ext Listen Interval %x = %d) \n", ExtTime, ExtTime)); + if (ExtTime > 0) + pP2PCtrl->ExtListenInterval = ExtTime; + } + break; + default: + break; + + } + Length = Length + 3 + AttriLen; /* Eid[1] + Len[1]+ content[Len] */ + pP2pEid = (PP2PEID_STRUCT)((UCHAR*)pP2pEid + 3 + AttriLen); + AttriLen = pP2pEid->Len[0] + pP2pEid->Len[1] *8; + } + + } + LeftLength = LeftLength - pEid->Len - 2; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + +} + +/* + ========================================================================== + Description: + Parse P2P subelement content to fill into the correct output buffer + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pParseManageSubElmt( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *pChannel, + OUT UCHAR *pNumOfP2pOtherAttribute, + OUT UCHAR *pTotalNumOfP2pAttribute, + OUT UCHAR *pMamageablity, + OUT UCHAR *pMinorReason) +{ + PP2PEID_STRUCT pP2pEid; + PEID_STRUCT pEid; + ULONG Length; + ULONG AttriLen; + ULONG LeftLength; + + DBGPRINT(RT_DEBUG_TRACE, ("P2pParseManageSubElmt MsgLen = %ld. \n", MsgLen)); + if (pNumOfP2pOtherAttribute != NULL) + *pNumOfP2pOtherAttribute = 0; + + if (pTotalNumOfP2pAttribute != NULL) + *pTotalNumOfP2pAttribute = 0; + + LeftLength = MsgLen; + pEid = (PEID_STRUCT)Msg; + while ((ULONG)(pEid->Len + 2) <= LeftLength) + { + if (pEid->Eid == IE_CHANNEL_USAGE) + { + *pChannel = pEid->Octet[2]; + DBGPRINT(RT_DEBUG_TRACE, ("IE_CHANNEL_USAGE = %x %x %x %x [ch=]%x. \n", pEid->Eid, pEid->Len, pEid->Octet[0], pEid->Octet[1], pEid->Octet[2])); + } + /* might contains P2P IE and WPS IE. So use if else if enough for locate P2P IE. */ + if (RTMPEqualMemory(&pEid->Octet[0], WIFIDIRECT_OUI, 4)) + { + /* Get Request content capability */ + pP2pEid = (PP2PEID_STRUCT) &pEid->Octet[4]; + AttriLen = pP2pEid->Len[0] + pP2pEid->Len[1] *8; + Length = 0; + while ((Length + 3 + AttriLen) <= pEid->Len) + { + switch(pP2pEid->Eid) + { + case SUBID_P2P_MINOR_REASON: + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - Has P2P SUBID_P2P_MINOR_REASON IE Minor Reason = %d.\n", pP2pEid->Octet[0])); + if (pTotalNumOfP2pAttribute != NULL) + *pTotalNumOfP2pAttribute = *pTotalNumOfP2pAttribute+1; + if (pNumOfP2pOtherAttribute != NULL) + *pNumOfP2pOtherAttribute = *pNumOfP2pOtherAttribute+1; + if (pMinorReason != NULL) + *pMinorReason = pP2pEid->Octet[0]; + break; + case SUBID_P2P_MANAGEABILITY: + if (pTotalNumOfP2pAttribute != NULL) + { + *pTotalNumOfP2pAttribute = *pTotalNumOfP2pAttribute+1; + DBGPRINT(RT_DEBUG_TRACE, ("SYNC -Ap Has P2P Manageability IE . Total P2P IE count is %d \n", *pTotalNumOfP2pAttribute)); + } + if (pMamageablity != NULL) + *pMamageablity = pP2pEid->Octet[0]; + break; + default: + if (pTotalNumOfP2pAttribute != NULL) + *pTotalNumOfP2pAttribute = *pTotalNumOfP2pAttribute+1; + if (pNumOfP2pOtherAttribute != NULL) + *pNumOfP2pOtherAttribute = *pNumOfP2pOtherAttribute+1; + break; + + } + Length = Length + 3 + AttriLen; /* Eid[1] + Len[1]+ content[Len] */ + pP2pEid = (PP2PEID_STRUCT)((UCHAR*)pP2pEid + 3 + AttriLen); + AttriLen = pP2pEid->Len[0] + pP2pEid->Len[1] *8; + } + + } + LeftLength = LeftLength - pEid->Len - 2; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + +} + +/* + ========================================================================== + Description: + Parse P2P subelement content to fill into the correct output buffer. May contain multiple P2P IE and WPS IE. + So need while loop to find all IE. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pParseSubElmt( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN BOOLEAN bBeacon, + OUT USHORT *pDpid, + OUT UCHAR *pGroupCap, + OUT UCHAR *pDeviceCap, + OUT UCHAR *pDeviceName, + OUT UCHAR *pDeviceNameLen, + OUT UCHAR *pDevAddr, + OUT UCHAR *pInterFAddr, + OUT UCHAR *pBssidAddr, + OUT UCHAR *pSsidLen, + OUT UCHAR *pSsid, + OUT USHORT *pConfigMethod, + OUT USHORT *pWpsConfigMethod, + OUT UCHAR *pDevType, + OUT UCHAR *pListenChannel, + OUT UCHAR *pOpChannel, + OUT UCHAR *pChannelList, + OUT UCHAR *pIntent, + OUT UCHAR *pStatusCode, + OUT UCHAR *pInviteFlag) +{ + ULONG Length = 0; + PP2PEID_STRUCT pP2pEid; + ULONG AttriLen; + USHORT WscType, WscLen; + UCHAR offset; + PEID_STRUCT pEid; + UCHAR ChannelListLeft = MAX_NUM_OF_CHANNELS; + /*USHORT ExtTime; */ + ULONG AccuP2PIELen; + ULONG AccuIeLen = 0; + + /* Intel sends multiple P2P IE... So I can't give each input a default value.. */ + if (MsgLen == 0) + return; + + pEid = (PEID_STRUCT)Msg; + AccuIeLen = pEid->Len + 2; /* 2: Tag (1 octet) + Len (1 octet) */ + if (RTMPEqualMemory(&pEid->Octet[1], WIFIDIRECT_OUI, 4)) + { + /* + In this case, length is 2 bytes. + */ + AccuIeLen = pEid->Len + pEid->Octet[0]*256 + 3; /* 3: Tag (1 octet) + Len (2 octet) */ + } + + while ((ULONG)(AccuIeLen) <= MsgLen) + { + if (RTMPEqualMemory(&pEid->Octet[0], WPS_OUI, 4)) + { + /*PUCHAR pWscEid = &pEid->Eid;*/ + if (bBeacon == TRUE) + P2PParseWPSIE(&pEid->Octet, (pEid->Len + 2), pDpid, pWpsConfigMethod, pDeviceName, pDeviceNameLen); + else + P2PParseWPSIE(&pEid->Octet, (pEid->Len + 2), pDpid, pWpsConfigMethod, NULL, NULL); + } + /* might contains P2P IE and WPS IE. So use if else if enough for locate P2P IE. */ + else if ((RTMPEqualMemory(&pEid->Octet[0], WIFIDIRECT_OUI, 4)) + ||(RTMPEqualMemory(&pEid->Octet[1], WIFIDIRECT_OUI, 4))) + { + /* Get Request content capability */ + if (RTMPEqualMemory(&pEid->Octet[1], WIFIDIRECT_OUI, 4)) + { + /* + In this case, length is 2 bytes. + */ + pP2pEid = (PP2PEID_STRUCT) &pEid->Octet[5]; + AccuP2PIELen = pEid->Len + pEid->Octet[0]*256; + } + else + { + pP2pEid = (PP2PEID_STRUCT) &pEid->Octet[4]; + AccuP2PIELen = pEid->Len; + } + /* + The value of AccuP2PIELen shall reduce the length of OUI (4). + */ + AccuP2PIELen -= 4; + + AttriLen = pP2pEid->Len[0] + pP2pEid->Len[1] *8; + + Length = 0; + + while ((Length + 3 + AttriLen) <= AccuP2PIELen) + { + switch(pP2pEid->Eid) + { + case SUBID_P2P_EXT_LISTEN_TIMING: + break; + case SUBID_P2P_INVITE_FLAG: + if (pInviteFlag != NULL) + *pInviteFlag = pP2pEid->Octet[0]; + break; + case SUBID_P2P_MANAGEABILITY: + break; + case SUBID_P2P_CAP: + *pGroupCap = pP2pEid->Octet[1]; + *pDeviceCap = pP2pEid->Octet[0]; + break; + case SUBID_P2P_OWNER_INTENT: + if (pIntent != NULL) + *pIntent = pP2pEid->Octet[0]; + break; + case SUBID_P2P_CHANNEL_LIST: + DBGPRINT(RT_DEBUG_INFO, ("SUBID_P2P_CHANNEL_LIST - ( Len %d %d)= %x %x %x %x %x %x..\n", pP2pEid->Len[0], pP2pEid->Len[1], pP2pEid->Octet[0],pP2pEid->Octet[1],pP2pEid->Octet[2],pP2pEid->Octet[3],pP2pEid->Octet[4],pP2pEid->Octet[5])); + if ((pChannelList != NULL) && (ChannelListLeft >= pP2pEid->Octet[4])) + { + ChannelListLeft -= pP2pEid->Octet[4]; + RTMPMoveMemory(pChannelList, &pP2pEid->Octet[5], pP2pEid->Octet[4]); + pChannelList += pP2pEid->Octet[4]; + } + break; + case SUBID_P2P_OP_CHANNEL: + if (pOpChannel != NULL) + *pOpChannel = pP2pEid->Octet[4]; /* Octet[1] is regulatory */ + break; + case SUBID_P2P_LISTEN_CHANNEL: + if (pListenChannel != NULL) + *pListenChannel = pP2pEid->Octet[4]; /* Octet[1] is regulatory */ + break; + case SUBID_P2P_GROUP_BSSID: /* 6 group Bssid */ + if (pBssidAddr != NULL) + RTMPMoveMemory(pBssidAddr, &pP2pEid->Octet[0], MAC_ADDR_LEN); + break; + case SUBID_P2P_INTERFACE_ADDR: /* 9 */ + if (pInterFAddr != NULL) + { + RTMPMoveMemory(pInterFAddr, &pP2pEid->Octet[0], MAC_ADDR_LEN); + } + break; + case SUBID_P2P_DEVICE_ID: + /* Beacon has this field. */ + if (pDevAddr != NULL) + RTMPMoveMemory(pDevAddr, &pP2pEid->Octet[0], MAC_ADDR_LEN); + break; + case SUBID_P2P_GROUP_ID: + if ((pSsid != NULL) && (pP2pEid->Len[0]) > 6 && (pP2pEid->Len[0] <= 38)) + { + RTMPMoveMemory(pSsid, &pP2pEid->Octet[6], (pP2pEid->Len[0] - 6)); + if (pSsidLen != NULL) + { + *pSsidLen = pP2pEid->Len[0] - 6; + DBGPRINT(RT_DEBUG_INFO, (" SUBID_P2P_GROUP_ID - SSID ( Len %d)= %c %c %c %c %c %c %c %c %c.. \n", *pSsidLen, pSsid[0], pSsid[1],pSsid[2],pSsid[3],pSsid[4],pSsid[5],pSsid[6],pSsid[7],pSsid[8])); + } + } + break; + case SUBID_P2P_DEVICE_INFO: + if (pDevAddr != NULL) + RTMPMoveMemory(pDevAddr, &pP2pEid->Octet[0], MAC_ADDR_LEN); + if (pConfigMethod != NULL) + *pConfigMethod = be2cpu16(*(PUSHORT)&pP2pEid->Octet[6]); + if (pDevType != NULL) + RTMPMoveMemory(pDevType, &pP2pEid->Octet[8], 8); + /* Count the DeviceName offset. */ + offset = 17 + pP2pEid->Octet[16] * 8; + WscType = cpu2be16(*((PUSHORT) &pP2pEid->Octet[offset])); + WscLen = cpu2be16(*((PUSHORT) (&pP2pEid->Octet[offset+2]))); + if ((WscType == WSC_ID_DEVICE_NAME) && (WscLen <= 32)) + { + if ((pDeviceName != NULL)) + { + *pDeviceNameLen = (UCHAR)WscLen; + RTMPMoveMemory(pDeviceName, &pP2pEid->Octet[21 + pP2pEid->Octet[16]*8], WscLen); + DBGPRINT(RT_DEBUG_INFO, ("SUBID_P2P_DEVICE_INFO Device Name= %c %c %c %c %c %c \n", pDeviceName[0], pDeviceName[1],pDeviceName[2],pDeviceName[3],pDeviceName[4],pDeviceName[5])); + } + } + + break; + case SUBID_P2P_STATUS: + if (pStatusCode != NULL) + { + *pStatusCode = pP2pEid->Octet[0]; + DBGPRINT(RT_DEBUG_INFO, (" SUBID_P2P_STATUS Eid = %x \n", *pStatusCode)); + } + + break; + case SUBID_P2P_GROUP_INFO: + + break; + case SUBID_P2P_NOA: + break; + case SUBID_P2P_CONFIG_TIMEOUT: + break; + + default: + DBGPRINT(RT_DEBUG_ERROR, (" SUBID_P2P_ unknown Eid = %x \n", pP2pEid->Eid)); + break; + + } + Length = Length + 3 + AttriLen; /* Eid[1] + Len[1]+ content[Len] */ + if (Length >= AccuP2PIELen) + break; + + pP2pEid = (PP2PEID_STRUCT)((UCHAR*)pP2pEid + 3 + AttriLen); + AttriLen = pP2pEid->Len[0] + pP2pEid->Len[1] * 256; + } + + } + /* already reach the last IE. Stop finding next Eid. */ + if (AccuIeLen >= MsgLen) + break; + + /* Forward buffer to next pEid */ + if (RTMPEqualMemory(&pEid->Octet[1], WIFIDIRECT_OUI, 4)) + { + pEid = (PEID_STRUCT)((UCHAR*)pEid + (pEid->Len + pEid->Octet[0]*256 + 3)); + /* We already accumul ate all P2P IE. don't need to search next P2P IE */ + break; + } + else + { + 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[1], WIFIDIRECT_OUI, 4)) + { + AccuIeLen += (pEid->Len + pEid->Octet[0]*256 + 3); + } + else + { + AccuIeLen += (pEid->Len + 2); + } + + } + +} + +/* + ========================================================================== + Description: + The routine that is called when receiving Go Negociation Confirm packet. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pReceGoNegoConfirmAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PP2P_PUBLIC_FRAME pFrame = (PP2P_PUBLIC_FRAME)Elem->Msg; + UCHAR DevType[8] = {0}, DevAddr[6] = {0}, IfAddr[6] = {0}; + UCHAR Channel, OpChannel = 0, Intent, index, Ssid[32]; + UCHAR GroupCap, DeviceCap, DeviceNameLen; + /*ULONG FrameLen; */ + /*ULONG TempLen; */ + UCHAR StatusCode, SsidLen = 0; + /*PEID_STRUCT pEid; */ + /*ULONG LeftLength; */ + USHORT Dpid, ConfigMethod; + UCHAR AllZero[MAC_ADDR_LEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + + + DBGPRINT(RT_DEBUG_ERROR, (" P2P - Recieve Confirm Confirm Confirm. -> From %02x:%02x:%02x:%02x:%02x:%02x.\n", PRINT_MAC(pFrame->p80211Header.Addr2))); + + /* Get Request content capability */ + P2pParseSubElmt(pAd, &pFrame->ElementID, (Elem->MsgLen + 7 - sizeof(P2P_PUBLIC_FRAME)), + FALSE, &Dpid, &GroupCap, &DeviceCap, NULL, &DeviceNameLen, DevAddr, IfAddr, NULL, &SsidLen, (PUCHAR)&Ssid, &ConfigMethod, NULL, DevType, &Channel, &OpChannel, NULL, &Intent, &StatusCode, NULL); + /* confirm doesn't attach device addr in subelement. So copy from SA. */ + RTMPMoveMemory(DevAddr, pFrame->p80211Header.Addr2, MAC_ADDR_LEN); + DBGPRINT(RT_DEBUG_ERROR, (" DevAddr = %02x:%02x:%02x:%02x:%02x:%02x. \n", PRINT_MAC(DevAddr))); + DBGPRINT(RT_DEBUG_ERROR, (" OpChannel = %d. \n", OpChannel)); + + /* Check StatusCode. */ + if (StatusCode != 0) + { + DBGPRINT(RT_DEBUG_ERROR, (" P2P - Ignore Go Negociation Confirm Status Code not Success. \n")); +#ifdef DPA_S + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_GROUP_OWNER_NEGOTIATION_FAIL, NULL, NULL, 0); +#endif /* DPA_S */ + return; + } + else + DBGPRINT(RT_DEBUG_ERROR, (" P2P - Recieve Confirm Confirm Confirm Success. \n")); + +#ifdef DPA_S + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_GROUP_OWNER_NEGOTIATION_COMPLETE, NULL, NULL, 0); +#endif /* DPA_S */ + + /* Check Peer is in the valid state to receive Go Negociation Response. */ + index = P2pGroupTabSearch(pAd, DevAddr); + if (index == P2P_NOT_FOUND) + { + DBGPRINT(RT_DEBUG_ERROR, (" P2P - Ignore Go Negociation Confirm from Unknown device. \n")); + P2PPrintP2PEntry(pAd, 0); + return; + } + else + { + /* Existing peer stay in another state. Doesn't need respond the Go Negociation Request. */ + if ((pP2PCtrl->P2PConnectState == P2P_ANY_IN_FORMATION_AS_GO) && (pAd->P2pTable.Client[index].P2pClientState != P2PSTATE_WAIT_GO_COMFIRM)) + { + DBGPRINT(RT_DEBUG_ERROR, (" P2P - Existing peer stay in another state. = %d. return.\n", pAd->P2pTable.Client[index].P2pClientState)); + return; + } + } + + if (index < MAX_P2P_GROUP_SIZE) + { + PRT_P2P_CLIENT_ENTRY pP2pEntry = &pAd->P2pTable.Client[index]; + if (!NdisEqualMemory(AllZero, IfAddr, MAC_ADDR_LEN)) + RTMPMoveMemory(pP2pEntry->InterfaceAddr, IfAddr, MAC_ADDR_LEN); + DBGPRINT(RT_DEBUG_ERROR, (" pP2pEntry[%d]->rule = %s. GoIntent = %d. My intent is %d. \n", index, decodeMyRule(pP2pEntry->Rule), pP2pEntry->GoIntent, pP2PCtrl->GoIntentIdx)); + /*DBGPRINT(RT_DEBUG_ERROR, ("---->P2P pP2PCtrl->SsidLength = %d. [%x %x %x..]\n", pP2PCtrl->SSIDLen, + pP2PCtrl->SSID[0], pP2PCtrl->SSID[1], pP2PCtrl->SSID[2]));*/ + if (SsidLen > 0) + { + RTMPMoveMemory(pP2pEntry->Ssid, Ssid, 32); + pP2pEntry->SsidLen = SsidLen; + } + + if (pP2PCtrl->P2PConnectState == P2P_ANY_IN_FORMATION_AS_CLIENT) + { + int i; + /* I become Client */ + pP2pEntry->Rule = P2P_IS_GO; + pP2pEntry->P2pClientState = P2PSTATE_GO_WPS; + pP2PCtrl->GroupChannel = OpChannel; + pP2PCtrl->GroupOpChannel = OpChannel; + DBGPRINT(RT_DEBUG_ERROR, (" P2P - I become ENROLLEE!GOGO Go's SsidLen = %d.!!\n", pP2pEntry->SsidLen)); + DBGPRINT(RT_DEBUG_ERROR, (" P2P - I become ENROLLEE!GOGO Go's Ssid[%d] = ", pP2pEntry->SsidLen)); + for (i=0; iSsidLen; i++) + DBGPRINT(RT_DEBUG_ERROR, ("%c ", pP2pEntry->Ssid[i])); + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + DBGPRINT(RT_DEBUG_ERROR, (" P2P - I become ENROLLEE!!GOGO Go's Bssid = %02x:%02x:%02x:%02x:%02x:%02x!!\n", PRINT_MAC(pP2PCtrl->Bssid))); + RTMPZeroMemory(pP2PCtrl->SSID, 32); + RTMPMoveMemory(pP2PCtrl->SSID, pP2pEntry->Ssid, pP2pEntry->SsidLen); + pP2PCtrl->SSIDLen = pP2pEntry->SsidLen; + DBGPRINT(RT_DEBUG_ERROR, (" P2P - I become ENROLLEE!!GOGO Go's SSID[%d] = %s!!\n", pP2PCtrl->SSIDLen, pP2PCtrl->SSID)); + P2pGoNegoDone(pAd, pP2pEntry); + } + else + { + /* I become GO */ + pP2pEntry->Rule = P2P_IS_CLIENT; + pP2PCtrl->GroupOpChannel = pP2PCtrl->GroupChannel; + pP2pEntry->P2pClientState = P2PSTATE_GOT_GO_COMFIRM; + P2pGoNegoDone(pAd, pP2pEntry); + DBGPRINT(RT_DEBUG_ERROR, (" P2P - I become Internal REGISTRA!! REGISTRA. !! GOGOGO\n")); + } + + } + +} +/* + ========================================================================== + Description: + The routine that is called when receiving Go Negociation Response packet. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pReceGoNegoRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PP2P_PUBLIC_FRAME pFrame = (PP2P_PUBLIC_FRAME)&Elem->Msg[0]; + UCHAR DevType[8], Ssid[32], DevAddr[6], IfAddr[6] = {0}, Channel = 0, OpChannel = 0, Intent, index; + UCHAR GroupCap, DeviceCap, DeviceName[32]; + UCHAR SsidLen = 0, DeviceNameLen = 0; + PRT_P2P_CLIENT_ENTRY pP2pEntry; + UCHAR StatusCode = 8; + UCHAR TempIntent; + USHORT Dpid, ConfigMethod; + BOOLEAN Cancelled; + UCHAR AllZero[MAC_ADDR_LEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + + DBGPRINT(RT_DEBUG_ERROR, (" P2P - GOGOGO Recieve Response.Response MsgLen = %ld.\n", Elem->MsgLen)); + if (pP2PCtrl->bP2pReSendTimerRunning) + { + pP2PCtrl->bP2pReSendTimerRunning = FALSE; + RTMPCancelTimer(&pP2PCtrl->P2pReSendTimer, &Cancelled); + } + /* Get Request content capability */ + P2pParseSubElmt(pAd, &pFrame->ElementID, (Elem->MsgLen - LENGTH_802_11 - 8), + FALSE, &Dpid, &GroupCap, &DeviceCap, DeviceName, &DeviceNameLen, + DevAddr, IfAddr, NULL, &SsidLen, Ssid, &ConfigMethod, NULL, DevType, &Channel, &OpChannel, NULL, &TempIntent, &StatusCode, NULL); + + Intent = TempIntent >>1; + DBGPRINT(RT_DEBUG_ERROR, (" Dev Addr = %02x:%02x:%02x:%02x:%02x:%02x. Intent = %d. My Intent = %d. \n", PRINT_MAC(DevAddr), Intent, pP2PCtrl->GoIntentIdx)); + DBGPRINT(RT_DEBUG_ERROR, (" interface addr = %02x:%02x:%02x:%02x:%02x:%02x \n", PRINT_MAC(IfAddr))); + + DBGPRINT(RT_DEBUG_ERROR, (" P2P -StatusCode = %d. PeerIntent = %d . OpChannel = %d. My Intent = %d.\n", StatusCode, Intent, OpChannel, pP2PCtrl->GoIntentIdx)); + + /* Check StatusCode. */ + if (StatusCode == P2PSTATUS_BOTH_INTENT15) + { + pP2PCtrl->P2pCounter.DisableRetryGrpFormCounter = 1200; + DBGPRINT(RT_DEBUG_TRACE, (" P2P - Receive Status Code that both Go Intent Value is 15. = %x \n", StatusCode)); +#ifdef DPA_S + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_GROUP_OWNER_NEGOTIATION_FAIL_INTENT, NULL, NULL, 0); + + if ((pAd->flg_p2p_OpStatusFlags & P2P_FIXED_MODE) == 0) +#endif /* DPA_S */ + P2pLinkDown(pAd, P2P_CONNECT_FAIL); + return; + } + else if ((StatusCode == P2PSTATUS_REJECT_BY_USER) || (StatusCode == P2PSTATUS_PASSED)) + { + DBGPRINT(RT_DEBUG_ERROR, (" P2P -Go Negociation Response Status Code PASSED or being rejected = %d \n", StatusCode)); + index = P2pGroupTabSearch(pAd, DevAddr); + if (index < MAX_P2P_GROUP_SIZE) + { + pAd->P2pTable.Client[index].ReTransmitCnt = 0; + /* since peer return that info unknown, then stop resend GO Negociation Req. */ + /* doesn't need to prepare for retry GO Nego REQ. */ + /*pAd->P2pTable.Client[index].P2pClientState = P2PSTATE_DISCOVERY; */ + /* Test Plan 5.1.22 */ + P2pStopConnectThis(pAd); + /* Reset Peer State as Default. */ + pAd->P2pTable.Client[index].P2pClientState = P2PSTATE_DISCOVERY_CLIENT; + /* Turn Back to My Listen Channel. */ + P2pStopScan(pAd); + /* Back to LISTEN State. */ + MlmeEnqueue(pAd, P2P_DISC_STATE_MACHINE, P2P_DISC_CANL_CMD_EVT, 0, NULL, 0); + DBGPRINT(RT_DEBUG_ERROR, (" P2P - = %s \n", decodeP2PState(pAd->P2pCfg.P2PConnectState))); + } + + Channel = pAd->P2pCfg.ListenChannel; + AsicSwitchChannel(pAd, Channel, FALSE); + AsicLockChannel(pAd, Channel); + + return; + } + else if (StatusCode != 0) + { + DBGPRINT(RT_DEBUG_ERROR, (" P2P - Ignore Go Negociation Response Status Code not Success. = %d \n", StatusCode)); +#ifdef DPA_S + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_GROUP_OWNER_NEGOTIATION_FAIL, NULL, NULL, 0); +#endif /* DPA_S */ + return; + } + + /* Check Peer is in the valid state to receive Go Negociation Response. */ + index = P2pGroupTabSearch(pAd, DevAddr); + if (index == P2P_NOT_FOUND) + { + DBGPRINT(RT_DEBUG_ERROR, (" P2P - Ignore Go Negociation Response from Unknown device. \n")); + return; + } + else + { + + } + + if (index < MAX_P2P_GROUP_SIZE) + { + pP2pEntry = &pAd->P2pTable.Client[index]; + pP2pEntry->ConfigMethod = ConfigMethod; + /* Check peer capability */ + pP2pEntry->ListenChannel = Channel; + if (OpChannel != 0) + pP2pEntry->OpChannel = OpChannel; + pP2pEntry->GoIntent = Intent; + pP2pEntry->StateCount = 0; + pP2pEntry->bValid = FALSE; + pP2pEntry->Dpid = Dpid; + if (!NdisEqualMemory(AllZero, IfAddr, MAC_ADDR_LEN)) + RTMPMoveMemory(pP2pEntry->InterfaceAddr, IfAddr, MAC_ADDR_LEN); + + if (SsidLen > 0) + { + RTMPMoveMemory(pP2pEntry->Ssid, Ssid, SsidLen); + pP2pEntry->SsidLen = SsidLen; + } + P2PPrintP2PEntry(pAd, index); + /* If this peer is provistioned, dpid should follows spec's assignment on page 33 */ + if (P2P_TEST_FLAG(pP2pEntry, P2PFLAG_PROVISIONED)) + { + DBGPRINT(RT_DEBUG_ERROR, ("P2P provisioned -dpid= %x. ConfigMethod = %s.\n", Dpid, decodeConfigMethod(pP2pEntry->ConfigMethod))); + switch(pP2pEntry->ConfigMethod) + { + case WSC_CONFMET_DISPLAY: + if ((Dpid != DEV_PASS_ID_REG) && (Dpid != DEV_PASS_ID_PIN)) + { + DBGPRINT(RT_DEBUG_ERROR, (" P2P -1 Ignore Go Negociation Response with wrong dpid \n")); + return; + } + break; + case WSC_CONFMET_KEYPAD: + if (Dpid != DEV_PASS_ID_USER) + { + DBGPRINT(RT_DEBUG_ERROR, (" P2P -3 Ignore Go Negociation Response with wrong dpid \n")); + return; + } + break; + default: + break; + } + } + P2pSetRule(pAd, index, IfAddr, TempIntent, OpChannel); + + if ((pP2PCtrl->P2PConnectState == P2P_ANY_IN_FORMATION_AS_GO) && (pAd->P2pTable.Client[index].P2pClientState != P2PSTATE_SENT_GO_NEG_REQ)) + { + DBGPRINT(RT_DEBUG_ERROR, (" P2P - Existing peer stay in another state. = %d. \n", pAd->P2pTable.Client[index].P2pClientState)); + return; + } + P2PSendGoNegoConfirm(pAd, pFrame->Token, index, pP2pEntry->addr); + } + +} + +/* + ========================================================================== + Description: + The routine that is called when receiving Go Negociation Request packet. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pReceGoNegoReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PP2P_PUBLIC_FRAME pFrame = (PP2P_PUBLIC_FRAME)Elem->Msg; + UCHAR DevType[8] = {0}, DevAddr[6] = {0}, BssidAddr[6] = {0}; + UCHAR Channel, OpChannel, Intent, index, StatusCode; + UCHAR GroupCap, DeviceCap, DeviceName[32], DeviceNameLen; + ULONG FrameLen; + ULONG TempLen; + UCHAR SsidLen = 0; + RT_P2P_CLIENT_ENTRY *pP2pEntry; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + PUCHAR pDest; +#ifdef DPA_S + UCHAR RspStatus = P2PSTATUS_PASSED; +#else /* DPA_S */ + UCHAR RspStatus = P2PSTATUS_SUCCESS; +#endif /* !DPA_S */ + UCHAR TempIntent; + /*PUCHAR pP2pIE; */ + USHORT Dpid, SentDpid, ConfigMethod; + BOOLEAN bSendEvent = FALSE; + UCHAR AllZero[MAC_ADDR_LEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_ERROR, ("GOGOGOGO P2P - receive Go Neg Request. MsgLen = %ld \n", Elem->MsgLen)); + + RTMPZeroMemory(&DeviceName[0], 32); + pP2pEntry = NULL; + if (IS_P2P_DEVICE_DISCOVERING(pAd)) + P2pStopScan(pAd); + /* Get Request content capability */ + P2pParseSubElmt(pAd, &pFrame->ElementID, (Elem->MsgLen - LENGTH_802_11 - 8), + FALSE, &Dpid, &GroupCap, &DeviceCap, DeviceName, &DeviceNameLen, DevAddr, + BssidAddr, NULL, &SsidLen, NULL, &ConfigMethod, NULL, DevType, &Channel, &OpChannel, NULL, &TempIntent, &StatusCode, NULL); + + Intent = TempIntent >>1; + DBGPRINT(RT_DEBUG_TRACE, (" DevAddr in P2P IE = %02x %02x %02x %02x %02x %02x \n", PRINT_MAC(DevAddr))); + DBGPRINT(RT_DEBUG_TRACE, (" Addr2 = %02x %02x %02x %02x %02x %02x \n", PRINT_MAC(pFrame->p80211Header.Addr2))); + DBGPRINT(RT_DEBUG_TRACE, (" its bssid = %02x %02x %02x %02x %02x %02x \n", PRINT_MAC(BssidAddr))); + DBGPRINT(RT_DEBUG_TRACE, (" Dpid = %x ,%s \n", Dpid, decodeDpid(Dpid))); + + index = P2pGroupTabSearch(pAd, DevAddr); + + if ((index != P2P_NOT_FOUND) && (pP2PCtrl->bP2pReSendTimerRunning)) + { + pP2PCtrl->bP2pReSendTimerRunning = FALSE; + pAd->P2pTable.Client[index].ReTransmitCnt = 0; + RTMPCancelTimer(&pP2PCtrl->P2pReSendTimer, &Cancelled); + } + + DBGPRINT(RT_DEBUG_ERROR, ("P2P -Peer[%d] Intent = %x . OpChannel = %x. My Intent = %x. TempIntent = %x\n", index, Intent, Channel, pP2PCtrl->GoIntentIdx, TempIntent)); + if (index == P2P_NOT_FOUND) + { + DBGPRINT(RT_DEBUG_TRACE, ("P2P -1 insert\n")); + index = P2pGroupTabInsert(pAd, DevAddr, P2PSTATE_DISCOVERY, NULL, 0, DeviceCap, GroupCap); + if (index < MAX_P2P_GROUP_SIZE) + { + pP2PCtrl->PopUpIndex = index; + RTMPMoveMemory(pAd->P2pTable.Client[index].DeviceName, DeviceName, 32); + DBGPRINT(RT_DEBUG_ERROR, ("From a unknown peer. Pop up setting windows. %d\n", pP2PCtrl->PopUpIndex)); + pAd->P2pTable.Client[index].DeviceNameLen = DeviceNameLen; + pAd->P2pTable.Client[index].DeviceName[pAd->P2pTable.Client[index].DeviceNameLen] = 0x0; + + pP2pEntry = &pAd->P2pTable.Client[index]; + pP2pEntry->ConfigMethod = ConfigMethod; + } + bSendEvent = TRUE; + } + + if (index < MAX_P2P_GROUP_SIZE) + { +#ifdef DPA_S + if ((pP2PCtrl->bConfirmByUI) + || (pAd->P2pCfg.bSigmaEnabled == TRUE)) + { + RspStatus = P2PSTATUS_SUCCESS; + } +#endif /* DPA_S */ + pP2pEntry = &pAd->P2pTable.Client[index]; + pP2pEntry->ConfigMethod = ConfigMethod; + if (!NdisEqualMemory(AllZero, BssidAddr, MAC_ADDR_LEN)) + RTMPMoveMemory(pP2pEntry->InterfaceAddr, BssidAddr, MAC_ADDR_LEN); + P2PPrintP2PEntry(pAd, index); + + DBGPRINT(RT_DEBUG_TRACE, ("My P2P Dpid = %x. State = %s. \n", pP2PCtrl->Dpid, decodeP2PClientState(pP2pEntry->P2pClientState))); + if (IS_P2P_PEER_CLIENT_OP(pP2pEntry) || IS_P2P_PEER_WPAPSK(pP2pEntry) || IS_P2P_PEER_PROVISIONING(pP2pEntry)) + { + /* Receive Go Neg Req when this peer's state is operating or doing provisioning. Delete this peer. */ + DBGPRINT(RT_DEBUG_TRACE, (" P2P - Existing peer state is %d. %s,. Delete it.\n", pP2pEntry->P2pClientState, decodeP2PClientState(pP2pEntry->P2pClientState))); + + return; + } + if (pP2pEntry->P2pClientState > P2PSTATE_GO_DONE) + { + DBGPRINT(RT_DEBUG_TRACE, (" P2P - Existing peer state is %d . %s,. return.\n", pP2pEntry->P2pClientState, decodeP2PClientState(pP2pEntry->P2pClientState))); + return; + } + else if (pP2pEntry->P2pClientState == P2PSTATE_SENT_GO_NEG_REQ) + { + if (IsP2pFirstMacSmaller(pP2pEntry->addr, pP2PCtrl->CurrentAddress)) + { + DBGPRINT(RT_DEBUG_TRACE, (" P2P - Dual GO Req. Existing peer state is %s. \n", decodeP2PClientState(pP2pEntry->P2pClientState))); + return; + } + } + if (P2P_GO_ON(pAd)) + { + /* I am GO . Don't need go through GO NEgo process. So return fail. */ + RspStatus = P2PSTATUS_INVALID_PARM; + } + else if (pP2PCtrl->Dpid == DEV_PASS_ID_NOSPEC) + { + /* Test Plan 5.1.21 */ + RspStatus = P2PSTATUS_PASSED; + } +#ifdef DPA_S + else if ((pP2PCtrl->Dpid != Dpid) && (Dpid != DEV_PASS_ID_USER)) + { + /* + Peer is PBC or Display, pass to upper layer daemon to decide do or not. + */ + RspStatus = P2PSTATUS_PASSED; + } +#endif /* DPA_S */ + } + else + return; + + /* Ban Request from the same GoIntent index. */ + if ((Intent == pP2PCtrl->GoIntentIdx) && (Intent == 15)) + { + RspStatus = P2PSTATUS_BOTH_INTENT15; + DBGPRINT(RT_DEBUG_ERROR, (" P2pReceGoNegoReqAction -Receive a peer that has the same Go Intent index as mine. \n")); +#ifdef DPA_S + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_GROUP_OWNER_NEGOTIATION_FAIL_INTENT, NULL, NULL, 0); +#endif /* DPA_S */ + } + + /* allocate and send out ProbeRsp frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR, (" MlmeAllocateMemory fail - . \n")); + return; + } + + pDest = pOutBuffer; + if (RspStatus == P2PSTATUS_SUCCESS) + { + pP2pEntry->P2pClientState = P2PSTATE_WAIT_GO_COMFIRM; + pP2pEntry->StateCount = 0; + pP2pEntry->bValid = FALSE; + pP2pEntry->Dpid = Dpid; + P2pSetRule(pAd, index, BssidAddr, TempIntent, OpChannel); + /* If I am Go, Use my channel to set in the Go Nego Rsp. */ + if (pP2pEntry->Rule == P2P_IS_CLIENT) + OpChannel = pP2PCtrl->GroupChannel; + /* Change beacon content */ + pP2PCtrl->P2pCapability[1] |= (GRPCAP_GROUP_FORMING); + P2pUpdateBssBeacon(pAd, pP2PCtrl->P2pCapability, NULL); +#ifdef DPA_S + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_GROUP_OWNER_NEGOTIATION_REQUEST_RECEIVED, NULL, NULL, 0); +#endif /* DPA_S */ + } + + /*SentDpid = DEV_PASS_ID_PIN; */ + if (P2P_TEST_FLAG(pP2pEntry, P2PFLAG_PROVISIONED)) + { + DBGPRINT(RT_DEBUG_ERROR, (" P2P - Go Negociation Responce to provisioned \n")); + if (pP2PCtrl->ConfigMethod == WSC_CONFMET_DISPLAY) + SentDpid = DEV_PASS_ID_REG; + else if (pP2PCtrl->ConfigMethod == WSC_CONFMET_LABEL) + SentDpid = DEV_PASS_ID_PIN; + else if (pP2PCtrl->ConfigMethod == WSC_CONFMET_KEYPAD) + { + if (pP2PCtrl->bSigmaEnabled == FALSE) + RspStatus = P2PSTATUS_PASSED; + SentDpid = DEV_PASS_ID_USER; + } + else if (pP2PCtrl->ConfigMethod == WSC_CONFMET_PBC) + SentDpid = DEV_PASS_ID_PBC; + } + else + { + if (Dpid == DEV_PASS_ID_PIN) + SentDpid = DEV_PASS_ID_USER; + else if (Dpid == DEV_PASS_ID_USER) + SentDpid = DEV_PASS_ID_PIN; + else if (Dpid == DEV_PASS_ID_REG) + { + if (pP2PCtrl->bSigmaEnabled == FALSE) + RspStatus = P2PSTATUS_PASSED; + SentDpid = DEV_PASS_ID_USER; + } + else if (Dpid == DEV_PASS_ID_PBC) + SentDpid = DEV_PASS_ID_PBC; + else + DBGPRINT(RT_DEBUG_ERROR, ("Peer Go Nego Req DPID = %x\n", Dpid)); + } + + /* Save peer capability */ + pP2pEntry->ListenChannel = Channel; + pP2pEntry->OpChannel = OpChannel; +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT + if (bSendEvent) + P2pSendWirelessEvent(pAd, RT_P2P_DEVICE_FIND, &pAd->P2pTable.Client[index], pFrame->p80211Header.Addr2); + P2pSendWirelessEvent(pAd, RT_P2P_RECV_GO_NEGO_REQ, &pAd->P2pTable.Client[index], pFrame->p80211Header.Addr2); +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ + /*P2P_SetWscRule(pAd, SentDpid); */ + SentDpid = pP2PCtrl->Dpid; + DBGPRINT(RT_DEBUG_TRACE, (" P2P - ReceDpid = %x. SentDpid %x \n", (Dpid), (SentDpid))); + DBGPRINT(RT_DEBUG_TRACE, (" P2P - ReceDpid = %s. SentDpid %s \n", decodeDpid(Dpid), decodeDpid(SentDpid))); + P2PMakeGoNegoRsp(pAd, DevAddr, SentDpid, pFrame->Token, TempIntent, OpChannel, RspStatus, pOutBuffer, &TempLen); + FrameLen = TempLen; + pDest += TempLen; + /* : copy req to rsp first. */ + + DBGPRINT(RT_DEBUG_TRACE, (" P2P - Make Go Negociation Responce Length = %ld.RspStatus = %d \n", FrameLen, RspStatus)); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + + if (RspStatus == P2PSTATUS_PASSED) + { +#ifndef DPA_S + P2P_CMD_STRUCT P2pCmd; + + pP2pEntry->Dpid = Dpid; + P2pSetRule(pAd, index, BssidAddr, TempIntent, OpChannel); + /*UCHAR ClientState = pAd->P2pTable.Client[index].P2pClientState;*/ + COPY_MAC_ADDR(&P2pCmd.Addr[0], pAd->P2pTable.Client[index].addr); + P2pCmd.Idx = index; + if (pP2PCtrl->ConfigMethod != WSC_CONFMET_KEYPAD) + MlmeEnqueue(pAd, P2P_GO_FORM_STATE_MACHINE, P2P_SEND_PASSED_CMD_EVT, sizeof(P2P_CMD_STRUCT), &P2pCmd, 0); +#endif /* !DPA_S */ + +#ifdef DPA_S + /* + Inform upper layer daemon and wait P2P connection command. + */ + P2pSendPeerNegoReqEvent(pAd, + P2P_NOTIF_GROUP_OWNER_NEGOTIATION_REQUEST_RECEIVED, + Dpid, + DevAddr, + RspStatus, + DeviceName, + DeviceNameLen, + pP2pEntry->Ssid, + pP2pEntry->SsidLen, + pP2pEntry->PrimaryDevType[1], + pP2pEntry->ListenChannel); +#endif /* DPA_S */ + } + + /*P2PPrintP2PEntry(pAd, index); */ + /* else ignore this Go Negociation Request because P2P table reach maximum. */ + +} + +/* + ========================================================================== + Description: + The routine that is called when receiving Client Discovery Request Public Action Frame packet. + + Parameters: + Note: + + ========================================================================== + */ +UCHAR DevDiscCnt = 0; +VOID P2pReceDevDisReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PP2P_PUBLIC_FRAME pFrame = (PP2P_PUBLIC_FRAME)Elem->Msg; + UCHAR devAddr[6], BssidAddr[6], OpChannel, StatusCode; + UCHAR GroupCap, DeviceCap, DeviceNameLen; + UCHAR SsidLen; + UCHAR p2pClientIndex; + RT_P2P_CLIENT_ENTRY *pEntry = NULL; + MAC_TABLE_ENTRY *pMacEntry = NULL; + ULONG TotalFrameLen; + + DBGPRINT(RT_DEBUG_ERROR, ("P2P - P2pReceDevDisReqAction = %ld\n", Elem->MsgLen)); + + /* stop scan and lock at Listen Channel. */ + if ((!P2P_GO_ON(pAd)) && (!P2P_CLI_ON(pAd))) + { + P2pStopScan(pAd); + AsicSwitchChannel(pAd, pAd->P2pCfg.ListenChannel, FALSE); + AsicLockChannel(pAd, pAd->P2pCfg.ListenChannel); + } + + /* Get Request content capability */ + P2pParseSubElmt(pAd, &pFrame->ElementID, (Elem->MsgLen - LENGTH_802_11 - 8), + FALSE, NULL, &GroupCap, &DeviceCap, NULL, &DeviceNameLen, devAddr, NULL, + BssidAddr, &SsidLen, NULL, NULL, NULL, NULL, NULL, &OpChannel, NULL, NULL, &StatusCode, NULL); + /* Use TX to decide who is sending. */ + p2pClientIndex = P2pGroupTabSearch(pAd, devAddr); + if (p2pClientIndex < MAX_P2P_GROUP_SIZE) + { + pEntry = &pAd->P2pTable.Client[p2pClientIndex]; + pMacEntry = MacTableLookup(pAd, pEntry->InterfaceAddr); + } + DBGPRINT(RT_DEBUG_ERROR, ("P2P - ask for p2p client[%d] = %02x:%02x:%02x:%02x:%02x:%02x.\n", p2pClientIndex, PRINT_MAC(devAddr))); + + if (((pMacEntry != NULL) && (pEntry != NULL) + && (pEntry->P2pClientState == P2PSTATE_CLIENT_WPS_DONE))) + { + MLME_P2P_ACTION_STRUCT P2PActReq; + + + NdisZeroMemory(&P2PActReq, sizeof(P2PActReq)); + DBGPRINT(RT_DEBUG_TRACE, ("to interface Addr = %02x:%02x:%02x:%02x:%02x:%02x.\n", + PRINT_MAC(pEntry->InterfaceAddr))); + COPY_MAC_ADDR(P2PActReq.Addr, pEntry->InterfaceAddr); + P2PActReq.TabIndex = p2pClientIndex; + MlmeEnqueue(pAd, P2P_ACTION_STATE_MACHINE, MT2_MLME_P2P_GO_DIS_REQ, sizeof(MLME_P2P_ACTION_STRUCT), (PVOID)&P2PActReq, 0); + MlmeHandler(pAd); + DevDiscCnt++; + + /* Device Discvoery Response is delayed until I get the GO Discovery Request Frame's Ack. */ + /* Assume always success. Send back response. */ + RTMPMoveMemory(&pAd->P2pCfg.LatestP2pPublicFrame, pFrame, sizeof(P2P_SAVED_PUBLIC_FRAME)); + OS_WAIT(500); + P2PSendDevDisRsp(pAd, P2PSTATUS_SUCCESS, pAd->P2pCfg.LatestP2pPublicFrame.Token, pAd->P2pCfg.LatestP2pPublicFrame.p80211Header.Addr2, &TotalFrameLen); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s:: P2P -can't find p2p client .Status fail", __FUNCTION__)); + P2PSendDevDisRsp(pAd, P2PSTATUS_IMCOMPA_PARM, pFrame->Token, pFrame->p80211Header.Addr2, &TotalFrameLen); + } +} + + +/* + ========================================================================== + Description: + The routine that is called when receiving Client Discovery Response Public Action Frame packet. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pReceDevDisRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PP2P_PUBLIC_FRAME pFrame = (PP2P_PUBLIC_FRAME)Elem->Msg; + UCHAR DevType[8], DevAddr[6], BssidAddr[6], Channel, OpChannel, index, StatusCode; + UCHAR GroupCap, DeviceCap, DeviceNameLen, TempIntent; + UCHAR SsidLen = 0; + RT_P2P_CLIENT_ENTRY *pP2pEntry; + USHORT Dpid, ConfigMethod; + UCHAR ClientP2PIndex = P2P_NOT_FOUND, i; + + + DBGPRINT(RT_DEBUG_ERROR, ("GOGO P2P - P2pReceDevDisRspAction MsgLen = %ld ", Elem->MsgLen)); + + pP2pEntry = NULL; + + index = P2pGroupTabSearch(pAd, pFrame->p80211Header.Addr2); + if (index == P2P_NOT_FOUND) + return; + + pP2pEntry = &pAd->P2pTable.Client[index]; + + DBGPRINT(RT_DEBUG_ERROR, ("P2pReceDevDisRspAction %s.\n ", decodeP2PClientState(pP2pEntry->P2pClientState))); + if (pP2pEntry->P2pClientState != P2PSTATE_GO_DISCO_COMMAND) + return; + /* Change State back to P2PSTATE_DISCOVERY_GO */ + /* Because P2PSTATE_GO_DISCO_COMMAND is from P2PSTATE_DISCOVERY_GO */ + pP2pEntry->P2pClientState = P2PSTATE_DISCOVERY_GO; + /* Get Request content capability */ + P2pParseSubElmt(pAd, &pFrame->ElementID, (Elem->MsgLen - LENGTH_802_11 - 8), + FALSE, &Dpid, &GroupCap, &DeviceCap, NULL, &DeviceNameLen, DevAddr, + BssidAddr, NULL, &SsidLen, NULL, &ConfigMethod, NULL, DevType, &Channel, &OpChannel, NULL, &TempIntent, &StatusCode, NULL); + + if (StatusCode == P2PSTATUS_SUCCESS) + { + for (i = index; i < MAX_P2P_GROUP_SIZE;i++) + { + if (pAd->P2pTable.Client[i].P2pClientState == P2PSTATE_CLIENT_DISCO_COMMAND) + ClientP2PIndex = i; + } + if (ClientP2PIndex == P2P_NOT_FOUND) + return; + + pAd->P2pTable.Client[ClientP2PIndex].P2pClientState = P2PSTATE_CONNECT_COMMAND; + P2pStartGroupForm(pAd, pAd->P2pTable.Client[ClientP2PIndex].addr, ClientP2PIndex); + } + +} + +/* + ========================================================================== + Description: + The routine that is called when receiving Invitation Request Action Frame packet. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pReceInviteReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PP2P_PUBLIC_FRAME pFrame = (PP2P_PUBLIC_FRAME)Elem->Msg; + UCHAR DevType[8], Ssid[32], DevAddr[6], BssidAddr[6], InfAddr[6], OpChannel, index, StatusCode; + UCHAR GroupCap, DeviceCap, DeviceNameLen; + ULONG FrameLen; + UCHAR ChannelList[MAX_NUM_OF_CHANNELS]; + UCHAR SsidLen, p2pindex; + /*RT_P2P_CLIENT_ENTRY *pP2pEntry;*/ + UCHAR RspStatus = P2PSTATUS_INVALID_PARM; + UCHAR MyRule = P2P_IS_GO; + USHORT ConfigMethod; + UCHAR InviteFlag; + BOOLEAN bReinvoke = FALSE; + + RTMPZeroMemory(ChannelList, MAX_NUM_OF_CHANNELS); + RTMPZeroMemory(Ssid, MAX_LEN_OF_SSID); + /* Get Request content capability */ + P2pParseSubElmt(pAd, &pFrame->ElementID, (Elem->MsgLen - LENGTH_802_11 - 8), + FALSE, NULL, &GroupCap, &DeviceCap, NULL, &DeviceNameLen, DevAddr, InfAddr, + BssidAddr, &SsidLen, Ssid, &ConfigMethod, NULL, DevType, NULL, &OpChannel, ChannelList, NULL, &StatusCode, &InviteFlag); + DBGPRINT(RT_DEBUG_ERROR, ("P2pReceInviteReqAction ==>InviteFlag = %d. %s \n", + InviteFlag, decodeP2PState(pP2PCtrl->P2PConnectState))); + + /* Use TX to decide who is sending. */ + RTMPMoveMemory(DevAddr, pFrame->p80211Header.Addr2, MAC_ADDR_LEN); + + DBGPRINT(RT_DEBUG_ERROR, ("OpChannel = %d. \n", OpChannel)); + DBGPRINT(RT_DEBUG_ERROR, ("BssidAddr = %02x:%02x:%02x:%02x:%02x:%02x \n", PRINT_MAC(BssidAddr))); + DBGPRINT(RT_DEBUG_ERROR, ("DevAddr = %02x:%02x:%02x:%02x:%02x:%02x \n", PRINT_MAC(DevAddr))); + DBGPRINT(RT_DEBUG_ERROR, ("Ssid[%d] = %s. \n", SsidLen, Ssid)); + p2pindex = P2pGroupTabSearch(pAd, DevAddr); + if (p2pindex >= MAX_P2P_GROUP_SIZE) + { + p2pindex = P2pGroupTabInsert(pAd, DevAddr, P2PSTATE_DISCOVERY_GO, Ssid, SsidLen, DeviceCap, GroupCap); + } + index = P2pPerstTabSearch(pAd, DevAddr, BssidAddr, InfAddr); + DBGPRINT(RT_DEBUG_ERROR, ("perst index = %d. p2pindex = %d. \n", index, p2pindex)); + DBGPRINT(RT_DEBUG_ERROR, ("My Dpid = %d. Dpid = %s.\n", pP2PCtrl->Dpid, decodeDpid(pP2PCtrl->Dpid))); + P2PPrintP2PEntry(pAd, p2pindex); + + if (p2pindex == P2P_NOT_FOUND) + return; + + if ((index < MAX_P2P_TABLE_SIZE) && ((InviteFlag & P2P_INVITE_FLAG_REINVOKE) == P2P_INVITE_FLAG_REINVOKE)) + bReinvoke = TRUE; + + /* case 1: Reinvoke case: */ + /* If I have credential and both enable persistent. */ + if (bReinvoke == TRUE) + { + DBGPRINT(RT_DEBUG_ERROR, ("Invite: reinvoke. \n")); + P2pCheckInviteReq(pAd, (pAd->P2pTable.PerstEntry[index].MyRule == P2P_IS_GO), index, ChannelList, BssidAddr, OpChannel, Ssid, SsidLen, &RspStatus); + if (RspStatus == P2PSTATUS_SUCCESS) + { + /* Find peer,. So set Status = success. */ + if (pAd->P2pTable.PerstEntry[index].MyRule == P2P_IS_GO) + { + OpChannel = pP2PCtrl->GroupChannel; + pP2PCtrl->GroupOpChannel = OpChannel; + /* pAd->StaCfg.WscControl.WscAPChannel = OpChannel; */ + DBGPRINT(RT_DEBUG_ERROR, ("Invite: Decide to use OpChannel = %d for group \n", OpChannel)); + p2pindex = P2pGroupTabInsert(pAd, DevAddr, P2PSTATE_CLIENT_WPS, Ssid, SsidLen, DeviceCap, GroupCap); + if (p2pindex < MAX_P2P_GROUP_SIZE) + { + pAd->P2pTable.Client[p2pindex].P2pClientState = P2PSTATE_WAIT_REVOKEINVITE_RSP_ACK; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Invite: reach my limit. Send back RspStatus = %d. \n", RspStatus)); + RspStatus = P2PSTATUS_LIMIT; + } + } + else + { + MyRule = P2P_IS_CLIENT; + pP2PCtrl->GroupChannel = OpChannel; + pP2PCtrl->GroupOpChannel = OpChannel; + /*P2pCopyPerstParmToCfg(pAd, index); */ + DBGPRINT(RT_DEBUG_ERROR, ("Invite: Reinvoke as client for group \n")); + pP2PCtrl->P2PConnectState = P2P_ANY_IN_FORMATION_AS_CLIENT; + /* Update the Client state and SSID. */ + P2pGroupTabInsert(pAd, DevAddr, P2PSTATE_GO_WPS, Ssid, SsidLen, DeviceCap, GroupCap); + /*P2pGoNegoDone(pAd, pAd->PortList[pAd->P2pCfg.PortNumber], &pAd->P2pTable.Client[index]); */ + pP2PCtrl->P2PConnectState = P2P_DO_WPS_ENROLLEE; + /*P2pWpsDone(pAd, DevAddr); */ + COPY_MAC_ADDR(pAd->ApCfg.ApCliTab[0].CfgApCliBssid, pP2PCtrl->Bssid); + } + } + } + /* case 2: abNormal invitation cases:... + */ + else if ((InviteFlag & P2P_INVITE_FLAG_REINVOKE) == P2P_INVITE_FLAG_REINVOKE) + { + /* Peer ask me to reinvoke. But I can't find my record. Send back error code. */ + RspStatus = P2PSTATUS_UNKNOWN_GROUP; + /* + In this case, we need to do P2P GO formation with that P2P peer again. + Therefore we need to update P2pClientState and Rule here for preventing wrong action in P2pReceProvisionReqAction. + */ + pAd->P2pTable.Client[p2pindex].Rule = P2P_IS_DEVICE; + pAd->P2pTable.Client[p2pindex].P2pClientState = P2PSTATE_DISCOVERY; + DBGPRINT(RT_DEBUG_ERROR, ("Invite: Can't find Credential. \n")); + } + /* case 3: Normal invitation cases: + */ + else + { + if (RTMPEqualMemory(BssidAddr, ZERO_MAC_ADDR, MAC_ADDR_LEN)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Invite Req carry allzero Bssid, \n")); + } + else if (IS_P2P_CONNECT_IDLE(pAd) || (pAd->P2pCfg.P2PConnectState == P2P_INVITE)) + { + P2pCheckInviteReqFromExisting(pAd, ChannelList, DevAddr, OpChannel, Ssid, SsidLen, &RspStatus); + DBGPRINT(RT_DEBUG_ERROR, ("Invite: Got invitation from P2P Client . RspStatus = %d \n", RspStatus)); + if (RspStatus == P2PSTATUS_SUCCESS) + { + RTMPZeroMemory(pP2PCtrl->SSID, MAX_LEN_OF_SSID); + RTMPMoveMemory(pP2PCtrl->SSID, Ssid, SsidLen); + RTMPZeroMemory(pAd->P2pTable.Client[p2pindex].Ssid, MAX_LEN_OF_SSID); + RTMPMoveMemory(pAd->P2pTable.Client[p2pindex].Ssid, Ssid, SsidLen); + pAd->P2pTable.Client[p2pindex].SsidLen = SsidLen; + COPY_MAC_ADDR(pP2PCtrl->Bssid, BssidAddr); + COPY_MAC_ADDR(pAd->P2pTable.Client[p2pindex].bssid, BssidAddr); + COPY_MAC_ADDR(pAd->P2pTable.Client[p2pindex].InterfaceAddr, BssidAddr); + pP2PCtrl->SSIDLen = SsidLen; + pP2PCtrl->GroupOpChannel = OpChannel; + pAd->P2pTable.Client[p2pindex].OpChannel = OpChannel; + pAd->P2pTable.Client[p2pindex].ConfigMethod = ConfigMethod; + MyRule = P2P_IS_CLIENT; + } + } + } + +#ifdef DPA_S + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_P2P_INVITE_REQ, NULL, NULL, 0); +#endif /* DPA_S */ + +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT + P2pSendWirelessEvent(pAd, RT_P2P_RECV_INVITE_REQ, &pAd->P2pTable.Client[p2pindex], pFrame->p80211Header.Addr2); +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ + DBGPRINT(RT_DEBUG_ERROR, ("P2p Send Invite Rsp RspStatus = %d. \n", RspStatus)); + P2PMakeInviteRsp(pAd, MyRule, pFrame->Token, pFrame->p80211Header.Addr2, pP2PCtrl->CurrentAddress, &OpChannel, &RspStatus, &FrameLen); + + /* Start Provision */ + if (((bReinvoke == FALSE) && (MyRule == P2P_IS_CLIENT)) && + ((RspStatus == P2PSTATUS_SUCCESS) || ((RspStatus == P2PSTATUS_UNKNOWN_GROUP)))) + { + P2pConnectPrepare(pAd, DevAddr, P2PSTATE_PROVISION_COMMAND); + } + else if ((bReinvoke == TRUE) && (RspStatus == P2PSTATUS_SUCCESS)) + { + PWSC_CTRL pWscControl; + if (MyRule == P2P_IS_CLIENT) + { + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + pObj->ioctl_if_type = INT_P2P; + pWscControl = &pAd->ApCfg.ApCliTab[0].WscControl; + + + /* P2P CLIENT up. */ + Set_P2p_OpMode_Proc(pAd, "2"); + + OS_WAIT(500); + + pObj->ioctl_if_type = INT_APCLI; + NdisMoveMemory(pP2PCtrl->Bssid, pAd->P2pTable.PerstEntry[index].Addr, MAC_ADDR_LEN); + WscWriteConfToApCliCfg(pAd, + pWscControl, + &pAd->P2pTable.PerstEntry[index].Profile, + TRUE); + pObj->ioctl_if_type = INT_P2P; + + if ((pAd->CommonCfg.Channel != OpChannel) && (!INFRA_ON(pAd))) + { + pAd->CommonCfg.Channel = OpChannel; + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + } + /* P2P AP-Client Enable. */ + Set_P2pCli_Enable_Proc(pAd, "1"); + } + else + { + if (!P2P_GO_ON(pAd) && !P2P_CLI_ON(pAd)) + { + pWscControl = &pAd->ApCfg.MBSSID[0].WscControl; + + WscWriteConfToPortCfg(pAd, + pWscControl, + &pAd->P2pTable.PerstEntry[index].Profile, + TRUE); + P2P_GoStop(pAd); + P2P_GoStartUp(pAd, MAIN_MBSSID); + } + } + } +} + +/* + ========================================================================== + Description: + The routine that is called when receiving Invitation Response Action Frame packet. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pReceInviteRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PP2P_PUBLIC_FRAME pFrame = (PP2P_PUBLIC_FRAME)Elem->Msg; + UCHAR DevType[8], devAddr[6], BssidAddr[6] = {0}, OpChannel, index, StatusCode; + UCHAR GroupCap, DeviceCap, DeviceNameLen; + USHORT ConfigMethod; + UCHAR SsidLen, ChannelList[MAX_NUM_OF_CHANNELS]; + PRT_P2P_CLIENT_ENTRY pP2pEntry = NULL; + PWSC_CTRL pWscControl; + + RTMPZeroMemory(ChannelList, MAX_NUM_OF_CHANNELS); + RTMPZeroMemory(BssidAddr, MAC_ADDR_LEN); + /* Get Request content capability */ + P2pParseSubElmt(pAd, &pFrame->ElementID, (Elem->MsgLen - LENGTH_802_11 - 8), + FALSE, NULL, &GroupCap, &DeviceCap, NULL, &DeviceNameLen, devAddr, NULL, + BssidAddr, &SsidLen, NULL, &ConfigMethod, NULL, DevType, NULL, &OpChannel, ChannelList, NULL, &StatusCode, NULL); + + DBGPRINT(RT_DEBUG_TRACE, ("P2pReceInviteRspAction ==> \n")); + DBGPRINT(RT_DEBUG_TRACE, ("TA = %02x:%02x:%02x:%02x:%02x:%02x \n", + PRINT_MAC(pFrame->p80211Header.Addr2))); + + if ((StatusCode == P2PSTATUS_SUCCESS) || (StatusCode == P2PSTATUS_PASSED)) + { + index = P2pPerstTabSearch(pAd, pFrame->p80211Header.Addr2, NULL, NULL); + if ((index < MAX_P2P_TABLE_SIZE) + && (IS_PERSISTENT_ON(pAd))) + { + /* this is a persistent connection. */ + pP2PCtrl->ExtListenInterval = P2P_EXT_LISTEN_INTERVAL; + pP2PCtrl->ExtListenPeriod = P2P_EXT_LISTEN_PERIOD; + /* Find peer,. So set Status = success. */ + if (pAd->P2pTable.PerstEntry[index].MyRule == P2P_IS_GO) + { + OpChannel = pP2PCtrl->GroupChannel; + pP2PCtrl->GroupOpChannel = OpChannel; + P2pCopyPerstParmToCfg(pAd, index); + DBGPRINT(RT_DEBUG_TRACE, ("Decide to use OpChannel = %d for group \n", OpChannel)); + P2pGroupTabInsert(pAd, pFrame->p80211Header.Addr2, P2PSTATE_CLIENT_WPS, NULL, SsidLen, 0, 0); + pP2pEntry = &pAd->P2pTable.Client[index]; + + + pWscControl = &pAd->ApCfg.MBSSID[0].WscControl; + + WscWriteConfToPortCfg(pAd, + pWscControl, + &pAd->P2pTable.PerstEntry[index].Profile, + TRUE); + P2P_GoStop(pAd); + P2P_GoStartUp(pAd, MAIN_MBSSID); + } + else + { + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + pObj->ioctl_if_type = INT_P2P; + pWscControl = &pAd->ApCfg.ApCliTab[0].WscControl; + + pP2PCtrl->GroupChannel = OpChannel; + pP2PCtrl->GroupOpChannel = OpChannel; + + DBGPRINT(RT_DEBUG_ERROR, ("Reinvoke as client for group. OpChannel= %d\n", OpChannel)); + pP2PCtrl->P2PConnectState = P2P_DO_WPS_ENROLLEE; + /* Add some delay to connect GO */ + P2pGroupTabInsert(pAd, pFrame->p80211Header.Addr2, P2PSTATE_REINVOKEINVITE_TILLCONFIGTIME, NULL, SsidLen, 0, 0); + + /* P2P CLIENT up. */ + Set_P2p_OpMode_Proc(pAd, "2"); + + OS_WAIT(500); + + pObj->ioctl_if_type = INT_APCLI; + WscWriteConfToApCliCfg(pAd, + pWscControl, + &pAd->P2pTable.PerstEntry[index].Profile, + TRUE); + pObj->ioctl_if_type = INT_P2P; + + /* P2P AP-Client Enable. */ + Set_P2pCli_Enable_Proc(pAd, "1"); + + } + } + else + { + index = P2pGroupTabSearch(pAd, pFrame->p80211Header.Addr2); + if (index < MAX_P2P_GROUP_SIZE) + { + if (P2P_GO_ON(pAd)) + { + pP2pEntry = &pAd->P2pTable.Client[index]; + pP2pEntry->P2pClientState = P2PSTATE_GOT_GO_COMFIRM; + P2pSetWps(pAd, pP2pEntry); + DBGPRINT(RT_DEBUG_ERROR, ("P2pReceInviteRspAction Success. I am GO. \n")); + } + else if (P2P_CLI_ON(pAd)) + DBGPRINT(RT_DEBUG_ERROR, ("P2pReceInviteRspAction Success. I am client. \n")); + + } + } +#ifdef DPA_S + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_P2P_INVITE_RSP, NULL, NULL, 0); +#endif /* DPA_S */ + } +} + +/* + ========================================================================== + Description: + The routine that is called when receiving provistion request Action Frame packet. + the Element field contains a single WPS IE. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pReceProvisionReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PRT_P2P_CLIENT_ENTRY pP2pEntry = NULL; + PP2P_PUBLIC_FRAME pFrame = (PP2P_PUBLIC_FRAME)Elem->Msg; + USHORT WpsConfigMethod; + ULONG FrameLen; + UCHAR p2pindex; + UCHAR GroupCap, DeviceCap, DevAddr[MAC_ADDR_LEN], BssidAddr[MAC_ADDR_LEN], OpChannel; + UCHAR Ssid[32], SsidLen; + UCHAR DeviceName[32], DeviceNameLen; + UCHAR DevType[8]; + USHORT PeerWscMethod; + BOOLEAN bSendEvent = FALSE; + + DBGPRINT(RT_DEBUG_ERROR, ("P2pRece Provision ReqAction ==> \n")); + if (IS_P2P_DEVICE_DISCOVERING(pAd)) + P2pStopScan(pAd); + RTMPZeroMemory(&DeviceName, 32); + P2pParseSubElmt(pAd, &pFrame->ElementID, (Elem->MsgLen - LENGTH_802_11 - 8), + FALSE, NULL, &GroupCap, &DeviceCap, DeviceName, &DeviceNameLen, DevAddr, NULL, + BssidAddr, &SsidLen, Ssid, NULL, &WpsConfigMethod, DevType, NULL, &OpChannel, NULL, NULL, NULL, NULL); + + DBGPRINT(RT_DEBUG_ERROR, ("P2pRece Provision ReqAction ==>ConfigMethod = %x %s\n", WpsConfigMethod, decodeConfigMethod(WpsConfigMethod))); + + /* + Patch for other vendor that might send multiple config... IN spec, the config method in Provision + Discovery req should carry config method that indicate SINGLE method. + */ + if (WpsConfigMethod == WSC_CONFMET_PBC + && (pP2PCtrl->Dpid == DEV_PASS_ID_PBC)) + { + /* Correct. Keep going. */ + } + else if (WpsConfigMethod == WSC_CONFMET_DISPLAY + && (pP2PCtrl->Dpid == DEV_PASS_ID_REG)) + { + /* Correct. Keep going. */ + } + else if (WpsConfigMethod == WSC_CONFMET_KEYPAD + && (pP2PCtrl->Dpid == DEV_PASS_ID_USER)) + { + /* Correct. Keep going. */ + } + else if (WpsConfigMethod == WSC_CONFMET_LABEL + && (pP2PCtrl->Dpid == DEV_PASS_ID_USER)) + { + /* Correct. Keep going. */ + } + else + { + if (WpsConfigMethod == WSC_CONFMET_PBC) + { + pP2PCtrl->WscMode = WSC_PBC_MODE; + pP2PCtrl->Dpid = DEV_PASS_ID_PBC; + pP2PCtrl->ConfigMethod = WSC_CONFMET_PBC; + } + else if (WpsConfigMethod == WSC_CONFMET_DISPLAY) + { + pP2PCtrl->WscMode = WSC_PIN_MODE; + pP2PCtrl->Dpid = DEV_PASS_ID_REG; + pP2PCtrl->ConfigMethod = WSC_CONFMET_DISPLAY; + } + else if (WpsConfigMethod == WSC_CONFMET_KEYPAD) + { + pP2PCtrl->WscMode = WSC_PIN_MODE; + pP2PCtrl->Dpid = DEV_PASS_ID_USER; + pP2PCtrl->ConfigMethod = WSC_CONFMET_KEYPAD; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("P2pRece Provision ReqAction ==> Ignore this provision request here\n")); + return; + } + } + + /* I only support those 4 method. */ + if ( (WpsConfigMethod == WSC_CONFMET_DISPLAY) + || (WpsConfigMethod == WSC_CONFMET_PBC) + || (WpsConfigMethod == WSC_CONFMET_KEYPAD) + || (WpsConfigMethod == 0x188)) + { + p2pindex = P2pGroupTabSearch(pAd, pFrame->p80211Header.Addr2); + if (p2pindex >= MAX_P2P_GROUP_SIZE) + { + if ((GroupCap & GRPCAP_OWNER) == GRPCAP_OWNER) + { + p2pindex = P2pGroupTabInsert(pAd, pFrame->p80211Header.Addr2, P2PSTATE_DISCOVERY_GO, NULL, 0, DeviceCap, GroupCap); + RTMPZeroMemory(pP2PCtrl->SSID, MAX_LEN_OF_SSID); + RTMPMoveMemory(pP2PCtrl->SSID, Ssid, SsidLen); + RTMPZeroMemory(pAd->P2pTable.Client[p2pindex].Ssid, MAX_LEN_OF_SSID); + RTMPMoveMemory(pAd->P2pTable.Client[p2pindex].Ssid, Ssid, SsidLen); + COPY_MAC_ADDR(pP2PCtrl->Bssid, BssidAddr); + COPY_MAC_ADDR(pAd->P2pTable.Client[p2pindex].bssid, DevAddr); + COPY_MAC_ADDR(pAd->P2pTable.Client[p2pindex].InterfaceAddr, DevAddr); + pAd->P2pTable.Client[p2pindex].SsidLen = SsidLen; + pP2PCtrl->SSIDLen = SsidLen; + } + else + p2pindex = P2pGroupTabInsert(pAd, pFrame->p80211Header.Addr2, P2PSTATE_DISCOVERY, NULL, 0, DeviceCap, GroupCap); + bSendEvent = TRUE; + } + if (p2pindex < MAX_P2P_GROUP_SIZE) + { + pP2pEntry = &pAd->P2pTable.Client[p2pindex]; + if (DeviceNameLen != 0) + { + RTMPMoveMemory(&pAd->P2pTable.Client[p2pindex].DeviceName[0], DeviceName, 32); + pAd->P2pTable.Client[p2pindex].DeviceNameLen = DeviceNameLen; + pAd->P2pTable.Client[p2pindex].DeviceName[pAd->P2pTable.Client[p2pindex].DeviceNameLen] = 0x0; + } + + DBGPRINT(RT_DEBUG_ERROR, ("Update My Config Method to %s (%d)\n", decodeConfigMethod(pP2PCtrl->ConfigMethod ), pP2PCtrl->ConfigMethod)); + if (WpsConfigMethod == WSC_CONFMET_KEYPAD) + { + pP2pEntry->ConfigMethod = WSC_CONFMET_DISPLAY; + pP2pEntry->Dpid = DEV_PASS_ID_REG; + } + else if (WpsConfigMethod == WSC_CONFMET_PBC) + { + pP2pEntry->ConfigMethod = WSC_CONFMET_PBC; + pP2pEntry->Dpid = DEV_PASS_ID_PBC; + } + else + { + pP2pEntry->ConfigMethod = WSC_CONFMET_KEYPAD; + pP2pEntry->Dpid = DEV_PASS_ID_USER; + } + + if ( pP2PCtrl->bProvAutoRsp == TRUE) + { +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT + P2pSendWirelessEvent(pAd, RT_P2P_RECV_PROV_REQ, &pAd->P2pTable.Client[p2pindex], pFrame->p80211Header.Addr2); +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ + /* Update My WPS Configuration. */ + P2P_SetWscRule(pAd, p2pindex, &PeerWscMethod); + /* Update Sigma.ConfigMethod after finished provision procedure. */ + P2P_SET_FLAG(&pAd->P2pTable.Client[p2pindex], P2PFLAG_PROVISIONED); + P2PSendProvisionRsp(pAd, WpsConfigMethod, pFrame->Token, pFrame->p80211Header.Addr2, &FrameLen); + if ((P2P_GO_ON(pAd)) +#ifdef DPA_S + && (pP2PCtrl->bSigmaEnabled == TRUE) +#endif /* DPA_S */ + ) + P2pSetWps(pAd, pP2pEntry); + else if ((pP2pEntry->Rule == P2P_IS_GO) +#ifdef DPA_S + && (pP2PCtrl->bSigmaEnabled == TRUE) +#endif /* DPA_S */ + + ) + { + pP2PCtrl->P2PConnectState = P2P_ANY_IN_FORMATION_AS_CLIENT; + pP2pEntry->P2pClientState = P2PSTATE_GO_WPS; + RTMPMoveMemory(pP2PCtrl->Bssid, pAd->P2pTable.Client[p2pindex].bssid, MAC_ADDR_LEN); + RTMPMoveMemory(pAd->P2pCfg.Bssid, pP2pEntry->bssid, MAC_ADDR_LEN); + RTMPZeroMemory(pP2PCtrl->SSID, 32); + RTMPMoveMemory(pP2PCtrl->SSID, pP2pEntry->Ssid, pP2pEntry->SsidLen); + pP2PCtrl->SSIDLen = pP2pEntry->SsidLen; + pP2PCtrl->GroupOpChannel = pP2pEntry->OpChannel; + P2pGoNegoDone(pAd, pP2pEntry); + } + else + { + pP2pEntry->P2pClientState = P2PSTATE_SENT_PROVISION_REQ; + COPY_MAC_ADDR(pAd->P2pCfg.ConnectingMAC, pP2pEntry->addr); + } + + DBGPRINT(RT_DEBUG_ERROR, ("Accept Provision Req ==>ConfigMethod = %s \n", decodeConfigMethod(WpsConfigMethod))); + } + else + { + if ( pP2PCtrl->P2pProvIndex== P2P_NOT_FOUND ) + { + pP2PCtrl->P2pProvConfigMethod = WpsConfigMethod; + pP2PCtrl->P2pProvToken = pFrame->Token; + RTMPMoveMemory(pP2PCtrl->ConnectingMAC, pFrame->p80211Header.Addr2, MAC_ADDR_LEN); + pP2PCtrl->P2pCounter.UserAccept = 300; + pP2PCtrl->P2pProvIndex = p2pindex; + pP2PCtrl->P2pProvUserNotify = FALSE; +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT + P2pSendWirelessEvent(pAd, RT_P2P_RECV_PROV_REQ, &pAd->P2pTable.Client[p2pindex], pFrame->p80211Header.Addr2); +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ + } + else + { + pP2pEntry->P2pClientState = P2PSTATE_SENT_PROVISION_REQ; + COPY_MAC_ADDR(pAd->P2pCfg.ConnectingMAC, pP2pEntry->addr); + } + } +#ifdef DPA_S + /* + Inform upper layer daemon and wait P2P connection command. + */ + if (pAd->P2pCfg.Dpid == DEV_PASS_ID_PBC) + { + P2pSendPeerNegoReqEvent(pAd, + P2P_NOTIF_PROVISION_DISCOVERY_REQUEST, + DEV_PASS_ID_PBC, + DevAddr, + 1, + pP2pEntry->DeviceName, + pP2pEntry->DeviceNameLen, + pP2pEntry->Ssid, + pP2pEntry->SsidLen, + pP2pEntry->PrimaryDevType[1], + pP2pEntry->ListenChannel); + } + else if (pAd->P2pCfg.Dpid == DEV_PASS_ID_USER) + { + P2pSendPeerNegoReqEvent(pAd, + P2P_NOTIF_PROVISION_DISCOVERY_REQUEST, + DEV_PASS_ID_REG, + DevAddr, + 1, + pP2pEntry->DeviceName, + pP2pEntry->DeviceNameLen, + pP2pEntry->Ssid, + pP2pEntry->SsidLen, + pP2pEntry->PrimaryDevType[1], + pP2pEntry->ListenChannel); + } + else if (pAd->P2pCfg.Dpid == DEV_PASS_ID_REG) + { + P2pSendPeerNegoReqEvent(pAd, + P2P_NOTIF_PROVISION_DISCOVERY_REQUEST, + DEV_PASS_ID_USER, + DevAddr, + 1, + pP2pEntry->DeviceName, + pP2pEntry->DeviceNameLen, + pP2pEntry->Ssid, + pP2pEntry->SsidLen, + pP2pEntry->PrimaryDevType[1], + pP2pEntry->ListenChannel); + } +#endif /* DPA_S */ + } + } + else + /* send null to indicate failure */ + P2PSendProvisionRsp(pAd, 0, pFrame->Token, pFrame->p80211Header.Addr2, &FrameLen); +} + +/* + ========================================================================== + Description: + The routine that is called when receiving provistion request Action Frame packet. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pReceProvisionRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PRT_P2P_CLIENT_ENTRY pP2pEntry; + PP2P_PUBLIC_FRAME pFrame = (PP2P_PUBLIC_FRAME)Elem->Msg; + USHORT ConfigMethod = 0, PeerWscMethod; + /*ULONG FrameLen; */ + UCHAR p2pindex = 0xff; + /*PEID_STRUCT pEid;*/ + PUCHAR Ptr = (PUCHAR) pFrame; + PUCHAR pAddr = NULL; + BOOLEAN Cancelled; + + + p2pindex = P2pGroupTabSearch(pAd, pFrame->p80211Header.Addr2); + if (p2pindex >= MAX_P2P_GROUP_SIZE) + { + DBGPRINT(RT_DEBUG_ERROR, ("P2pReceProvisionRspAction from unknown device ==> \n")); + return; + } + + if (pP2PCtrl->bP2pReSendTimerRunning) + { + pP2PCtrl->bP2pReSendTimerRunning = FALSE; + pAd->P2pTable.Client[p2pindex].ReTransmitCnt = 0; + RTMPCancelTimer(&pP2PCtrl->P2pReSendTimer, &Cancelled); + } + if (pAd->P2pCfg.GoFormCurrentState == P2P_WAIT_GO_FORM_PROV_RSP) + pAd->P2pCfg.GoFormCurrentState = P2P_GO_FORM_IDLE; + P2pStopConnectThis(pAd); + pP2pEntry = &pAd->P2pTable.Client[p2pindex]; + pP2pEntry->bValid = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("P2pReceProvisionRspAction from P2P_Tab[%d] = %02x:%02x:%02x:%02x:%02x:%02x ==> \n", p2pindex, PRINT_MAC(pP2pEntry->addr))); + /* point to OUI2 */ + Ptr += (sizeof(HEADER_802_11) + 2 + 4 + 4); /* Category + Action + OUI + OUIType + SubType + Token + ElementID + Length */ + if (RTMPEqualMemory(Ptr, WPS_OUI, 4)) + { + /* point to Element ID */ + /*Ptr -= 2;*/ + P2PParseWPSIE(Ptr, (pFrame->Length +2), NULL, &ConfigMethod, NULL, NULL); + } + + DBGPRINT(RT_DEBUG_ERROR, ("P2pRece Provision RspAction ==>ConfigMethod = %04x. %s.\n", ConfigMethod, decodeConfigMethod(ConfigMethod))); + DBGPRINT(RT_DEBUG_ERROR, ("pAd->P2pCfg.Dpid = %d. %s.\n", pAd->P2pCfg.Dpid, decodeDpid(pAd->P2pCfg.Dpid))); + /* Set Event to GUI to display PIN digit. */ + if (ConfigMethod == WSC_CONFMET_KEYPAD) + { + DBGPRINT(RT_DEBUG_ERROR, ("P2pKeSetEvent 13. Show PIN now\n")); + } + + if (pP2pEntry->P2pClientState == P2PSTATE_SENT_PROVISION_REQ) + { + if (pP2pEntry->Rule == P2P_IS_GO) + pP2pEntry->P2pClientState = P2PSTATE_DISCOVERY_GO; + else + pP2pEntry->P2pClientState = P2PSTATE_DISCOVERY; + } + + /* p.s spec said null indicates failure. So check ConfigMethod to decide if should go on following actions. */ + if ((ConfigMethod == WSC_CONFMET_DISPLAY) + || (ConfigMethod == WSC_CONFMET_KEYPAD) + || (ConfigMethod == WSC_CONFMET_PBC)) + { + BOOLEAN bAutoGroupFormation = FALSE; + P2P_SET_FLAG(&pAd->P2pTable.Client[p2pindex], P2PFLAG_PROVISIONED); + if (pP2pEntry->ConfigMethod == 0) + bAutoGroupFormation = TRUE; + pP2pEntry->ConfigMethod = ConfigMethod; + P2P_SetWscRule(pAd, p2pindex, &PeerWscMethod); + + + /* Peer use Label or Display. If peer is alreayd GO, I alreayd have WPS information to connect */ + /* So doesn't need to pop up a setting windows. */ + if ((ConfigMethod == WSC_CONFMET_DISPLAY) + && (pP2pEntry->Rule != P2P_IS_GO)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Need setting first. Pop up setting windows. %d\n", pAd->P2pCfg.PopUpIndex)); + pP2pEntry->P2pClientState = P2PSTATE_DISCOVERY; + } + + DBGPRINT(RT_DEBUG_ERROR, ("Peer %d ConfigMethod = %s \n", p2pindex, decodeConfigMethod(ConfigMethod))); + if (pP2pEntry->Rule == P2P_IS_GO) + { + DBGPRINT(RT_DEBUG_TRACE, ("Decide to Join P2p group? when I am %s \n", decodeP2PState(pAd->P2pCfg.P2PConnectState))); + if (pAd->P2pCfg.P2PConnectState == P2P_CONNECT_IDLE) + { + DBGPRINT(RT_DEBUG_TRACE, ("P2p :connecting to GO with Bssid %02x:%02x:%02x:%02x:%02x:%02x. \n", PRINT_MAC(pAd->P2pTable.Client[p2pindex].bssid))); + DBGPRINT(RT_DEBUG_TRACE, ("P2p : its GroupCapability= %x. DevCapability= %x. \n", pAd->P2pTable.Client[p2pindex].GroupCapability, pAd->P2pTable.Client[p2pindex].DevCapability)); + pP2PCtrl->P2PConnectState = P2P_ANY_IN_FORMATION_AS_CLIENT; + pP2pEntry->P2pClientState = P2PSTATE_GO_WPS; + RTMPMoveMemory(pP2PCtrl->Bssid, pAd->P2pTable.Client[p2pindex].bssid, MAC_ADDR_LEN); + RTMPMoveMemory(pAd->P2pCfg.Bssid, pP2pEntry->bssid, MAC_ADDR_LEN); + RTMPZeroMemory(pP2PCtrl->SSID, 32); + RTMPMoveMemory(pP2PCtrl->SSID, pP2pEntry->Ssid, pP2pEntry->SsidLen); + pP2PCtrl->SSIDLen = pP2pEntry->SsidLen; + pP2PCtrl->GroupOpChannel = pP2pEntry->OpChannel; + P2pGoNegoDone(pAd, pP2pEntry); + } + } + else + { + if (P2P_GO_ON(pAd)) + { + /* Set MyRule in P2P GroupFormat */ + P2pSetWps(pAd, pP2pEntry); + DBGPRINT(RT_DEBUG_ERROR, (" P2P - I am Internal REGISTRA!! REGISTRA. !! GOGOGO\n")); + } + else + { + if ((pP2PCtrl->ConfigMethod == WSC_CONFMET_KEYPAD) || + ((pP2PCtrl->ConfigMethod == WSC_CONFMET_DISPLAY) && bAutoGroupFormation == FALSE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s:: recv Provision Rsp. Condif Method = %04x.\n", __FUNCTION__, ConfigMethod)); + } + else + { + /* After Provision Success, start connect command */ + pAddr = &pAd->P2pTable.Client[p2pindex].addr; + P2pConnectPrepare(pAd, pAddr, P2PSTATE_CONNECT_COMMAND); + } + } + } +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT + P2pSendWirelessEvent(pAd, RT_P2P_RECV_PROV_RSP, &pAd->P2pTable.Client[p2pindex], pFrame->p80211Header.Addr2); +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ + +#ifdef DPA_S + if (pAd->P2pCfg.Dpid == DEV_PASS_ID_PBC) + { + P2pSendPeerNegoReqEvent(pAd, + P2P_NOTIF_PROVISION_DISCOVERY_RESPONSE, + DEV_PASS_ID_PBC, + pP2pEntry->addr, + 1, + pP2pEntry->DeviceName, + pP2pEntry->DeviceNameLen, + pP2pEntry->Ssid, + pP2pEntry->SsidLen, + pP2pEntry->PrimaryDevType[1], + pP2pEntry->ListenChannel); + } + else if (pAd->P2pCfg.Dpid == DEV_PASS_ID_USER) + { + P2pSendPeerNegoReqEvent(pAd, + P2P_NOTIF_PROVISION_DISCOVERY_RESPONSE, + DEV_PASS_ID_REG, + pP2pEntry->addr, + 1, + pP2pEntry->DeviceName, + pP2pEntry->DeviceNameLen, + pP2pEntry->Ssid, + pP2pEntry->SsidLen, + pP2pEntry->PrimaryDevType[1], + pP2pEntry->ListenChannel); + } + else if (pAd->P2pCfg.Dpid == DEV_PASS_ID_REG) + { + P2pSendPeerNegoReqEvent(pAd, + P2P_NOTIF_PROVISION_DISCOVERY_RESPONSE, + DEV_PASS_ID_USER, + pP2pEntry->addr, + 1, + pP2pEntry->DeviceName, + pP2pEntry->DeviceNameLen, + pP2pEntry->Ssid, + pP2pEntry->SsidLen, + pP2pEntry->PrimaryDevType[1], + pP2pEntry->ListenChannel); + } +#endif /* DPA_S */ + } + else + { + pP2pEntry->ConfigMethod = 0; +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT + P2pSendWirelessEvent(pAd, RT_P2P_RECV_PROV_RSP, &pAd->P2pTable.Client[p2pindex], pFrame->p80211Header.Addr2); +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ + } +} + + +/* + ========================================================================== + Description: + The routine send additional Probe Request when being in P2P Search State.. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pSendProbeReq( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel) +{ + PUCHAR pOutBuffer; + ULONG FrameLen; + NDIS_STATUS NStatus; + MLME_QUEUE_ELEM *Elem; + + os_alloc_mem(pAd, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM)); + if (Elem) + { + /* allocate and send out ProbeRsp frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + { + os_free_mem(NULL, Elem); + return; + } + + P2PMakeProbe(pAd, Elem, Channel, SUBTYPE_PROBE_REQ, pOutBuffer, &FrameLen); + if (FrameLen > 0) + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + os_free_mem(NULL, Elem); +} + +/* + ========================================================================== + Description: + The routine send Go Negociation Confirm packet . + + Parameters: + Note: + + ========================================================================== + */ +VOID P2PSendGoNegoConfirm( + IN PRTMP_ADAPTER pAd, + IN UCHAR Token, + IN UCHAR idx, + IN PUCHAR Addr1) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + ULONG FrameLen; + ULONG TempLen; + PRT_P2P_CLIENT_ENTRY pP2pEntry; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL, pDest; + UCHAR Channel, StatusCode; + PP2P_PUBLIC_FRAME pFrame; + ULONG P2pLen = 0; + + + /* allocate and send out ProbeRsp frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + pP2pEntry = &pAd->P2pTable.Client[idx]; + pDest = pOutBuffer; + pFrame = (PP2P_PUBLIC_FRAME)pOutBuffer; + P2PMakeGoNegoConfirm(pAd, Addr1, Token, pDest, &TempLen); + FrameLen = TempLen; + pDest += TempLen; + P2pLen = 4; + StatusCode = 0; + TempLen = InsertP2PSubelmtTlv(pAd, SUBID_P2P_STATUS, &StatusCode, pDest); + pDest += TempLen; + FrameLen += TempLen; + P2pLen +=TempLen; + /* : . + */ + TempLen = InsertP2PSubelmtTlv(pAd, SUBID_P2P_CAP, pP2PCtrl->P2pCapability, pDest); + FrameLen += TempLen; + pDest += TempLen; + P2pLen +=TempLen; + /* If I am Go, Use my channel to set in the Go Nego Rsp. */ + if (pP2pEntry->Rule == P2P_IS_CLIENT) + { + if (INFRA_ON(pAd)) + Channel = pAd->CommonCfg.Channel; + else + Channel = pP2PCtrl->GroupChannel; + DBGPRINT(RT_DEBUG_ERROR, ("%s:: P2P - I become Internal REGISTRA!! REGISTRA. !! GOGOGO\n", __FUNCTION__)); + TempLen = InsertP2PSubelmtTlv(pAd, SUBID_P2P_OP_CHANNEL, &Channel, pDest); + FrameLen += TempLen; + pDest += TempLen; + P2pLen +=TempLen; + TempLen = InsertP2PSubelmtTlv(pAd, SUBID_P2P_CHANNEL_LIST, &Channel, pDest); + FrameLen += TempLen; + pDest += TempLen; + P2pLen +=TempLen; + /* Shall include Group ID if I am GO */ + /*NdisMoveMemory(pP2PCtrl->SSID, "DIRECT-qq", 9); */ + /*pP2PCtrl->SSIDLen = 9; */ + RTMPMoveMemory(pP2PCtrl->SSID, &pAd->ApCfg.MBSSID[MAIN_MBSSID].Ssid, pAd->ApCfg.MBSSID[MAIN_MBSSID].SsidLen); + pP2PCtrl->SSIDLen = pAd->ApCfg.MBSSID[MAIN_MBSSID].SsidLen; + { + UCHAR tmpGroupID[40]; // 2 (Length) + 6 (MAC Address ) + 32 (SSID) + tmpGroupID[0] = 6 + pAd->ApCfg.MBSSID[MAIN_MBSSID].SsidLen; + tmpGroupID[1] = 0; + RTMPMoveMemory(&tmpGroupID[2], pP2PCtrl->CurrentAddress, 6); + RTMPMoveMemory(&tmpGroupID[8], &pAd->ApCfg.MBSSID[MAIN_MBSSID].Ssid, pAd->ApCfg.MBSSID[MAIN_MBSSID].SsidLen); + TempLen = InsertP2PSubelmtTlv(pAd, SUBID_P2P_GROUP_ID, &tmpGroupID, pDest); + } + FrameLen += TempLen; + pDest += TempLen; + P2pLen +=TempLen; + + pP2PCtrl->Rule = P2P_IS_GO; + pAd->flg_p2p_OpStatusFlags = P2P_GO_UP; + } + else + { + /* update GO's SSID */ + RTMPZeroMemory(pP2PCtrl->SSID, 32); + RTMPMoveMemory(pP2PCtrl->SSID, pP2pEntry->Ssid, pP2pEntry->SsidLen); + pP2PCtrl->SSIDLen = pP2pEntry->SsidLen; + Channel = pP2pEntry->OpChannel; + TempLen = InsertP2PSubelmtTlv(pAd, SUBID_P2P_OP_CHANNEL, &Channel, pDest); + FrameLen += TempLen; + pDest += TempLen; + P2pLen +=TempLen; + TempLen = InsertP2PSubelmtTlv(pAd, SUBID_P2P_CHANNEL_LIST, &Channel, pDest); + FrameLen += TempLen; + pDest += TempLen; + P2pLen +=TempLen; + DBGPRINT(RT_DEBUG_ERROR, ("%s:: P2P - I become ENROLLEE!! ENROLLEE.!!\n", __FUNCTION__)); +/* + *pDest = SUBID_P2P_CHANNEL_LIST; + pDest++; + *pDest = 6; + *(pDest + 1) = 0; + //country string . Two ASCII + one more byte + *(pDest + 2) = 0x55; + *(pDest + 3) = 0x53; + *(pDest + 4) = 0x20; + *(pDest + 5) = 3; + if (Channel <= 11) + { + *(pDest + 5) = 12; + } + else if (Channel <= 48) + { + *(pDest + 5) = 1; + } + else if (Channel <= 64) + { + *(pDest + 5) = 2; + } + else if (Channel <= 140) + { + *(pDest + 5) = 4; + } + else if (Channel == 165) + { + *(pDest + 5) = 5; + } + *(pDest + 6) = 1; + *(pDest + 7) = Channel; + P2pLen += 9; + FrameLen += 9; + pDest += 9; + + // Insert Channel List Attribute. + *pDest = SUBID_P2P_CHANNEL_LIST; + pDest++; + *pDest = 6; + *(pDest + 1) = 0; +*/ + pP2PCtrl->Rule = P2P_IS_CLIENT; + pAd->flg_p2p_OpStatusFlags = P2P_CLI_UP; + } + DBGPRINT(RT_DEBUG_INFO, ("%s:: P2P - Opchannel is %d \n", __FUNCTION__, Channel)); + + pFrame->Length = (UCHAR)P2pLen; + pP2pEntry->P2pClientState = P2PSTATE_WAIT_GO_COMFIRM_ACK; + /* PFP2P */ + pP2pEntry->StateCount = 0; + pP2pEntry->bValid = FALSE; + /*P2pSetWps(pAd, pPort); */ + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + /* + Wait here for waiting this GO Nego Confirm is sent out; + otherwise this GO Nego Confirm will be sent out in operation channel. + P2pSetWps will do AsicSwitchChannel to operation channel. + */ + OS_WAIT(50); + /* Start WPS. */ + P2pSetWps(pAd, pP2pEntry); + +} + +/* + ========================================================================== + Description: + The routine make Device Discovery Request Action Frame Packet . + + Parameters: + Note: + + ========================================================================== + */ +VOID P2PSendDevDisReq( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr1, + IN PUCHAR Bssid, + IN PUCHAR ClientAddr1, + OUT PULONG pTotalFrameLen) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PP2P_PUBLIC_FRAME pFrame; + ULONG P2pIeLen = 0; + PUCHAR pDest; + ULONG Length; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + UCHAR i; + PUCHAR Ptr = NULL; + + *pTotalFrameLen = 0; + /* allocate and send out ProbeRsp frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + pDest = pOutBuffer; + pFrame = (PP2P_PUBLIC_FRAME)pOutBuffer; + Ptr = (PUCHAR) pFrame; + ActHeaderInit(pAd, &pFrame->p80211Header, Addr1, pP2PCtrl->CurrentAddress, Bssid); + DBGPRINT(RT_DEBUG_TRACE, ("P2P - P2PSendDevDisReq TO %02x:%02x:%02x:%02x:%02x:%02x. \n", PRINT_MAC(Addr1))); + DBGPRINT(RT_DEBUG_TRACE, ("P2P - P2PSendDevDisReq Bssid %02x:%02x:%02x:%02x:%02x:%02x. \n", PRINT_MAC(Bssid))); + pFrame->Category = CATEGORY_PUBLIC; + pFrame->Action = ACTION_WIFI_DIRECT; + /* point to OUI */ + Ptr += (sizeof(HEADER_802_11) + 2); + /*RTMPMoveMemory((pFrame->OUI), P2POUIBYTE, 4);*/ + RTMPMoveMemory(Ptr, P2POUIBYTE, 4); + Ptr += 4; + /* OUISubtype */ + pFrame->Subtype = P2P_DEV_DIS_REQ; + + pP2PCtrl->Token++; + pFrame->Token = pP2PCtrl->Token; + + pFrame->ElementID = IE_VENDOR_SPECIFIC; + /* point to OUI2 */ + Ptr += 4; + /*RTMPMoveMemory((pFrame->OUI2), P2POUIBYTE, 4);*/ + RTMPMoveMemory(Ptr, P2POUIBYTE, 4); + P2pIeLen = 4; + *pTotalFrameLen = 38; + + pDest = &pFrame->Octet[0]; + /* attach subelementID = 3. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_DEVICE_ID, ClientAddr1, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + + pFrame->Length = (UCHAR)P2pIeLen; + pDest = (PUCHAR)pOutBuffer; + for (i = 0; i <*pTotalFrameLen; ) + { + DBGPRINT(RT_DEBUG_TRACE,(": %x %x %x %x %x %x %x %x %x \n", *(pDest+i), *(pDest+i+1), *(pDest+i+2), + *(pDest+i+3), *(pDest+i+4), *(pDest+i+5), *(pDest+i+6), *(pDest+i+7), *(pDest+i+8))); + i = i + 9; + } + MiniportMMRequest(pAd, 0, pOutBuffer, *pTotalFrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("P2P - P2PSendDevice Discovery Req . TO %02x:%02x:%02x:%02x:%02x:%02x. *pTotalFrameLen = %ld. \n", PRINT_MAC(Addr1), *pTotalFrameLen)); + +} + +/* + ========================================================================== + Description: + The routine make Device Discovery Response Action Frame Packet . + Send by GO. So Bssid is my GO addr + + Parameters: + Note: + + ========================================================================== + */ +VOID P2PSendDevDisRsp( + IN PRTMP_ADAPTER pAd, + IN UCHAR RspStatus, + IN UCHAR Token, + IN PUCHAR Addr1, + OUT PULONG pTotalFrameLen) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PP2P_PUBLIC_FRAME pFrame; + ULONG P2pIeLen = 0; + PUCHAR pDest; + ULONG Length; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + PUCHAR Ptr = NULL; + + *pTotalFrameLen = 0; + /* allocate and send out ProbeRsp frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + pDest = pOutBuffer; + pFrame = (PP2P_PUBLIC_FRAME)pOutBuffer; + Ptr = (PUCHAR) pFrame; + ActHeaderInit(pAd, &pFrame->p80211Header, Addr1, pP2PCtrl->CurrentAddress, pP2PCtrl->CurrentAddress); + DBGPRINT(RT_DEBUG_ERROR, ("P2P - P2PSendDevDisRsp TO %02x:%02x:%02x:%02x:%02x:%02x. \n", PRINT_MAC(Addr1))); + pFrame->Category = CATEGORY_PUBLIC; + pFrame->Action = ACTION_WIFI_DIRECT; + /* point to OUI */ + Ptr += (sizeof(HEADER_802_11) + 2); + /*RTMPMoveMemory((pFrame->OUI), P2POUIBYTE, 4);*/ + RTMPMoveMemory(Ptr, P2POUIBYTE, 4); + Ptr += 4; + /* OUISubtype */ + pFrame->Subtype = P2P_DEV_DIS_RSP; + + pFrame->Token = Token; + + pFrame->ElementID = IE_VENDOR_SPECIFIC; + /* point to OUI2 */ + Ptr += 4; + /*RTMPMoveMemory((pFrame->OUI2), P2POUIBYTE, 4);*/ + RTMPMoveMemory(Ptr, P2POUIBYTE, 4); + P2pIeLen = 4; + *pTotalFrameLen = 38; + + pDest = &pFrame->Octet[0]; + /* attach subelementID = 3. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_STATUS, &RspStatus, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + + pFrame->Length = (UCHAR)P2pIeLen; + MiniportMMRequest(pAd, 0, pOutBuffer, *pTotalFrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_ERROR, ("P2P - P2PSendDevice Discovery Response. TO %02x:%02x:%02x:%02x:%02x:%02x. \n", PRINT_MAC(Addr1))); + +} + +/* + ========================================================================== + Description: + The routine make Invitiation Response Action Frame Packet . + + Parameters: + Note: + + ========================================================================== + */ +VOID P2PSendProvisionReq( + IN PRTMP_ADAPTER pAd, + IN USHORT ConfigMethod, + IN UCHAR Token, + IN PUCHAR Addr1, + OUT PULONG pTotalFrameLen) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PP2P_PUBLIC_FRAME pFrame; + ULONG WpsIeLen = 0; + PUCHAR pDest; + PUCHAR pP2PIeLenDest; + ULONG Length; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + PUCHAR Ptr = NULL; + + UCHAR index; + PRT_P2P_CLIENT_ENTRY pP2pEntry; + *pTotalFrameLen = 0; + /* allocate and send out ProbeRsp frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_ERROR, ("P2P - P2PMakeProvisionReq . TO %02x:%02x:%02x:%02x:%02x:%02x. ConfigMethod = %s \n", PRINT_MAC(Addr1), decodeConfigMethod(ConfigMethod))); + pFrame = (PP2P_PUBLIC_FRAME)pOutBuffer; + Ptr = (PUCHAR) pFrame; + ActHeaderInit(pAd, &pFrame->p80211Header, Addr1, pP2PCtrl->CurrentAddress, Addr1); + pFrame->Category = CATEGORY_PUBLIC; + pFrame->Action = ACTION_WIFI_DIRECT; + /* point to OUI */ + Ptr += (sizeof(HEADER_802_11) + 2); + /*RTMPMoveMemory((pFrame->OUI), P2POUIBYTE, 4);*/ + RTMPMoveMemory(Ptr, P2POUIBYTE, 4); + Ptr += 4; + /* OUISubtype */ + pFrame->Subtype = P2P_PROVISION_REQ; + pFrame->Token = Token; + pFrame->ElementID = IE_VENDOR_SPECIFIC; + /* point to OUI2 */ + Ptr += 4; + /*RTMPMoveMemory((pFrame->OUI2), WPS_OUI, 4);*/ + RTMPMoveMemory(Ptr, WPS_OUI, 4); + WpsIeLen = 4; + *pTotalFrameLen = 38; + pDest = pFrame->Octet; + /* attach config method . */ + *((PUSHORT) pDest) = cpu2be16(WSC_ID_CONFIG_METHODS); + *((PUSHORT) (pDest + 2)) = cpu2be16(0x0002); + *((PUSHORT) (pDest + 4)) = cpu2be16(ConfigMethod); /* Label, Display, PBC */ + pDest += 6; + WpsIeLen += 6; + *pTotalFrameLen += 6; + pFrame->Length = (UCHAR)WpsIeLen; + + /* Insert P2P IE===> */ + *pDest = IE_VENDOR_SPECIFIC; + pP2PIeLenDest = (pDest+1); + RTMPMoveMemory(pDest+2, P2POUIBYTE, 4); + WpsIeLen = 4; + pDest += 6; + *pTotalFrameLen += 6; + + /* attach capability */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_CAP, pP2PCtrl->P2pCapability, pDest); + pDest += Length; + WpsIeLen += Length; + *pTotalFrameLen += Length; + /* attach subelementID= 13. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_DEVICE_INFO, pP2PCtrl->CurrentAddress, pDest); + pDest += Length; + WpsIeLen += Length; + *pP2PIeLenDest = (UCHAR)WpsIeLen; + *pTotalFrameLen += Length; + /* attach subelementID = 15 */ + index = P2pGroupTabSearch(pAd, Addr1); + if (index != P2P_NOT_FOUND) + { + UCHAR tmpGroupID[40]; // 2 (Length) + 6 (MAC Address ) + 32 (SSID) + pP2pEntry = &pAd->P2pTable.Client[index]; + DBGPRINT(RT_DEBUG_ERROR, ("P2P - P2PMakeProvisionReq MyRule=%s, PeerRule=%d \n", decodeMyRule(pP2PCtrl->Rule), pP2pEntry->Rule)); + if (pP2pEntry->Rule == P2P_IS_GO) // peer is GO + { + tmpGroupID[0] = 6 + pP2pEntry->SsidLen; + tmpGroupID[1] = 0; + RTMPMoveMemory(&tmpGroupID[2], pP2pEntry->bssid, 6); + RTMPMoveMemory(&tmpGroupID[8], &pP2pEntry->Ssid[0], pP2pEntry->SsidLen); + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_GROUP_ID, &tmpGroupID, pDest); + }else if (P2P_GO_ON(pAd)) //I'm GO + { + tmpGroupID[0] = 6 + pAd->ApCfg.MBSSID[MAIN_MBSSID].SsidLen; + tmpGroupID[1] = 0; + RTMPMoveMemory(&tmpGroupID[2], pP2PCtrl->CurrentAddress, 6); + RTMPMoveMemory(&tmpGroupID[8], &pAd->ApCfg.MBSSID[MAIN_MBSSID].Ssid, pAd->ApCfg.MBSSID[MAIN_MBSSID].SsidLen); + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_GROUP_ID, &tmpGroupID, pDest); + } + else + { + Length =0; + } + } + else + { + Length =0; + } + pDest += Length; + WpsIeLen += Length; + *pP2PIeLenDest = (UCHAR)WpsIeLen; + *pTotalFrameLen += Length; + + pP2PCtrl->bP2pReSendTimerRunning = TRUE; + RTMPSetTimer(&pP2PCtrl->P2pReSendTimer, P2P_TRANSMIT_TIMER); + MiniportMMRequest(pAd, 0, pOutBuffer, *pTotalFrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + +} +/* + ========================================================================== + Description: + The routine make Invitiation Response Action Frame Packet . + + Parameters: + Note: + + ========================================================================== + */ +VOID P2PSendProvisionRsp( + IN PRTMP_ADAPTER pAd, + IN USHORT ConfigMethod, + IN UCHAR Token, + IN PUCHAR Addr1, + OUT PULONG pTotalFrameLen) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PP2P_PUBLIC_FRAME pFrame; + UCHAR WpsIeLen = 0; + PUCHAR pDest; + //ULONG Length; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + PUCHAR Ptr = NULL; + + *pTotalFrameLen = 0; + /* allocate and send out ProbeRsp frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_ERROR, ("P2P - P2PMakeProvisionRsp . TO %02x:%02x:%02x:%02x:%02x:%02x. ConfigMethod = %x(%s) \n", PRINT_MAC(Addr1), ConfigMethod, decodeConfigMethod(ConfigMethod))); + pFrame = (PP2P_PUBLIC_FRAME)pOutBuffer; + Ptr = (PUCHAR) pFrame; + ActHeaderInit(pAd, &pFrame->p80211Header, Addr1, pP2PCtrl->CurrentAddress, Addr1); + pFrame->Category = CATEGORY_PUBLIC; + pFrame->Action = ACTION_WIFI_DIRECT; + /* point to OUI */ + Ptr += (sizeof(HEADER_802_11) + 2); + /*RTMPMoveMemory((pFrame->OUI), P2POUIBYTE, 4); */ + RTMPMoveMemory(Ptr, P2POUIBYTE, 4); + Ptr += 4; + /* OUISubtype */ + pFrame->Subtype = P2P_PROVISION_RSP; + pFrame->Token = Token; + pFrame->ElementID = IE_VENDOR_SPECIFIC; + /* point to OUI2 */ + Ptr += 4; + /*RTMPMoveMemory((pFrame->OUI2), WPS_OUI, 4); */ + RTMPMoveMemory(Ptr, WPS_OUI, 4); + WpsIeLen = 4; + *pTotalFrameLen = 38; + pDest = pFrame->Octet; + if (ConfigMethod > 0) + { + /* attach wsc version */ + *((PUSHORT) pDest) = cpu2be16(WSC_ID_VERSION); + *((PUSHORT) (pDest + 2)) = cpu2be16(0x0001); + *(pDest + 4) = WSC_VERSION; /* TODO: WPS2.0 ?? */ + pDest += 5; + WpsIeLen += 5; + *pTotalFrameLen += 5; + + /* attach config method . */ + *((PUSHORT) pDest) = cpu2be16(WSC_ID_CONFIG_METHODS); + *((PUSHORT) (pDest + 2)) = cpu2be16(0x0002); + *((PUSHORT) (pDest + 4)) = cpu2be16(ConfigMethod); /* Label, Display, PBC */ + pDest += 6; + WpsIeLen += 6; + *pTotalFrameLen += 6; + } + pFrame->Length = WpsIeLen; + pP2PCtrl->bP2pReSendTimerRunning = TRUE; + RTMPSetTimer(&pP2PCtrl->P2pReSendTimer, /*P2P_TRANSMIT_TIMER*/ 1000); + MiniportMMRequest(pAd, 0, pOutBuffer, *pTotalFrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + +} + +/* + ========================================================================== + Description: + The routine prepares Go Negociation Confirm packet . + + Parameters: + Note: + + ========================================================================== + */ +VOID P2PMakeGoNegoConfirm( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr1, + IN UCHAR Token, + IN PUCHAR pOutBuffer, + OUT PULONG pTotalFrameLen) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PP2P_PUBLIC_FRAME pFrame = (PP2P_PUBLIC_FRAME)pOutBuffer; + /*PUCHAR pDest; */ + /*ULONG Length; */ + PUCHAR Ptr = (PUCHAR) pFrame; + + ActHeaderInit(pAd, (PHEADER_802_11)pOutBuffer, Addr1, pP2PCtrl->CurrentAddress, pP2PCtrl->PortCfg.Bssid); + + pFrame->Category = CATEGORY_PUBLIC; + pFrame->Action = ACTION_WIFI_DIRECT; + /* point to OUI */ + Ptr += (sizeof(HEADER_802_11) + 2); + /*RTMPMoveMemory((pFrame->OUI), P2POUIBYTE, 4); */ + RTMPMoveMemory(Ptr, P2POUIBYTE, 4); + Ptr += 4; + /* OUISubtype */ + pFrame->Subtype = GO_NEGOCIATION_CONFIRM; + pFrame->Token = Token; + pFrame->ElementID = IE_VENDOR_SPECIFIC; + /* point to OUI2 */ + Ptr += 4; + /*RTMPMoveMemory((pFrame->Octet), P2POUIBYTE, 4); */ + RTMPMoveMemory(Ptr, P2POUIBYTE, 4); + + *pTotalFrameLen = 38; + +} + + +/* + ========================================================================== + Description: + The routine make Go Negociation Response packet . + + Parameters: + TempIntent is directly from Go Req. Still need to parse this. + Note: + + ========================================================================== + */ +VOID P2PMakeGoNegoRsp( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr1, + IN USHORT SentDpid, + IN UCHAR Token, + IN UCHAR TempIntent, + IN UCHAR Channel, + IN UCHAR Status, + IN PUCHAR pOutBuffer, + OUT PULONG pTotalFrameLen) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PP2P_PUBLIC_FRAME pFrame = (PP2P_PUBLIC_FRAME)pOutBuffer; + PUCHAR pDest; + ULONG Length; + /*UCHAR P2PCap[2]; */ + ULONG P2pIeLen = 0; + UCHAR RealIntent; + UCHAR WscIEFixed[] = {0xdd, 0x0f, 0x00, 0x50, 0xf2, 0x04}; /* length will modify later */ + PUCHAR Ptr = (PUCHAR) pFrame; + + ActHeaderInit(pAd, &pFrame->p80211Header, Addr1, pP2PCtrl->CurrentAddress, Addr1); + + pFrame->Category = CATEGORY_PUBLIC; + pFrame->Action = ACTION_WIFI_DIRECT; + /* pointer to OUI */ + Ptr += (sizeof(HEADER_802_11) + 2); + /*RTMPMoveMemory((pFrame->OUI), P2POUIBYTE, 4);*/ + RTMPMoveMemory(Ptr, P2POUIBYTE, 4); + Ptr +=4; + /* OUISubtype */ + pFrame->Subtype = GO_NEGOCIATION_RSP; + pFrame->Token = Token; + pFrame->ElementID = IE_VENDOR_SPECIFIC; + /* point to OUI2 */ + Ptr += 4; + /*RTMPMoveMemory((pFrame->Octet), P2POUIBYTE, 4);*/ + RTMPMoveMemory(Ptr, P2POUIBYTE, 4); + P2pIeLen = 4; + *pTotalFrameLen = sizeof(P2P_PUBLIC_FRAME) - 1; + pDest = pFrame->Octet; + + /* Start attach subelement. */ + /* attach subelementID= 0. */ + DBGPRINT(RT_DEBUG_ERROR, ("%s: P2P - Status %d \n", __FUNCTION__, Status)); + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_STATUS, &Status, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + /* attach subelementID= 2. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_CAP, pP2PCtrl->P2pCapability, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + + /* attach subelementID= 4. */ + RealIntent = TempIntent>>1; + RealIntent = (pP2PCtrl->GoIntentIdx << 1) + ((TempIntent & 0x1) == 1 ? 0 : 1); + + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_OWNER_INTENT, &RealIntent, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + /* attach subelementID= 4. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_CONFIG_TIMEOUT, &pP2PCtrl->ConfigTimeout[0], pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + /* attach subelementID= 17. */ + if (INFRA_ON(pAd)) + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_OP_CHANNEL, &pAd->CommonCfg.Channel, pDest); + else + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_OP_CHANNEL, &pP2PCtrl->GroupChannel, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + /* attach subelementID= 9. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_INTERFACE_ADDR, pP2PCtrl->CurrentAddress, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + /* attach channel List= 11. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_CHANNEL_LIST, &pP2PCtrl->GroupChannel, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + /* attach subelementID= 13. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_DEVICE_INFO, pP2PCtrl->CurrentAddress, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + + /* attach subelementID= 15. */ + if (pP2PCtrl->P2PConnectState == P2P_ANY_IN_FORMATION_AS_GO) + { + UCHAR tmpGroupID[40]; // 2 (Length) + 6 (MAC Address ) + 32 (SSID) + tmpGroupID[0] = 6 + pAd->ApCfg.MBSSID[MAIN_MBSSID].SsidLen; + tmpGroupID[1] = 0; + RTMPMoveMemory(&tmpGroupID[2], pP2PCtrl->CurrentAddress, 6); + RTMPMoveMemory(&tmpGroupID[8], &pAd->ApCfg.MBSSID[MAIN_MBSSID].Ssid, pAd->ApCfg.MBSSID[MAIN_MBSSID].SsidLen); + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_GROUP_ID, &tmpGroupID, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + } + + pFrame->Length = (UCHAR)P2pIeLen; + /* 0. WSC fixed IE */ + RTMPMoveMemory(pDest, &WscIEFixed[0], 6); + pDest += 6; + *pTotalFrameLen += 6; + /* 1. Version */ + *((PUSHORT) pDest) = cpu2be16(WSC_ID_VERSION); + *((PUSHORT) (pDest + 2)) = cpu2be16(0x0001); + *(pDest + 4) = WSC_VERSION; + pDest += 5; + *pTotalFrameLen += 5; + /* 9. Device password ID. According to Table.1 in P2P Spec. */ + + *((PUSHORT) pDest) = cpu2be16(WSC_ID_DEVICE_PWD_ID); + *((PUSHORT) (pDest + 2)) = cpu2be16(0x0002); + *((PUSHORT) (pDest + 4)) = cpu2be16(SentDpid); + pDest += 6; + *pTotalFrameLen += 6; + +} + + +/* + ========================================================================== + Description: + The routine make Go Negociation Request packet . + + Parameters: + Note: + + ========================================================================== + */ +VOID P2PMakeGoNegoReq( + IN PRTMP_ADAPTER pAd, + IN UCHAR index, + IN PUCHAR Addr1, + IN PUCHAR pOutBuffer, + OUT PULONG pTotalFrameLen) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PP2P_PUBLIC_FRAME pFrame = (PP2P_PUBLIC_FRAME)pOutBuffer; + PUCHAR pDest; + ULONG Length; + ULONG P2pIeLen = 0; + UCHAR FilledIntent; + UCHAR RandomB; + UCHAR WscIEFixed[] = {0xdd, 0x0f, 0x00, 0x50, 0xf2, 0x04}; /* length will modify later */ + PUCHAR pWscIeLen; + /*UCHAR ChannelList; */ + USHORT SentDpid; + PUCHAR Ptr = (PUCHAR) pFrame; + + if (index >= MAX_P2P_GROUP_SIZE) + { + return; + } + *pTotalFrameLen = 0; + RTMPMoveMemory(pP2PCtrl->PortCfg.Bssid, Addr1, 6); + ActHeaderInit(pAd, &pFrame->p80211Header, Addr1, pP2PCtrl->CurrentAddress, Addr1); + + DBGPRINT(RT_DEBUG_ERROR, (" %s - P2PMakeGoNegoReq TO %02x:%02x:%02x:%02x:%02x:%02x. \n", __FUNCTION__, Addr1[0], Addr1[1], Addr1[2],Addr1[3],Addr1[4],Addr1[5])); + + pFrame->Category = CATEGORY_PUBLIC; + pFrame->Action = ACTION_WIFI_DIRECT; + /* point to OUI */ + Ptr += (sizeof(HEADER_802_11) + 2); + /*RTMPMoveMemory((pFrame->OUI), P2POUIBYTE, 4);*/ + RTMPMoveMemory(Ptr, P2POUIBYTE, 4); + Ptr += 4; + /* OUISubtype */ + pFrame->Subtype = GO_NEGOCIATION_REQ; + pFrame->Token = 1; + pFrame->ElementID = IE_VENDOR_SPECIFIC; + /* point to OUI2 */ + Ptr += 4; + /*RTMPMoveMemory((pFrame->OUI2), P2POUIBYTE, 4);*/ + RTMPMoveMemory(Ptr, P2POUIBYTE, 4); + P2pIeLen = 4; + *pTotalFrameLen = 38; + pDest = pFrame->Octet; + + /* Start attach subelement. */ + /* attach subelementID= 2. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_CAP, pP2PCtrl->P2pCapability, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + /* attach subelementID= 4. */ + FilledIntent = pP2PCtrl->GoIntentIdx<<1; + RandomB = RandomByte(pAd); + /* If Intent is not 15, set tie breaker bit to 1 randomly. */ + if (((RandomB %2) == 0) && (pP2PCtrl->GoIntentIdx != 15)) + FilledIntent |= 1; + + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_OWNER_INTENT, &FilledIntent, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + /* attach subelementID= 7. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_CONFIG_TIMEOUT, &pP2PCtrl->ConfigTimeout[0], pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_LISTEN_CHANNEL, &pP2PCtrl->ListenChannel, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + + /* attach subelementID= 9. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_INTERFACE_ADDR, pP2PCtrl->CurrentAddress, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + /* attach channel List= 11. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_CHANNEL_LIST, &pP2PCtrl->GroupChannel, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + /* attach subelementID= 13. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_DEVICE_INFO, pP2PCtrl->CurrentAddress, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + + /* attach subelementID= 17. */ + if (INFRA_ON(pAd)) + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_OP_CHANNEL, &pAd->CommonCfg.Channel, pDest); + else + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_OP_CHANNEL, &pP2PCtrl->GroupChannel, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + + if (IS_P2P_SUPPORT_EXT_LISTEN(pAd)) + { + /* attach subelementID= 17. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_EXT_LISTEN_TIMING, NULL, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + } + + pFrame->Length = (UCHAR)P2pIeLen; + + /* 0. WSC fixed IE */ + + RTMPMoveMemory(pDest, &WscIEFixed[0], 6); + pWscIeLen = pDest + 1; + pDest += 6; + *pTotalFrameLen += 6; + *pWscIeLen = 4; + /* 1. Version */ + *((PUSHORT) pDest) = cpu2be16(WSC_ID_VERSION); + *((PUSHORT) (pDest + 2)) = cpu2be16(0x0001); + *(pDest + 4) = WSC_VERSION; + pDest += 5; + *pTotalFrameLen += 5; + *pWscIeLen += 5; + /* 9. Device password ID */ + *((PUSHORT) pDest) = cpu2be16(WSC_ID_DEVICE_PWD_ID); + *((PUSHORT) (pDest + 2)) = cpu2be16(0x0002); + SentDpid = pP2PCtrl->Dpid; + if (P2P_TEST_FLAG(&pAd->P2pTable.Client[index], P2PFLAG_PROVISIONED)) + { + switch(pAd->P2pTable.Client[index].ConfigMethod) + { + case WSC_CONFMET_DISPLAY: + SentDpid = DEV_PASS_ID_USER; + break; + case WSC_CONFMET_PBC: + SentDpid = DEV_PASS_ID_PBC; + break; + case WSC_CONFMET_KEYPAD: + SentDpid = DEV_PASS_ID_REG; + default : + SentDpid = DEV_PASS_ID_PIN; + break; + } + } + *((PUSHORT) (pDest + 4)) = cpu2be16(SentDpid); + pDest += 6; + *pTotalFrameLen += 6; + *pWscIeLen += 6; + +} + +/* + ========================================================================== + Description: + The routine make Invitiation Request Action Frame Packet . + + Parameters: + Note: + + ========================================================================== + */ +VOID P2PMakeInviteReq( + IN PRTMP_ADAPTER pAd, + IN UCHAR MyRule, + IN UCHAR InviteFlag, + IN PUCHAR Addr1, + IN PUCHAR Bssid, + OUT PULONG pTotalFrameLen) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PP2P_PUBLIC_FRAME pFrame; + ULONG P2pIeLen = 0; + PUCHAR pDest; + ULONG Length; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + PUCHAR Ptr = NULL; + + *pTotalFrameLen = 0; + /* allocate and send out ProbeRsp frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + pFrame = (PP2P_PUBLIC_FRAME)pOutBuffer; + Ptr = (PUCHAR) pFrame; + ActHeaderInit(pAd, &pFrame->p80211Header, Addr1, pP2PCtrl->CurrentAddress, Bssid); + DBGPRINT(RT_DEBUG_ERROR, ("P2P - P2PMakeInviteReq TO %02x:%02x:%02x:%02x:%02x:%02x. \n", PRINT_MAC(Addr1))); + pFrame->Category = CATEGORY_PUBLIC; + pFrame->Action = ACTION_WIFI_DIRECT; + /* point to OUI */ + Ptr += (sizeof(HEADER_802_11) + 2); + /*RTMPMoveMemory((pFrame->OUI), P2POUIBYTE, 4);*/ + RTMPMoveMemory(Ptr, P2POUIBYTE, 4); + Ptr += 4; + /* OUISubtype */ + pFrame->Subtype = P2P_INVITE_REQ; + + pP2PCtrl->Token++; + pFrame->Token = pP2PCtrl->Token; + + pFrame->ElementID = IE_VENDOR_SPECIFIC; + /* point to OUI2 */ + Ptr += 4; + /*RTMPMoveMemory((pFrame->OUI2), P2POUIBYTE, 4);*/ + RTMPMoveMemory(Ptr, P2POUIBYTE, 4); + P2pIeLen = 4; + *pTotalFrameLen = 38; + pDest = pFrame->Octet; + /* attach subelementID= 5. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_CONFIG_TIMEOUT, &pP2PCtrl->ConfigTimeout[0], pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + /* attach subelementID= 11. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_INVITE_FLAG, &InviteFlag, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + /* attach subelementID= 17. */ + if (MyRule == P2P_IS_GO) + { + if (INFRA_ON(pAd)) + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_OP_CHANNEL, &pAd->CommonCfg.Channel, pDest); + else + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_OP_CHANNEL, &pP2PCtrl->GroupOpChannel, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + } + /* attach subelementID= 7. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_GROUP_BSSID, &pP2PCtrl->CurrentAddress[0], pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + /* attach subelementID= 11. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_CHANNEL_LIST, &pP2PCtrl->GroupOpChannel, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + /* attach subelementID= 11. */ + { + UCHAR tmpGroupID[40]; // 2 (Length) + 6 (MAC Address ) + 32 (SSID) + tmpGroupID[0] = 6 + pP2PCtrl->SSIDLen; + tmpGroupID[1] = 0; + RTMPMoveMemory(&tmpGroupID[2], pP2PCtrl->CurrentAddress, 6); + RTMPMoveMemory(&tmpGroupID[8], &pP2PCtrl->SSID[0], pP2PCtrl->SSIDLen); + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_GROUP_ID, &tmpGroupID, pDest); + } + + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + /* attach subelementID= 11. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_DEVICE_INFO, pP2PCtrl->CurrentAddress, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + + + pFrame->Length = (UCHAR)P2pIeLen; + MiniportMMRequest(pAd, 0, pOutBuffer, *pTotalFrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + +} + +/* + ========================================================================== + Description: + The routine make Invitiation Response Action Frame Packet . + + Parameters: + Note: + + ========================================================================== + */ +VOID P2PMakeInviteRsp( + IN PRTMP_ADAPTER pAd, + IN UCHAR MyRule, + IN UCHAR Token, + IN PUCHAR Addr1, + IN PUCHAR Bssid, + IN PUCHAR OpChannel, + IN PUCHAR Status, + OUT PULONG pTotalFrameLen) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PP2P_PUBLIC_FRAME pFrame; + ULONG P2pIeLen = 0; + PUCHAR pDest; + ULONG Length; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + PUCHAR Ptr = NULL; + + *pTotalFrameLen = 0; + /* allocate and send out ProbeRsp frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + pFrame = (PP2P_PUBLIC_FRAME)pOutBuffer; + Ptr = (PUCHAR) pFrame; + if (MyRule == P2P_IS_CLIENT) + ActHeaderInit(pAd, &pFrame->p80211Header, Addr1, pP2PCtrl->CurrentAddress, Addr1); + else + ActHeaderInit(pAd, &pFrame->p80211Header, Addr1, pP2PCtrl->CurrentAddress, Bssid); + DBGPRINT(RT_DEBUG_ERROR, ("P2P - P2PMakeInviteRsp MyRule = %s. TO %02x:%02x:%02x:%02x:%02x:%02x. \n", decodeMyRule(MyRule), PRINT_MAC(Addr1))); + DBGPRINT(RT_DEBUG_ERROR, ("P2P - Bssid %02x:%02x:%02x:%02x:%02x:%02x. \n", PRINT_MAC(Bssid))); + pFrame->Category = CATEGORY_PUBLIC; + pFrame->Action = ACTION_WIFI_DIRECT; + /* point to OUI */ + Ptr += (sizeof(HEADER_802_11) + 2); + /*RTMPMoveMemory((pFrame->OUI), P2POUIBYTE, 4);*/ + RTMPMoveMemory(Ptr, P2POUIBYTE, 4); + Ptr += 4; + /* OUISubtype */ + pFrame->Subtype = P2P_INVITE_RSP; + pFrame->Token = Token; + pFrame->ElementID = IE_VENDOR_SPECIFIC; + /* point to OUI2 */ + Ptr += 4; + /*RTMPMoveMemory((pFrame->OUI2), P2POUIBYTE, 4);*/ + RTMPMoveMemory(Ptr, P2POUIBYTE, 4); + P2pIeLen = 4; + *pTotalFrameLen = 38; + pDest = pFrame->Octet; + /* attach subelementID= 0. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_STATUS, Status, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + /* attach subelementID= 5. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_CONFIG_TIMEOUT, &pP2PCtrl->ConfigTimeout[0], pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + /* attach subelementID= 17. */ + if ((MyRule == P2P_IS_GO) && (*Status == P2PSTATUS_SUCCESS)) + { + DBGPRINT(RT_DEBUG_TRACE, (" P2P - OpChannel = %d \n", pP2PCtrl->GroupChannel)); + if (INFRA_ON(pAd)) + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_OP_CHANNEL, &pAd->CommonCfg.Channel, pDest); + else + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_OP_CHANNEL, OpChannel, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + } + /* attach subelementID= 7. */ + if ((MyRule == P2P_IS_GO) && (*Status == P2PSTATUS_SUCCESS)) + { + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_GROUP_BSSID, Bssid, pDest); + pDest += Length; + P2pIeLen += Length; + *pTotalFrameLen += Length; + } + /* attach subelementID= 7. */ + Length = InsertP2PSubelmtTlv(pAd, SUBID_P2P_CHANNEL_LIST, OpChannel, pDest); + pDest += Length; + P2pIeLen += Length; + /* attach subelementID= 17. */ + *pTotalFrameLen += Length; + pFrame->Length = (UCHAR)P2pIeLen; + + MiniportMMRequest(pAd, 0, pOutBuffer, *pTotalFrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + +} + + +/* + ========================================================================== + Description: + Sanity check of the Probe Request frame when operating as a P2P Device. + Can be called from both as AP's state machine or as STA( that is doing P2P search)'s state machine + + Parameters: + Note: + + ========================================================================== + */ +BOOLEAN PeerP2pProbeReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen, + OUT ULONG *Peerip, + OUT ULONG *P2PSubelementLen, + OUT PUCHAR pP2pSubelement, + OUT ULONG *WpsIELen, + OUT PUCHAR pWpsIE) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PFRAME_802_11 pFrame; + PEID_STRUCT pEid; + ULONG Length = 0; + BOOLEAN brc = FALSE; + UCHAR RateLen; + + pFrame = (PFRAME_802_11)Msg; + Length += LENGTH_802_11; + + *P2PSubelementLen = 0; + *WpsIELen = 0; + *pSsidLen = 0; + *Peerip = 0; + RateLen = 0; + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + + pEid = (PEID_STRUCT) pFrame->Octet; + + /* get variable fields from payload and advance the pointer */ + while ((Length + 2 + pEid->Len) <= MsgLen) + { + switch(pEid->Eid) + { + case IE_EXT_SUPP_RATES: + /* concatenate all extended rates to Rates[] and RateLen */ + RateLen = (RateLen) + pEid->Len; + break; + case IE_SUPP_RATES: + RateLen = (RateLen) + pEid->Len; + break; + 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, WPS_OUI, 4) && (pEid->Len > 4)) + { + RTMPMoveMemory(pWpsIE, &pEid->Eid, pEid->Len +2); + *WpsIELen = pEid->Len + 2; + } + if (NdisEqualMemory(pEid->Octet, P2POUIBYTE, 4) && (pEid->Len > 4)) + { + if (*P2PSubelementLen == 0) + { + RTMPMoveMemory(pP2pSubelement, &pEid->Eid, pEid->Len+2); + *P2PSubelementLen = pEid->Len+2; + brc = TRUE; + } + else if (*P2PSubelementLen > 0) + { + RTMPMoveMemory(pP2pSubelement + *P2PSubelementLen, &pEid->Eid, pEid->Len+2); + *P2PSubelementLen += (pEid->Len+2); + brc = TRUE; + } + + DBGPRINT(RT_DEBUG_INFO, (" !FIND!!!!!!===>P2P - PeerP2pProbeReq P2P IE Len = %ld. %s\n", *P2PSubelementLen, decodeP2PState(pP2PCtrl->P2PConnectState))); + } + break; + } + Length = Length + 2 + pEid->Len; /* Eid[1] + Len[1]+ content[Len] */ + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + + } + + /* Doesn't parse probe request that only support 11b. So return FALSE. */ + if (RateLen <= 4) + { + brc = FALSE; + DBGPRINT(RT_DEBUG_INFO, ("Ignore Probe Request that is 11b-only.\n")); + } + /* Check P2P's Probe Response validatity. */ + if (*P2PSubelementLen <= 4) + { + brc = FALSE; + DBGPRINT(RT_DEBUG_INFO, ("Ignore Probe Request that doesn't have P2P IE.\n")); + } + + return brc; + +} + +/* + ========================================================================== + Description: + Sanity check of the Probe Response frame when operating as a P2P Device. + Only called from STA's state machine that is in scanning. + + Parameters: + Note: + + ========================================================================== + */ +BOOLEAN PeerP2pBeaconSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen, + OUT ULONG *Peerip, + OUT ULONG *P2PSubelementLen, + OUT PUCHAR pP2pSubelement) +{ + PFRAME_802_11 pFrame; + PEID_STRUCT pEid; + ULONG Length = 0; + BOOLEAN brc = FALSE; + PUCHAR Ptr; + BOOLEAN bFirstP2pOUI = TRUE; + + 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, WPS_OUI, 4) && (pEid->Len >= 4)) + { + if (*P2PSubelementLen == 0) + { + RTMPMoveMemory(pP2pSubelement, &pEid->Eid, pEid->Len +2); + *P2PSubelementLen = pEid->Len +2; + } + else if (*P2PSubelementLen > 0) + { + RTMPMoveMemory(pP2pSubelement + *P2PSubelementLen, &pEid->Eid, pEid->Len+2); + *P2PSubelementLen += (pEid->Len+2); + } + } + else if (NdisEqualMemory(pEid->Octet, 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) + { + RTMPMoveMemory(pP2pSubelement + *P2PSubelementLen, &pEid->Eid, pEid->Len+2); + *P2PSubelementLen += (pEid->Len+2); + brc = TRUE; + } + 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)) + { + RTMPMoveMemory(pP2pSubelement + *P2PSubelementLen, &pEid->Eid, pEid->Len+2); + *P2PSubelementLen += (pEid->Len+2); + brc = TRUE; + } + } + } + break; + } + Length = Length + 2 + pEid->Len; /* Eid[1] + Len[1]+ content[Len] */ + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + + } + return brc; +} + +/* + ========================================================================== + Description: + Sanity check of the Probe Response frame when operating as a P2P Device. + Only called from STA's state machine that is in scanning. + + Parameters: + Note: + + ========================================================================== + */ +BOOLEAN PeerP2pProbeRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen, + OUT ULONG *Peerip, + OUT ULONG *P2PSubelementLen, + OUT PUCHAR pP2pSubelement) +{ + 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; + *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: + 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) + { + RTMPMoveMemory(pP2pSubelement + *P2PSubelementLen, &pEid->Eid, pEid->Len+2); + *P2PSubelementLen += (pEid->Len+2); + } + } + 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) + { + 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)); + } + 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)) + { + RTMPMoveMemory(pP2pSubelement + *P2PSubelementLen, &pEid->Octet[4], pEid->Len-4); + *P2PSubelementLen += (pEid->Len-4); + P2PIeConLen += (pEid->Len - 4); + } + } + } + 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; +} + +VOID P2pPeerBeaconAtJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem, + IN PUCHAR Bssid) +{ + /*PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg;*/ + UCHAR P2pManageability = 0xff; + UCHAR NumOfOtherP2pAttri = 1; + UCHAR Channel = 1; + UCHAR TotalNumOfP2pAttribute = 1; + + if (Elem->MsgLen <= (LENGTH_802_11 + 12)) + return; + + P2pParseManageSubElmt(pAd, + &Elem->Msg[LENGTH_802_11 + 12], + (Elem->MsgLen - LENGTH_802_11 - 12), + &Channel, + &NumOfOtherP2pAttri, + &TotalNumOfP2pAttribute, + &P2pManageability, + NULL); + + DBGPRINT(RT_DEBUG_INFO, ("P2pParseManageSubElmt TotalNumOfP2pAttribute = %d. \n", TotalNumOfP2pAttribute)); + /* If this AP carries Managed Attribute. Update to our ManageAPBSsid */ + if (P2pManageability != 0xff) + { + DBGPRINT(RT_DEBUG_INFO, ("SYNC - Receive desired BEACON with valid P2pManageability= %x\n", P2pManageability)); + DBGPRINT(RT_DEBUG_INFO, ("SYNC -NumOfOtherP2pAttri %d . Channel = %d. \n", NumOfOtherP2pAttri, Channel)); + RTMPMoveMemory(pAd->P2pCfg.P2pManagedParm.ManageAPBSsid, Bssid, MAC_ADDR_LEN); + + /* Reset Minor Reason when connecting to Managed AP. */ + pAd->P2pCfg.P2pManagedParm.APP2pMinorReason = 0; + pAd->P2pCfg.P2pManagedParm.APUsageChannel = Channel ; + /* If this is the latest managed AP that I connected to. but this AP turn off the managed function. */ + /* I should clear my record. */ + + /* If this is a manged AP. update to the ManageAPBSsid. */ + if ((P2P_TEST_BIT(P2pManageability, P2PMANAGED_ENABLE_BIT)) && (NumOfOtherP2pAttri == 0)) + { + DBGPRINT(RT_DEBUG_INFO, ("SYNC -I am connecting to a Managed AP. Save this Bssid. %x %x %x \n", Bssid[3],Bssid[4],Bssid[5])); + } + + pAd->P2pCfg.P2pManagedParm.APP2pManageability = P2pManageability; + } + pAd->P2pCfg.P2pManagedParm.TotalNumOfP2pAttribute = TotalNumOfP2pAttribute; + + DBGPRINT(RT_DEBUG_INFO, ("SYNC - BEACON P2pManageability= %x. TotalNumOfP2pAttribute = %d. OtherP2pAttri = %d\n", P2pManageability, TotalNumOfP2pAttribute, NumOfOtherP2pAttri)); + +} + +/* + ========================================================================== + Description: + Processing the Probe Response frame when operating as a P2P Device. + Only called from STA's state machine that is in scanning. + + Parameters: + Note: + + ========================================================================== + */ +VOID PeerP2pBeaconProbeRspAtScan( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +/* IN USHORT CapabilityInfo, */ +/* IN UCHAR WorkingChannel) */ +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PRT_P2P_CLIENT_ENTRY pP2pEntry = NULL; + BOOLEAN bBeacon = FALSE; + BOOLEAN bresult; + BOOLEAN bChangeState = FALSE; + ULONG P2PSubelementLen; + PUCHAR P2pSubelement = NULL; + UCHAR index;/*, perstindex; */ + UCHAR Addr2[6], SsidLen; + UCHAR Ssid[32]; + ULONG Peerip; + UCHAR DevType[8], DevAddr[6], Channel = 0, OpChannel = 0, Intent; + UCHAR GroupCap, DeviceCap, StatusCode; + USHORT Dpid; + PHEADER_802_11 pHeader; + USHORT ConfigMethod = 0xffff; + UCHAR DeviceNameLen = 0, DeviceName[32]; + UCHAR SavedP2PTableNum; + P2P_CMD_STRUCT P2pCmd; + BOOLEAN bSendP2pEvent = FALSE; +#ifdef DPA_S + BOOLEAN bNewFound = FALSE; +#endif /* DPA_S */ + + /* If there is already BSS or IBSS and only one port, no need to parse Probe response for P2P discovery feature */ + /* INFRA on includes case that I am P2P client. in this case, doesn't need to parse P2P IE in Probe Response either?? */ + /* if ((INFRA_ON(pAd) || ADHOC_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) + { + DBGPRINT(RT_DEBUG_ERROR, ("1 PeerP2pBeaconProbeRspAtScan:: %s \n", decodeP2PState(pP2PCtrl->P2PDiscoProvState))); + return; + } + */ + + /* Init P2pSubelement */ + os_alloc_mem(pAd, &P2pSubelement, MAX_VIE_LEN); + + if (P2pSubelement == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("PeerP2pBeaconProbeRspAtScan::Allocate memory size(=1024) failed\n")); + goto CleanUp; + } + RTMPZeroMemory(&DeviceName[0], 32); + + /* P2P Device's probe response doesn't set ess bit on. */ + pHeader = (PHEADER_802_11)&Elem->Msg[0]; + /* In P2P spec, the P2P IE in probe response and beacon are different. */ + /* So set a boolean to check if this is a beacon frame. */ + if (pHeader->FC.SubType == SUBTYPE_BEACON) + bBeacon = TRUE; + + /* Intel put P2P IE into two separate IE */ + /* Sanity check */ + if (PeerP2pProbeRspSanity(pAd, + Elem->Msg, + Elem->MsgLen, + Addr2, + Ssid, + &SsidLen, + &Peerip, + &P2PSubelementLen, + P2pSubelement)) + { + CHAR Rssi; + /* Check P2P's Probe Response validatity. */ + if (!(NdisEqualMemory(Ssid, &WILDP2PSSID[0], WILDP2PSSIDLEN))) + { + DBGPRINT(RT_DEBUG_INFO, ("PeerP2pBeaconProbeRspAtScan: Len = %ld.: \n", P2PSubelementLen)); + DBGPRINT(RT_DEBUG_INFO, ("= %02x:%02x:%02x:%02x:%02x:%02x \n", PRINT_MAC(Addr2))); + DBGPRINT(RT_DEBUG_INFO, ("= %c %c %c %c %c %c%c \n", Ssid[0], Ssid[1],Ssid[2],Ssid[3],Ssid[4],Ssid[5],Ssid[6])); + goto CleanUp; + } + else + DBGPRINT(RT_DEBUG_INFO, ("!! %s = %02x:%02x:%02x:%02x:%02x:%02x!!\n", __FUNCTION__, PRINT_MAC(Addr2))); + Rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); + + /* Step 1: Parse P2P attribute */ + /* If this peer is provisioned, don't update Config */ + if (bBeacon == FALSE) + { + P2pParseSubElmt(pAd, (PVOID)P2pSubelement, P2PSubelementLen, + bBeacon, &Dpid, &GroupCap, &DeviceCap, DeviceName, &DeviceNameLen, DevAddr, NULL, NULL, NULL, NULL, &ConfigMethod, NULL, DevType, &Channel, &OpChannel, NULL, &Intent, &StatusCode, NULL); + } + else + P2pParseSubElmt(pAd, (PVOID)P2pSubelement, P2PSubelementLen, + bBeacon, &Dpid, &GroupCap, &DeviceCap, DeviceName, &DeviceNameLen, DevAddr, NULL, NULL, NULL, NULL, NULL, NULL, DevType, &Channel, &OpChannel, NULL, &Intent, &StatusCode, NULL); + + /* Step 3: Insert. */ + SavedP2PTableNum = pAd->P2pTable.ClientNumber; + index = P2pGroupTabSearch(pAd, DevAddr); + if (index == P2P_NOT_FOUND) + { + /* Because only Probe Response carrys group info, */ + /* If we use Probe Response to add to my P2P table structure. If this is beacon */ + /* and in social channels. return. */ + if (bBeacon == TRUE) + goto CleanUp; + + DBGPRINT(RT_DEBUG_ERROR, ("2 New From Addr2 = %02x:%02x:%02x:%02x:%02x:%02x. bBeacon = %d . GroupCap = %x \n", PRINT_MAC(Addr2), bBeacon, GroupCap)); + DBGPRINT(RT_DEBUG_ERROR, ("2 New From DevAddr = %02x:%02x:%02x:%02x:%02x:%02x. bBeacon = %d . GroupCap = %x \n", PRINT_MAC(DevAddr), bBeacon, GroupCap)); +#ifdef DPA_S + bNewFound = TRUE; +#endif /* DPA_S */ + if ((bBeacon == TRUE) || ((GroupCap&GRPCAP_OWNER) == GRPCAP_OWNER)) + { + index = P2pGroupTabInsert(pAd, DevAddr, P2PSTATE_DISCOVERY_GO, Ssid, SsidLen, DeviceCap, GroupCap); +#ifdef DPA_S + P2pSendDevFoundEvent(pAd, P2P_NOTIF_DISCOVER_FOUND_P2P_GROUPS, Rssi, Ssid, SsidLen, P2pSubelement, P2PSubelementLen); +#endif /* DPA_S */ + + } + /* P2P client can't send probe response. So the probe response must be from P2P device. */ + else + { + index = P2pGroupTabInsert(pAd, DevAddr, P2PSTATE_DISCOVERY, Ssid, SsidLen, DeviceCap, GroupCap); +#ifdef DPA_S + P2pSendDevFoundEvent(pAd, P2P_NOTIF_DISCOVER_FOUND_PEERS, Rssi, Ssid, SsidLen, P2pSubelement, P2PSubelementLen); +#endif /* DPA_S */ + } + bSendP2pEvent = TRUE; + } + + /* No matter the index is from existing table, or newly added, always update Ssid Information If this peer is not connected. */ + /* Step 4: Update table. */ + if (index < MAX_P2P_GROUP_SIZE) + { + pP2pEntry = &pAd->P2pTable.Client[index]; + DBGPRINT(RT_DEBUG_INFO, ("%s:: got ProbeResp.index = %d. statue = %s\n", __FUNCTION__, index, decodeP2PClientState(pAd->P2pTable.Client[index].P2pClientState))); + pP2pEntry->DevCapability = DeviceCap; + pP2pEntry->GroupCapability = GroupCap; + pP2pEntry->Rssi = Rssi; + +#ifdef DPA_S + NdisGetSystemUpTime(&pAd->P2pTable.Client[index].LastRxTime); +#endif /* DPA_S */ + + /* Update Rule according to latest Probe Response or Beacon that I received. */ + if ((bBeacon == TRUE) && + ((pP2pEntry->P2pClientState == P2PSTATE_DISCOVERY_CLIENT) || (pP2pEntry->P2pClientState == P2PSTATE_DISCOVERY))) + { + /* If total P2P device number > 10, don't want keep update topology if topology change. */ + if ((pAd->P2pTable.ClientNumber < 10) + || (((pAd->P2pTable.ClientNumber%4) == 3)&&(pAd->P2pTable.ClientNumber >= 10))) + bChangeState = TRUE; + pP2pEntry->Rule = P2P_IS_GO; + pP2pEntry->P2pClientState = P2PSTATE_DISCOVERY_GO; + DBGPRINT(RT_DEBUG_ERROR, ("3 From DevAddr = %02x:%02x:%02x:%02x:%02x:%02x. Change rule to GO GroupCap = %x \n", PRINT_MAC(DevAddr), GroupCap)); + } + else if ((pP2pEntry->P2pClientState == P2PSTATE_DISCOVERY_GO) + && ((GroupCap&GRPCAP_OWNER) != GRPCAP_OWNER)) + { + if ((pAd->P2pTable.ClientNumber < 10) + || (((pAd->P2pTable.ClientNumber % 4) == 3) && (pAd->P2pTable.ClientNumber >= 10))) + bChangeState = TRUE; + pP2pEntry->Rule = P2P_IS_CLIENT; + pP2pEntry->P2pClientState = P2PSTATE_DISCOVERY; + DBGPRINT(RT_DEBUG_ERROR, ("4 From DevAddr = %02x:%02x:%02x:%02x:%02x:%02x. Change rule to Device. GroupCap = %x \n", PRINT_MAC(DevAddr), GroupCap)); + } + + + + /* If peer is provisioned, don't update. We treat him only support this provisioned configmethod. */ + if (!P2P_TEST_FLAG(pP2pEntry, P2PFLAG_PROVISIONED) && (ConfigMethod != 0xffff)) + pP2pEntry->ConfigMethod = ConfigMethod; + + /* Always Update Device Name */ + if (DeviceNameLen != 0) + { +#ifdef DPA_S + if (bNewFound) + { + /* + We don't need to send this event in this case + */ + RTMPMoveMemory(&pAd->P2pTable.Client[index].DeviceName[0], DeviceName, 32); + pAd->P2pTable.Client[index].DeviceNameLen = DeviceNameLen; + pAd->P2pTable.Client[index].DeviceName[pAd->P2pTable.Client[index].DeviceNameLen] = 0x0; + } + else if ((pAd->P2pTable.Client[index].DeviceNameLen != DeviceNameLen) + || NdisEqualMemory(&pAd->P2pTable.Client[index].DeviceName[0], + DeviceName, + pAd->P2pTable.Client[index].DeviceNameLen) == FALSE) + { + RTMPMoveMemory(&pAd->P2pTable.Client[index].DeviceName[0], DeviceName, 32); + pAd->P2pTable.Client[index].DeviceNameLen = DeviceNameLen; + pAd->P2pTable.Client[index].DeviceName[pAd->P2pTable.Client[index].DeviceNameLen] = 0x0; + if ((pAd->P2pTable.Client[index].GroupCapability & GRPCAP_OWNER) == GRPCAP_OWNER) + P2pSendDevFoundEvent(pAd,P2P_NOTIF_DISCOVER_FOUND_P2P_GROUPS, Rssi, DeviceName, DeviceNameLen, P2pSubelement, P2PSubelementLen); + else + P2pSendDevFoundEvent(pAd,P2P_NOTIF_DISCOVER_FOUND_PEERS, Rssi, DeviceName, DeviceNameLen, P2pSubelement, P2PSubelementLen); + } +#else /* DPA_S */ + RTMPMoveMemory(&pP2pEntry->DeviceName[0], DeviceName, 32); + pP2pEntry->DeviceNameLen = DeviceNameLen; + pP2pEntry->DeviceName[pP2pEntry->DeviceNameLen] = 0x0; +#endif /* !DPA_S */ + } + + /* If this is beacon. It must use correct opchannel, ssid, interface addr, and SSID. So update. */ + /* Step 4 - 1: Update table according to this is beacon or probe response. Beacon and probe response carries */ + /* different attribute. */ + if (bBeacon == TRUE) + { + pP2pEntry->Rule = P2P_IS_GO; + RTMPMoveMemory(pP2pEntry->Ssid, Ssid, 32); + pP2pEntry->SsidLen = SsidLen; + RTMPMoveMemory(pP2pEntry->bssid, Addr2, MAC_ADDR_LEN); + RTMPMoveMemory(pP2pEntry->InterfaceAddr, Addr2, MAC_ADDR_LEN); + pP2pEntry->OpChannel = Elem->Priv; /* WorkingChannel; */ + /* The peer is GO. So set its state to GO_WPS directly. No need for Group forming procedure. */ + /* Search this beacon's group info, and insert its client to my p2p table too. */ + if ((GroupCap & GRPCAP_OWNER) != GRPCAP_OWNER) + { + /* Print for debug. */ + DBGPRINT(RT_DEBUG_ERROR, ("P2p : One P2P device[%d] send out Beacon. But group owner %x bit not set ? \n", index, GroupCap)); + } + } + /* Make it more readable to use "else if". Group info only appears in Probe Response. */ + else if (bBeacon == FALSE) + { + /* If this is GO. */ + if ((GroupCap & GRPCAP_OWNER) == GRPCAP_OWNER) + { + /* The peer is GO. So set its state to GO_WPS directly. No need for Group forming procedure. */ + pP2pEntry->Rule = P2P_IS_GO; + } + else + { + /* Not GO anymore, update State. */ + if (IS_P2P_PEER_DISCOVERY(pP2pEntry)) + pP2pEntry->P2pClientState = P2PSTATE_DISCOVERY; + pP2pEntry->Rule = P2P_IS_CLIENT; + } + /* P2P PrimaryDevType only appears in Probe Response. not in beacon. */ + RTMPMoveMemory(pP2pEntry->PrimaryDevType, DevType, 8); + /* Can I just set this channel that I got Probe response as listent channel?? */ + if (Elem->Priv) + pP2pEntry->ListenChannel = Elem->Priv; + bresult = P2pParseGroupInfoAttribute(pAd, index, P2pSubelement, P2PSubelementLen); + if (bresult == FALSE) + goto CleanUp; + } + +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT + if (bSendP2pEvent) + P2pSendWirelessEvent(pAd, RT_P2P_DEVICE_FIND, pP2pEntry, Addr2); +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ + /* Step 5: Take Some action when the peer is */ + /* Decide to connect? or Provision ? or Service discovery ? */ + if ((pP2pEntry->P2pClientState <= P2PSTATE_GO_DONE)) + { + if ((DeviceCap & DEVCAP_INVITE) == DEVCAP_INVITE) + P2P_SET_FLAG(pP2pEntry, P2PFLAG_INVITE_ENABLED); + + if (pP2pEntry->P2pClientState != P2PSTATE_DISCOVERY) + { + UCHAR ClientState = pP2pEntry->P2pClientState; + COPY_MAC_ADDR(&P2pCmd.Addr[0], pP2pEntry->addr); + P2pCmd.Idx = index; + pP2pEntry->ReTransmitCnt = 0; + /*P2pCmd.ConfigMethod = pAd->P2pTable.Client[index].ConfigMethod; */ + DBGPRINT(RT_DEBUG_INFO, ("P2p : DevAddr[%02x:%02x:%02x:%02x:%02x:%02x] State = %s.\n", + PRINT_MAC(DevAddr), decodeP2PClientState(pP2pEntry->P2pClientState))); + DBGPRINT(RT_DEBUG_INFO, ("P2p : GrpCap=%x. DevCap=%x. ConfigMethod= %x.\n", + GroupCap, DeviceCap, pP2pEntry->ConfigMethod)); + + MlmeEnqueue(pAd, P2P_GO_FORM_STATE_MACHINE, P2P_START_COMMUNICATE_CMD_EVT, sizeof(P2P_CMD_STRUCT), &P2pCmd, ClientState); + RTMP_MLME_HANDLER(pAd); + goto CleanUp; + } + if (pAd->P2pCfg.ConnectingIndex < MAX_P2P_GROUP_SIZE) + { + if (MAC_ADDR_EQUAL(pAd->P2pTable.Client[index].addr, &pAd->P2pCfg.ConnectingMAC[0])) + { + DBGPRINT(RT_DEBUG_INFO, (" From : %02x:%02x:%02x:%02x:%02x:%02x, state = %s\n", PRINT_MAC(Addr2), decodeP2PClientState(pP2pEntry->P2pClientState))); + DBGPRINT(RT_DEBUG_INFO, (" P2PTab[%d] Addr : %02x:%02x:%02x:%02x:%02x:%02x\n", index, PRINT_MAC(pP2pEntry->addr))); + DBGPRINT(RT_DEBUG_INFO, (" ConenctIdx = %d, Addr : %02x:%02x:%02x:%02x:%02x:%02x\n", pAd->P2pCfg.ConnectingIndex, PRINT_MAC(pAd->P2pCfg.ConnectingMAC))); + + P2pConnectAfterScan(pAd, bBeacon, index); + } + } + } + } + } + +CleanUp: + if (P2pSubelement) + os_free_mem(pAd, P2pSubelement); + +} + +/* + ========================================================================== + Description: + Processing the Beacon frame when operating as a P2P client. + Only called from STA's state machine that is in idle. + this function can support NoA and show Ralink IP. + Parameters: + Note: + + ========================================================================== + */ +VOID PeerP2pBeacon( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr2, + IN MLME_QUEUE_ELEM *Elem, + IN LARGE_INTEGER TimeStamp) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + UCHAR Addr2[6], SsidLen; + UCHAR Ssid[32]; + ULONG Peerip; + ULONG P2PSubelementLen; + PUCHAR P2pSubelement = NULL; + PFRAME_802_11 pFrame; + /*UCHAR bitmap;*/ + 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]; + if (!(IS_P2P_CLI_ENTRY(pMacEntry) && IS_ENTRY_APCLI(pMacEntry))) + { + DBGPRINT(RT_DEBUG_INFO, ("1 PeerP2pBeaconProbeRspAtScan failed : wcid = %d. not ValidAsP2P. Bug!please check. \n", Elem->Wcid)); + DBGPRINT(RT_DEBUG_INFO, ("pMacEntry Addr = %02x:%02x:%02x:%02x:%02x:%02x.\n", PRINT_MAC(pMacEntry->Addr))); + return; + } + + if ((pMacEntry->WpaState != AS_PTKINITDONE)) + return; + + /* Init P2pSubelement */ + os_alloc_mem(pAd, &P2pSubelement, MAX_VIE_LEN); + if (P2pSubelement == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("3 PeerP2pBeaconProbeRspAtScan::1Allocate memory size(=1024) failed\n")); + goto CleanUp; + } + + if (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; + P2pParseNoASubElmt(pAd, P2pSubelement, P2PSubelementLen, Elem->Wcid, pFrame->Hdr.Sequence); + /* Since we get beacon, check if GO enable and OppPS. */ + if (P2P_TEST_BIT(pAd->P2pCfg.CTWindows, P2P_OPPS_BIT)) + { + pAd->P2pCfg.bKeepSlient = FALSE; + /* TO DO : sync with windows if necessary */ + /*RTMPDeQueueNoAMgmtPacket(pAd);*/ + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); /* Dequeue outgoing frames from TxSwQueue0..3 queue and process it */ + if (((pAd->P2pCfg.CTWindows&0x7f) > 0) && ((pAd->P2pCfg.CTWindows&0x7f) < 80)) + { + DBGPRINT(RT_DEBUG_INFO, ("%s:: set P2P CTWindows timer.\n", __FUNCTION__)); + RTMPSetTimer(&pAd->P2pCfg.P2pCTWindowTimer, (pAd->P2pCfg.CTWindows&0x7f)); + } + } + } + +CleanUp: + if (P2pSubelement) + os_free_mem(NULL, P2pSubelement); + +} + +/* + ========================================================================== + Description: + Processing the Beacon frame when operating as a P2P client. + Only called from STA's state machine that is in idle. + + Parameters: + *pPeerip : Go's ip. + *pMemberip : Other member's ip that is in the same P2P Group. + Note: + + ========================================================================== + */ +BOOLEAN PeerBeaconParseRalinkIE( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT RALINKIP_IE *pRalinkIE, + OUT RALINKMBRIP_ELEM *pMemberip, + OUT ULONG *pPeerip) +{ + PFRAME_802_11 pFrame; + PEID_STRUCT pEid; + ULONG Length = 0; + BOOLEAN brc = FALSE; + PUCHAR Ptr; + + pFrame = (PFRAME_802_11)Msg; + Length += LENGTH_802_11; + + *pPeerip = 0; + NdisZeroMemory(pRalinkIE, sizeof(RALINKIP_IE)); + NdisZeroMemory(pMemberip, sizeof(RALINKMBRIP_ELEM)); + + 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_VENDOR_SPECIFIC: + if (NdisEqualMemory(pEid->Octet, RALINK_OUI, 3) && (pEid->Len == 5)) + { + RTMPMoveMemory(pRalinkIE, &pEid->Eid, sizeof(RALINKIP_IE)); + brc = TRUE; + } + else if (NdisEqualMemory(pEid->Octet, RALINK_OUI, 3) && (pEid->Len == 8)) + { + if (pEid->Octet[3] == RALINKOUIMODE_IPRSP) + { + *pPeerip = *(PULONG)&pEid->Octet[4]; + brc = TRUE; + } + } + else if (NdisEqualMemory(pEid->Octet, RALINK_OUI, 3)) + { + /* Beacon broadcast's other peer's ip in Probe rsp. */ + if (pEid->Octet[3] == RALINKOUIMODE_MBRIPRSP) + { + RTMPMoveMemory(pMemberip, &pEid->Octet[4], sizeof(RALINKMBRIP_ELEM)); + brc = TRUE; + } + } + break; + default: + break; + } + + Length = Length + 2 + pEid->Len; /* Eid[1] + Len[1]+ content[Len] */ + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + + return brc; + +} + +/* + ========================================================================== + Description: + Processing Probe Request frame when operating as a P2P Device. + Can be called from both as AP's state machine or as STA( that is doing P2P search)'s state machine + + Parameters: + Note: + + ========================================================================== + */ +VOID PeerP2pProbeReq( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +/* IN BOOLEAN bSendRsp) */ +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + ULONG P2PSubelementLen, WpsIELen; + UCHAR *P2pSubelement; + UCHAR *WpsIE; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + UCHAR Addr2[MAC_ADDR_LEN]; + UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen; + UCHAR index, perstindex; + /*BOOLEAN bNewlyAdd = FALSE; */ + ULONG Peerip; + /*RALINKIP_IE RalinkIp;*/ + BOOLEAN bresult = FALSE; + UCHAR GroupCap, DeviceCap, DevAddr[MAC_ADDR_LEN], StatusCode; + BOOLEAN bSendRsp = TRUE; + UCHAR Channel = Elem->Priv; + + /* When I am a P2P Client , can't send probe response. */ + if (P2P_CLI_ON(pAd)) + return; + + if ( pP2PCtrl->bSentProbeRSP != TRUE ) + return; + + /* When I am not in listen channel , can't send probe response. */ + if (Channel != pAd->P2pCfg.ListenChannel) + { + bSendRsp = FALSE; + if (P2P_GO_ON(pAd) && (Channel == pAd->P2pCfg.GroupOpChannel)) + bSendRsp = TRUE; + } + + P2pSubelement = NULL; + WpsIE = NULL; + + os_alloc_mem(pAd, &P2pSubelement, MAX_VIE_LEN); + os_alloc_mem(pAd, &WpsIE, MAX_VIE_LEN); + + if ((P2pSubelement == NULL) || (WpsIE == NULL)) + goto CleanUp; + + if (PeerP2pProbeReqSanity(pAd, + Elem->Msg, + Elem->MsgLen, + Addr2, + Ssid, + &SsidLen, + &Peerip, + &P2PSubelementLen, + P2pSubelement, + &WpsIELen, + WpsIE)) + { + if (FALSE == P2PDeviceMatch(pAd, Addr2, NULL, 0)) + goto CleanUp; + + DBGPRINT(RT_DEBUG_INFO, ("P2P Peer Probe Req from %02x %02x %02x %02x %02x %02x \n", Addr2[0],Addr2[1],Addr2[2],Addr2[3],Addr2[4],Addr2[5])); + /*if ((RalinkIp.OUIMode == RALINKOUIMODE_IPREQ) + && (pAd->P2pCfg.P2pEventQueue.bGotMyip == TRUE)) + { + pP2PCtrl->P2pEventQueue.bSendMyip = TRUE; + DBGPRINT(RT_DEBUG_INFO,("Set bSendMyip = TRUE for this probe request. \n")); + } + if (Peerip != 0) + { + DBGPRINT(RT_DEBUG_INFO,("Client[%d] ip = %x. \n", index, Peerip)); + if (index < MAX_P2P_GROUP_SIZE) + { + if (pAd->P2pTable.Client[index].Peerip != Peerip) + { + pAd->P2pTable.Client[index].Peerip = Peerip; + pAd->P2pCfg.P2pEventQueue.bP2pTopologyUpdate = TRUE; + + DBGPRINT(RT_DEBUG_INFO,("Update Client[%d] ip = %x. \n", index, Peerip)); + P2pUpdateBssBeacon(pAd, NULL, &index); + } + } + }*/ + index = P2pGroupTabSearch(pAd, Addr2); + + if (index < MAX_P2P_GROUP_SIZE) + { + DBGPRINT(RT_DEBUG_INFO, ("%s / %s\n", + decodeP2PClientState(pAd->P2pTable.Client[index].P2pClientState), decodeP2PState(pAd->P2pCfg.P2PConnectState))); + if ((pAd->P2pTable.Client[index].P2pClientState > P2PSTATE_DISCOVERY_UNKNOWN) || + (pAd->P2pCfg.P2PConnectState != P2P_CONNECT_IDLE)) + bSendRsp = TRUE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("(%d) P2P Peer Probe Req from %02x %02x %02x %02x %02x %02x \n", + bSendRsp, Addr2[0],Addr2[1],Addr2[2],Addr2[3],Addr2[4],Addr2[5])); + + if (bSendRsp == TRUE) + { + /* allocate and send out ProbeRsp frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + goto CleanUp; + + + P2PMakeProbe(pAd, Elem, Channel, SUBTYPE_PROBE_RSP, pOutBuffer, &FrameLen); + + + if (FrameLen > 0) + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + + + DBGPRINT(RT_DEBUG_INFO, ("Got P2P Peer %d Probe Req . Send probe response back len=%ld \n", index, FrameLen)); + MlmeFreeMemory(pAd, pOutBuffer); + } + /* Check already in table ? */ + /* If currently there is no activated P2P profile, we can still check if there is matching peer that is */ + /* in Persistent table send probe response. If there is one, maybe we can try to connect to it. */ + + if (index < MAX_P2P_GROUP_SIZE) + { + P2pParseSubElmt(pAd, P2pSubelement, P2PSubelementLen, + FALSE, NULL, &GroupCap, &DeviceCap, NULL, NULL, DevAddr, NULL, NULL, &SsidLen, Ssid, NULL, NULL, pAd->P2pTable.Client[index].PrimaryDevType, &pAd->P2pTable.Client[index].ListenChannel, &pAd->P2pTable.Client[index].OpChannel, NULL, &pAd->P2pTable.Client[index].GoIntent, &StatusCode, NULL); +#ifdef DPA_S + NdisGetSystemUpTime(&pAd->P2pTable.Client[index].LastRxTime); +#endif /* DPA_S */ + if (pAd->P2pTable.Client[index].P2pClientState == P2PSTATE_CONNECT_COMMAND) + { + P2P_CMD_STRUCT P2pCmd; + UCHAR ClientState = pAd->P2pTable.Client[index].P2pClientState; + DBGPRINT(RT_DEBUG_ERROR, ("<< %s: Start Group Form!\n", __FUNCTION__)); + COPY_MAC_ADDR(&P2pCmd.Addr[0], pAd->P2pTable.Client[index].addr); + P2pCmd.Idx = index; + /*P2pStartGroupForm(pAd, pAd->P2pTable.Client[index].addr, index); */ + } + else if (pAd->P2pTable.Client[index].P2pClientState == P2PSTATE_INVITE_COMMAND) + { + DBGPRINT(RT_DEBUG_ERROR, ("<< %s: Invite!\n", __FUNCTION__)); + + if (IS_P2P_CONNECT_IDLE(pAd)) + { + perstindex = P2pPerstTabSearch(pAd, pAd->P2pTable.Client[index].addr, pAd->P2pTable.Client[index].bssid, pAd->P2pTable.Client[index].InterfaceAddr); + bresult = P2pInvite(pAd, pAd->P2pTable.Client[index].addr, perstindex, index); + } + else if (P2P_GO_ON(pAd)) + { + /* Invite Case 1 */ + bresult = P2pInvite(pAd, pAd->P2pTable.Client[index].addr, MAX_P2P_TABLE_SIZE, index); + + } + else if (P2P_CLI_ON(pAd)) + { + /* Invite Case 1 */ + bresult = P2pInvite(pAd, pAd->P2pTable.Client[index].addr, MAX_P2P_TABLE_SIZE, index); + } + + if (bresult == TRUE) + { + P2pStopScan(pAd); + pP2PCtrl->P2PConnectState = P2P_INVITE; + } + } + + } + + } + CleanUp: + + if (P2pSubelement) + os_free_mem(NULL, P2pSubelement); + if (WpsIE) + os_free_mem(NULL, WpsIE); + +} + +/* + ========================================================================== + Description: + Call this function when receiving WPS EAP Nack frame. Most of time is because incorrect PIN. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pReceiveEapNack( + IN PRTMP_ADAPTER pAd, + IN PMLME_QUEUE_ELEM pElem) +{ +} + + +VOID P2pMakeProbeRspWSCIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pOutBuf, + OUT PULONG pIeLen) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + UCHAR WscIEFixed[] = {0xdd, 0x0e, 0x00, 0x50, 0xf2, 0x04}; /* length will modify later */ + + + ULONG Len; + PUCHAR pData; + PWSC_DEV_INFO pDevInfo; + + + /* Role play, Enrollee or Registrar */ + pDevInfo = &pP2PCtrl->DevInfo; + + pData = pOutBuf; + Len = 0; + *pIeLen = 0; + + /* 0. WSC fixed IE */ + RTMPMoveMemory(pData, &WscIEFixed[0], 6); + pData += 6; + Len += 6; + + /* 1. Version */ + *((PUSHORT) pData) = cpu2be16(WSC_ID_VERSION); + *((PUSHORT) (pData + 2)) = cpu2be16(0x0001); + *(pData + 4) = pDevInfo->Version; + pData += 5; + Len += 5; + /* 2. Wi-Fi Protected Setup State */ + *((PUSHORT) pData) = cpu2be16(WSC_ID_SC_STATE); + *((PUSHORT) (pData + 2)) = cpu2be16(0x0001); + *(pData + 4) = (pAd->P2pCfg.bConfiguredAP ? WSC_SCSTATE_CONFIGURED : WSC_SCSTATE_UNCONFIGURED); + pData += 5; + Len += 5; + + + + /* 3. Response Type WSC_ID_RESP_TYPE */ + *((PUSHORT) pData) = cpu2be16(WSC_ID_RESP_TYPE); + *((PUSHORT) (pData + 2)) = cpu2be16(0x0001); + if (P2P_GO_ON(pAd)) + *(pData + 4) = WSC_MSGTYPE_AP_WLAN_MGR; + else + *(pData + 4) = WSC_MSGTYPE_ENROLLEE_INFO_ONLY; + pData += 5; + Len += 5; + + /* 4. UUID-E */ + *((PUSHORT) pData) = cpu2be16(WSC_ID_UUID_E); + *((PUSHORT) (pData + 2)) = cpu2be16(0x0010); + NdisMoveMemory((pData + 4), pDevInfo->Uuid, 16); + pData += 20; + Len += 20; + + // 5. Manufacture + *((PUSHORT) pData) = cpu2be16(WSC_ID_MANUFACTURER); + *((PUSHORT) (pData + 2)) = cpu2be16(0x0001); + *(pData + 4) = 0x20; + pData += 5; + Len += 5; + + /* We don't support full length manufacture, model name, model name and model serial */ + /* because it shall overflow. (> 255 bytes) */ + /* 6. Model Name */ + *((PUSHORT) pData) = cpu2be16(WSC_ID_MODEL_NAME); + *((PUSHORT) (pData + 2)) = cpu2be16(0x0001); + *(pData + 4) = 0x20; + pData += 5; + Len += 5; + + /* 7. Model Number */ + *((PUSHORT) pData) = cpu2be16(WSC_ID_MODEL_NUMBER); + *((PUSHORT) (pData + 2)) = cpu2be16(0x0001); + *(pData + 4) = 0x20; + pData += 5; + Len += 5; + + /* 8. Serial Number */ + *((PUSHORT) pData) = cpu2be16(WSC_ID_SERIAL_NUM); + *((PUSHORT) (pData + 2)) = cpu2be16(0x0001); + *(pData + 4) = 0x20; + pData += 5; + Len += 5; + + /* 9. Primary device type */ + *((PUSHORT) pData) = cpu2be16(WSC_ID_PRIM_DEV_TYPE); + *((PUSHORT) (pData + 2)) = cpu2be16(0x0008); + NdisMoveMemory((pData + 4), pDevInfo->PriDeviceType, 8); + pData += 12; + Len += 12; + + /* 10. Primary device name */ + *((PUSHORT) pData) = cpu2be16(WSC_ID_DEVICE_NAME); + *((PUSHORT) (pData + 2)) = cpu2be16(pAd->P2pCfg.DeviceNameLen); + NdisMoveMemory((pData + 4), pAd->P2pCfg.DeviceName, pAd->P2pCfg.DeviceNameLen); + pData += pAd->P2pCfg.DeviceNameLen + 4; + Len += pAd->P2pCfg.DeviceNameLen + 4; + + /* 11. Config Method */ + *((PUSHORT) pData) = cpu2be16(WSC_ID_CONFIG_METHODS); + *((PUSHORT) (pData + 2)) = cpu2be16(0x0002); + *((PUSHORT) (pData + 4)) = cpu2be16(0x0188); + + pData += 6; + Len += 6; + + /* The WPS IE shall contain the attributes required for an AP/Registrar as described in ¡±7.2.5 of [6] + */ + { + /* 12. RF band, shall change based on current channel */ + *((PUSHORT) pData) = cpu2be16(WSC_ID_RF_BAND); + *((PUSHORT) (pData + 2)) = cpu2be16(0x0001); + *(pData + 4) = pDevInfo->RfBand; + pData += 5; + Len += 5; + + /* 13. DPID shall be a required attribute if Credentials are available and ready for immediate use. */ + if (pAd->P2pCfg.Dpid != DEV_PASS_ID_NOSPEC) + { + /* Device Password ID */ + *((PUSHORT) pData) = cpu2be16(WSC_ID_DEVICE_PWD_ID); + *((PUSHORT) (pData + 2)) = cpu2be16(0x0002); + *((PUSHORT) (pData + 4)) = cpu2be16(pAd->P2pCfg.Dpid); + pData += 6; + Len += 6; + } + + /* When PBC has triggered, done or connected with timeout, */ + /* we must change the value of SelReg. */ +#ifdef CONFIG_AP_SUPPORT + if ((pAd->ApCfg.MBSSID[BSS0].WscControl.WscSelReg) && (pAd->P2pCfg.Dpid == DEV_PASS_ID_PBC)) + { + if (P2P_GO_ON(pAd)) + { + /* 14. Selected Registrar */ + *((PUSHORT) pData) = cpu2be16(WSC_ID_SEL_REGISTRAR); + *((PUSHORT) (pData + 2)) = cpu2be16(0x0001); + *(pData + 4) = pAd->ApCfg.MBSSID[BSS0].WscControl.WscSelReg; /* AP */ + pData += 5; + Len += 5; + + /* Device Password ID (append it above) */ + /* 15. Selected Registrar Config Methods */ + *((PUSHORT) pData) = cpu2be16(WSC_ID_SEL_REG_CFG_METHODS); + *((PUSHORT) (pData + 2)) = cpu2be16(0x0002); + *((PUSHORT) (pData + 4)) = cpu2be16(0x18c); /* Support All : PBC, Keypad, Label, Display */ + pData += 6; + Len += 6; + + DBGPRINT(RT_DEBUG_INFO, ("P2pMakeProbeRspWSCIE: SelReg=1 \n")); + } + } +#endif /* CONFIG_AP_SUPPORT */ + } + + /* update the total length in vendor specific IE */ + *(pOutBuf+1) = Len - 2; + + /* fill in output buffer */ + *pIeLen = Len; +} + +/* + ======================================================================== + + Routine Description: + Make WSC IE for the ProbeReq frame for P2P Spec requirement + + Arguments: + pAdapter - NIC Adapter pointer + pOutBuf - all of WSC IE field + pIeLen - length + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + None + + ======================================================================== +*/ +VOID P2pMakeProbeReqIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pOutBuf, + OUT PUCHAR pIeLen) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + UCHAR WscIEFixed[] = {0xdd, 0x0e, 0x00, 0x50, 0xf2, 0x04}; /* length will modify later */ + UCHAR Len; + PUCHAR pData; + PWSC_REG_DATA pReg; + PWSC_DEV_INFO pDevInfo; + UCHAR OutMsgBuf[512]; + + + pReg = (PWSC_REG_DATA) &pAd->StaCfg.WscControl.RegData; + + /* Role play, Enrollee or Registrar */ + pDevInfo = (PWSC_DEV_INFO) &pReg->SelfInfo; + + pData = (PUCHAR) &OutMsgBuf[0]; + Len = 0; + *pIeLen = 0; + + /* 0. WSC fixed IE */ + RTMPMoveMemory(pData, &WscIEFixed[0], 6); + pData += 6; + Len += 6; + + /* 1. Version */ + *((PUSHORT) pData) = cpu2be16(WSC_ID_VERSION); + *((PUSHORT) (pData + 2)) = cpu2be16(0x0001); + *(pData + 4) = pDevInfo->Version; + pData += 5; + Len += 5; + + /* 2. Request Type */ + *((PUSHORT) pData) = cpu2be16(WSC_ID_REQ_TYPE); + *((PUSHORT) (pData + 2)) = cpu2be16(0x0001); + *(pData + 4) = ((pAd->StaCfg.WscControl.WscConfMode == WSC_REGISTRAR) ? WSC_MSGTYPE_AP_WLAN_MGR : WSC_MSGTYPE_ENROLLEE_OPEN_8021X ); + pData += 5; + Len += 5; + + /* 3. Config method */ + *((PUSHORT) pData) = cpu2be16(WSC_ID_CONFIG_METHODS); + *((PUSHORT) (pData + 2)) = cpu2be16(0x0002); + *((PUSHORT) (pData + 4)) = cpu2be16(0x188);/* Keypad, Display, PBC */ + pData += 6; + Len += 6; + + /* 4. UUID-(E or R) */ + *((PUSHORT) pData) = ((pAd->StaCfg.WscControl.WscConfMode == WSC_REGISTRAR) ? cpu2be16(WSC_ID_UUID_R) : cpu2be16(WSC_ID_UUID_E)); + *((PUSHORT) (pData + 2)) = cpu2be16(0x0010); + NdisMoveMemory((pData + 4), pDevInfo->Uuid, 16); + pData += 20; + Len += 20; + + /* 5. Primary device type */ + *((PUSHORT) pData) = cpu2be16(WSC_ID_PRIM_DEV_TYPE); + *((PUSHORT) (pData + 2)) = cpu2be16(0x0008); + NdisMoveMemory((pData + 4), pP2PCtrl->DevInfo.PriDeviceType, 8); + pData += 12; + Len += 12; + + /* 6. Primary device name */ + *((PUSHORT) pData) = cpu2be16(WSC_ID_DEVICE_NAME); + *((PUSHORT) (pData + 2)) = cpu2be16(pP2PCtrl->DeviceNameLen); + NdisMoveMemory((pData + 4), pP2PCtrl->DeviceName, pP2PCtrl->DeviceNameLen); + pData += (pP2PCtrl->DeviceNameLen + 4); + Len += (pP2PCtrl->DeviceNameLen + 4); + + /* 13. DPID shall be a required attribute if Credentials are available and ready for immediate use. */ + { + USHORT Dpid = 0x188; + /* Device Password ID */ + *((PUSHORT) pData) = cpu2be16(WSC_ID_DEVICE_PWD_ID); + *((PUSHORT) (pData + 2)) = cpu2be16(0x0002); + *((PUSHORT) (pData + 4)) = cpu2be16(Dpid); + pData += 6; + Len += 6; + } + + /* update the total length in vendor specific IE */ + OutMsgBuf[1] = Len - 2; + + /* fill in output buffer */ + *pIeLen = Len; + NdisMoveMemory(pOutBuf, &OutMsgBuf[0], *pIeLen); + + +} + +/* + ========================================================================== + Description: + Prepare Probe reqeust or response frame when opeartin as P2P DEvice. + + Parameters: + pDest : buffer to put frame content. + pFrameLen : frame length. + Note: + + ========================================================================== + */ +VOID P2PMakeProbe( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem, + IN UCHAR DsChannel, + IN USHORT SubType, + OUT PUCHAR pDest, + OUT ULONG *pFrameLen) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PUCHAR pOutBuffer = pDest; + UCHAR Addr2[6]; + PHEADER_802_11 pHeader; + HEADER_802_11 ProbeRspHdr; + UCHAR RSNIe=IE_WPA2;/*, RSNIe2=IE_WPA2, RSN_Len=22; */ + UCHAR tmpSupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR tmpExtRateLen; + LARGE_INTEGER FakeTimestamp; + UCHAR DsLen = 1, SsidLen = 0; + ULONG TmpLen; + ULONG FrameLen = 0; + /*UCHAR ErpIeLen = 1; */ + /*UCHAR P2pIEFixed[6] = {0xdd, 0x08, 0x00, 0x50, 0xf2, 0x09}; */ /* length will modify later */ + USHORT CapabilityInfo; + UCHAR SupRateLen; + PUCHAR ptr; + + pHeader = (PHEADER_802_11) &Elem->Msg[0]; + RTMPMoveMemory(Addr2, pHeader->Addr2, 6); + + if (SubType== SUBTYPE_PROBE_RSP) + { + DBGPRINT(RT_DEBUG_INFO, ("SYNC - P2PMakeProbeRsp. Addr2 = %02x:%02x:%02x:%02x:%02x:%02x...\n", PRINT_MAC(Addr2))); + MgtMacHeaderInit(pAd,&ProbeRspHdr, SUBTYPE_PROBE_RSP, 0, Addr2, +#ifdef P2P_SUPPORT + pP2PCtrl->CurrentAddress, +#endif /* P2P_SUPPORT */ + pP2PCtrl->CurrentAddress); + } + else + MgtMacHeaderInit(pAd, &ProbeRspHdr, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, +#ifdef P2P_SUPPORT + pP2PCtrl->CurrentAddress, +#endif /* P2P_SUPPORT */ + BROADCAST_ADDR); + + NdisMoveMemory(tmpSupRate,pAd->CommonCfg.SupRate,pAd->CommonCfg.SupRateLen); + tmpExtRateLen = pAd->CommonCfg.ExtRateLen; + + /* P2P device's probe response need to set both ess and ibss bit to zero. */ + CapabilityInfo = CAP_GENERATE(0, 0, 1, 0, 0, 0); + if (P2P_GO_ON(pAd)) + CapabilityInfo = CAP_GENERATE(1, 0, 1, 0, 0, 0); + + tmpSupRate[0] = 0x8C; /* 6 mbps, in units of 0.5 Mbps, basic rate */ + tmpSupRate[1] = 0x12; /* 9 mbps, in units of 0.5 Mbps */ + tmpSupRate[2] = 0x98; /* 12 mbps, in units of 0.5 Mbps, basic rate */ + tmpSupRate[3] = 0x24; /* 18 mbps, in units of 0.5 Mbps */ + tmpSupRate[4] = 0xb0; /* 24 mbps, in units of 0.5 Mbps, basic rate */ + tmpSupRate[5] = 0x48; /* 36 mbps, in units of 0.5 Mbps */ + tmpSupRate[6] = 0x60; /* 48 mbps, in units of 0.5 Mbps */ + tmpSupRate[7] = 0x6c; /* 54 mbps, in units of 0.5 Mbps */ + SupRateLen = 8; + tmpExtRateLen = pAd->CommonCfg.ExtRateLen; + + if (DsChannel == 0) + DBGPRINT(RT_DEBUG_ERROR, ("SYNC - P2PMakeProbeRsp. DsChannel = is 0 !!!!!\n")); + + if (SubType == SUBTYPE_PROBE_RSP) + { + SsidLen = WILDP2PSSIDLEN; + if (P2P_GO_ON(pAd)) + SsidLen = pP2PCtrl->SSIDLen; + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &ProbeRspHdr, + TIMESTAMP_LEN, &FakeTimestamp, + 2, &pAd->CommonCfg.BeaconPeriod, + 2, &CapabilityInfo, + 1, &SsidIe, + 1, &SsidLen, + SsidLen, pP2PCtrl->SSID, + 1, &SupRateIe, + 1, &SupRateLen, + SupRateLen, tmpSupRate, + END_OF_ARGS); + } + else + { + SsidLen = WILDP2PSSIDLEN; + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &ProbeRspHdr, + 1, &SsidIe, + 1, &SsidLen, + SsidLen, &WILDP2PSSID[0], + 1, &SupRateIe, + 1, &SupRateLen, + SupRateLen, tmpSupRate, + END_OF_ARGS); + + } + + if ((DsChannel > 0) && (DsChannel <= 14)) + { + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &DsIe, + 1, &DsLen, + 1, &DsChannel, + END_OF_ARGS); + FrameLen += TmpLen; + } + + /* Add this IE after I already become GO. */ + if (tmpExtRateLen && (P2P_GO_ON(pAd))) + { + } + + /* Msut append RSN_IE because P2P uses WPA2PSK. */ + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &RSNIe, + 1, &pAd->StaCfg.RSNIE_Len, + pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, + END_OF_ARGS); + FrameLen += TmpLen; + } + +/* + + // add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back + if (pAd->CommonCfg.bAggregationCapable) + { + if ((pAd->CommonCfg.bPiggyBackCapable)) + { + UCHAR RalinkSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x07, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkSpecificIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + else + { + UCHAR RalinkSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x05, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkSpecificIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + } + else + { + UCHAR RalinkSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x06, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkSpecificIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + + if ((pP2PCtrl->P2pPhyMode != P2P_PHYMODE_LEGACY_ONLY)) + { + UCHAR HtLen, AddHtLen, NewExtLen; + ADD_HT_INFO_IE AddHTInfo; // Useful as AP. + + HT_CAPABILITY_IE HtCapability; + NdisMoveMemory(&HtCapability, &pAd->ApCfg.HtCapability, sizeof(HT_CAPABILITY_IE)); + if (pAd->Antenna.field.RxPath > 1) + { + HtCapability.MCSSet[1] = 0xff; + } + else + { + HtCapability.MCSSet[1] = 0x00; + } + + HtLen = sizeof(pAd->ApCfg.HtCapability); + AddHtLen = sizeof(pAd->ApCfg.AddHTInfoIe); + NewExtLen = 1; + + NdisMoveMemory(&AddHTInfo, &pAd->ApCfg.AddHTInfoIe, sizeof(ADD_HT_INFO_IE)); + + //New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &HtLen, + sizeof(HT_CAPABILITY_IE), &HtCapability, + 1, &AddHtInfoIe, + 1, &AddHtLen, + sizeof(ADD_HT_INFO_IE), &AddHTInfo, + 1, &NewExtChanIe, + 1, &NewExtLen, + sizeof(NEW_EXT_CHAN_IE), &pAd->CommonCfg.NewExtChanOffset, + END_OF_ARGS); + FrameLen += TmpLen; + } + */ + /* New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame */ + + P2pMakeProbeRspWSCIE(pAd, pOutBuffer + FrameLen, &TmpLen); + FrameLen += TmpLen; + + ptr = pOutBuffer + FrameLen; + P2pMakeP2pIE(pAd, (UCHAR)SubType, ptr, &TmpLen); + FrameLen += TmpLen; + *pFrameLen = FrameLen; + +} + +/* + ========================================================================== + Description: + Make P2P IE. + + Parameters: + reutrn IE lenght and buffer. + Note: + + ========================================================================== + */ +VOID P2pMakeP2pIE( + IN PRTMP_ADAPTER pAd, + IN UCHAR PacketType, + OUT PUCHAR pOutBuf, + OUT PULONG pIeLen) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + UCHAR P2pIEFixed[6] = {0xdd, 0x0e, 0x00, 0x50, 0xf2, 0x09}; /* length will modify later */ + ULONG Len; + PUCHAR pData; + ULONG TempLen; + UCHAR Status; + /*UCHAR Maganed; */ + UCHAR P2pCapability[2]; + PUCHAR pBuf; + + RTMPMoveMemory(&P2pIEFixed[2], P2POUIBYTE, 4); + pData = pOutBuf; + Len = 0; + *pIeLen = 0; + /* 0. P2P fixed IE */ + RTMPMoveMemory(pData, &P2pIEFixed[0], 6); + pData += 6; + Len += 6; + + P2pCapability[0] = pAd->P2pCfg.P2pCapability[0]; + P2pCapability[1] = pAd->P2pCfg.P2pCapability[1]; + + /* : . + */ + if (PacketType == SUBTYPE_ASSOC_RSP) + { + Status = P2PSTATUS_SUCCESS; + TempLen = InsertP2PSubelmtTlv(pAd, SUBID_P2P_STATUS, &Status, pData); + Len += TempLen; + pData += TempLen; + + if (IS_P2P_SUPPORT_EXT_LISTEN(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("P2pMakeP2pIE (PacketType = %d) insert SUBID_P2P_EXT_LISTEN_TIMING .\n", PacketType)); + TempLen = InsertP2PSubelmtTlv(pAd, SUBID_P2P_EXT_LISTEN_TIMING, NULL, pData); + Len += TempLen; + pData += TempLen; + } + + /* this is managed infra STA connect to Infra AP. So Add P2P Interface. then this's all. return here. */ + DBGPRINT(RT_DEBUG_TRACE, ("<----- P2pMakeP2pIE For managed STA. (Len = %ld) \n", Len)); + *(pOutBuf+1) = (Len-2); + *pIeLen = Len; + return; + } + + /* Conenct to Managed AP. */ + if ((pP2PCtrl->P2pManagedParm.TotalNumOfP2pAttribute > 0) && + (PacketType == SUBTYPE_ASSOC_REQ)) + { + /* Always support Managed when connecting using Assoc Req. */ + P2pCapability[0] |= DEVCAP_INFRA_MANAGED; + /* If the cross connect is enabled, check whether we need to turn off it because Managed AP Asks us to do so. */ + /* If already turned off, no need to check. */ + if ((!P2P_TEST_BIT(P2pCapability[1], GRPCAP_CROSS_CONNECT)) + && RTMPEqualMemory(pP2PCtrl->Bssid, pAd->P2pCfg.P2pManagedParm.ManageAPBSsid, MAC_ADDR_LEN)) + { + DBGPRINT(RT_DEBUG_TRACE, ("pAd->P2pCfg.P2pManagedParm.APP2pManageability = %x \n", pAd->P2pCfg.P2pManagedParm.APP2pManageability)); + /* If This is the 1st Managed AP that I just want to connect to, but now I don't turn off the cross connect bit yet. */ + /* I have to turn off this bit when connecting to this AP. */ + if ((pAd->P2pCfg.P2pManagedParm.APP2pManageability != 0xff) + && (P2P_TEST_BIT(pAd->P2pCfg.P2pManagedParm.APP2pManageability, P2PMANAGED_ENABLE_BIT)) + && (!P2P_TEST_BIT(pAd->P2pCfg.P2pManagedParm.APP2pManageability, P2PMANAGED_ICS_ENABLE_BIT))) + { + P2pCapability[1] &= (~GRPCAP_CROSS_CONNECT); + DBGPRINT(RT_DEBUG_TRACE, ("Turn off Corss Conenct bit in Assoc Req. %x \n", (~GRPCAP_CROSS_CONNECT))); + } + } + + TempLen = InsertP2PSubelmtTlv(pAd, SUBID_P2P_CAP, P2pCapability, pData); + Len += TempLen; + pData += TempLen; + TempLen = InsertP2PSubelmtTlv(pAd, SUBID_P2P_INTERFACE, pP2PCtrl->CurrentAddress, pData); + Len += TempLen; + pData += TempLen; + /* this is managed infra STA connect to Infra AP. So Add P2P Interface. then this's all. return here. */ + DBGPRINT(RT_DEBUG_ERROR, ("<-----P2pMakeP2pIE For managed STA. (Len = %ld PacketType = %d.) \n", Len, PacketType)); + *(pOutBuf+1) = (Len-2); + *pIeLen = Len; + return; + } + + if (IS_CLIENT_DISCOVERY_ON(pAd)) + { + P2pCapability[0] |= DEVCAP_CLIENT_DISCOVER; + } + + if (PacketType == SUBTYPE_PROBE_REQ) + { + /* Probe Request Group Capability bit is reserved. (TestPlan 4.1.1) */ + P2pCapability[1] = 0; + } + + pBuf = &P2pCapability[0]; + TempLen = InsertP2PSubelmtTlv(pAd, SUBID_P2P_CAP, pBuf, pData); + Len += TempLen; + pData += TempLen; + + /*if ((PortSubtype == PORTSUBTYPE_P2PClient) */ + if ((pP2PCtrl->Rule == P2P_IS_CLIENT) || (pP2PCtrl->Rule == P2P_IS_DEVICE) + || (PacketType == SUBTYPE_PROBE_REQ)) + { + /* Doesn't need to specify who I am searching for. So delete */ + } + else + { + TempLen = InsertP2PSubelmtTlv(pAd, SUBID_P2P_DEVICE_ID, pP2PCtrl->CurrentAddress, pData); + Len += TempLen; + pData += TempLen; + } + if (PacketType == SUBTYPE_PROBE_REQ) + { + if (INFRA_ON(pAd)) + pBuf = &pAd->CommonCfg.Channel; + else + pBuf = &pP2PCtrl->ListenChannel; + TempLen = InsertP2PSubelmtTlv(pAd, SUBID_P2P_LISTEN_CHANNEL, pBuf, pData); + Len += TempLen; + pData += TempLen; + + /*if (pP2PCtrl->PortSubtype == PORTSUBTYPE_P2PGO) */ + if (pP2PCtrl->Rule == P2P_IS_GO) + { + if (INFRA_ON(pAd)) + pBuf = &pAd->CommonCfg.Channel; + else + pBuf = &pP2PCtrl->GroupChannel; + TempLen = InsertP2PSubelmtTlv(pAd, SUBID_P2P_OP_CHANNEL, pBuf, pData); + Len += TempLen; + pData += TempLen; + } + + } + if ((PacketType == SUBTYPE_PROBE_RSP) || (PacketType == SUBTYPE_ASSOC_REQ) || (PacketType == SUBTYPE_REASSOC_REQ)) + { + if (PacketType == SUBTYPE_ASSOC_REQ) + { + DBGPRINT(RT_DEBUG_INFO, (" P2pMakeP2pIE (PacketType = %d) insert SUBID_P2P_DEVICE_INFO. DeviceNameLen = %ld.\n", PacketType, pAd->P2pCfg.DeviceNameLen)); + } + TempLen = InsertP2PSubelmtTlv(pAd, SUBID_P2P_DEVICE_INFO, pP2PCtrl->CurrentAddress, pData); + Len += TempLen; + pData += TempLen; + } + + if (((PacketType == SUBTYPE_PROBE_RSP) || (PacketType == SUBTYPE_PROBE_REQ) || (PacketType == SUBTYPE_ASSOC_RSP)) + && (IS_EXT_LISTEN_ON(pAd))) + { + DBGPRINT(RT_DEBUG_INFO, ("P2pMakeP2pIE (PacketType = %d) insert SUBID_P2P_EXT_LISTEN_TIMING .\n", PacketType)); + TempLen = InsertP2PSubelmtTlv(pAd, SUBID_P2P_EXT_LISTEN_TIMING, NULL, pData); + Len += TempLen; + pData += TempLen; + } + + if (P2P_GO_ON(pAd) && (PacketType == SUBTYPE_PROBE_RSP)) + { + /* If I am GO, must insert Group Info in my probe response to Probe Request that has P2P IE. */ + TempLen = InsertP2PGroupInfoTlv(pAd, pData); + Len += TempLen; + pData += TempLen; + } + + /* The NoA has its own P2P IE. So NoA Attribute lenght doesn't count here. */ + *(pOutBuf+1) = (Len-2); + + if (P2P_GO_ON(pAd) && (pAd->P2pCfg.GONoASchedule.bValid == TRUE)) + { + TempLen = P2pUpdateNoAProbeRsp(pAd, pData); + Len += TempLen; + pData += TempLen; + } + else if (P2P_GO_ON(pAd) && (P2P_TEST_BIT(pAd->P2pCfg.CTWindows, P2P_OPPS_BIT))) + { + TempLen = P2pUpdateNoAProbeRsp(pAd, pData); + Len += TempLen; + pData += TempLen; + } + + DBGPRINT(RT_DEBUG_INFO, ("<----- P2pMakeP2pIE (Len = %ld) \n", Len)); + *pIeLen = Len; +} + +/* + ========================================================================== + Description: + Processing WSC IE and put to OUTPUT buffer. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2PParseWPSIE( + IN PUCHAR pWpsData, + IN USHORT WpsLen, + OUT PUSHORT Dpid, + OUT PUSHORT ConfigMethod, + OUT PUCHAR DeviceName, + OUT UCHAR *DeviceNameLen) +{ + USHORT Length; + PUCHAR pData; + USHORT WscType, WscLen; + + if (pWpsData == NULL) + return; + + if (DeviceNameLen !=NULL) + *DeviceNameLen = 0; + pData = pWpsData+4; /*pWpsData+6;*/ + Length = WpsLen - 6; + + if (pData == NULL) + return; + + /* Start to process WSC IEs */ + while (Length > 4) + { + WscType = cpu2be16(*((PUSHORT) pData)); + WscLen = cpu2be16(*((PUSHORT) (pData + 2))); + pData += 4; + Length -= 4; + + /* Parse M1 WSC type and store to RegData structure */ + switch (WscType) + { + case WSC_ID_DEVICE_NAME: /* 1 */ + if (DeviceName !=NULL) + { + RTMPMoveMemory(DeviceName, pData, 32); + if (DeviceNameLen !=NULL) + *DeviceNameLen = (UCHAR)WscLen; + DBGPRINT(RT_DEBUG_INFO,("%s : DeviceName = %c%c%c%c%c ...\n", __FUNCTION__, DeviceName[0], DeviceName[1], DeviceName[2],DeviceName[3],DeviceName[4])); + } + break; + case WSC_ID_DEVICE_PWD_ID: /* 1 */ + if (Dpid !=NULL) + { + *Dpid = be2cpu16(*((USHORT *) pData)); + /**Dpid = *((PUSHORT) pData); */ + DBGPRINT(RT_DEBUG_INFO,("%s : Dpid = %s .\n", __FUNCTION__, decodeDpid(*Dpid))); + } + break; + case WSC_ID_CONFIG_METHODS: /* 1 */ + if (ConfigMethod !=NULL) + { + *ConfigMethod = be2cpu16(*((PUSHORT) pData)); + DBGPRINT(RT_DEBUG_INFO,(" Config = %x ..\n", *ConfigMethod)); + } + break; + default: + /*DBGPRINT(RT_DEBUG_TRACE, ("WscRecvMessageM1 --> Unknown IE 0x%04x\n", WscType)); */ + break; + } + + /* Offset to net WSC Ie */ + pData += WscLen; + Length -= WscLen; + } + +} + +/* + ========================================================================== + Description: + Go PeerDisassocReq Action. + + Parameters: + Note: + + ========================================================================== + */ +VOID GoPeerDisassocReq( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr2) +{ + /* Set to a temporary state. If thie device connect within 25 seconds. he may use WPS to connect. */ + P2pGroupTabDelete(pAd, P2P_NOT_FOUND, Addr2); + + /* Don't Stop GO immediately. Give some time for this client to reconnect with 13 seconds. */ + /* when StopGo timer expired, */ +} + +/* + ========================================================================== + Description: + Update P2P beacon frame for P2P IE Group Info Attribute. + + Parameters: + Note: + + ========================================================================== + */ +ULONG P2pUpdateGroupBeacon( + IN PRTMP_ADAPTER pAd, + IN ULONG StartPosition) +{ + + return 0; +} + +/* + ========================================================================== + Description: + Update P2P beacon frame for P2P IE NoA Attribute. When I am GO. + + Parameters: + Note: + + ========================================================================== + */ +ULONG P2pUpdateNoABeacon( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx, +/* IN ULONG StartPosition) */ + IN PUCHAR pDest) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + /*PUCHAR pDest;*/ + UCHAR P2PIEFixed[] = {0xdd, 0x16, 0x00, 0x50, 0xf2, 0x09}; /* length will modify later */ + /*UCHAR i;*/ + /*PUCHAR ptr;*/ + + RTMPMoveMemory(&P2PIEFixed[2], P2POUIBYTE, 4); + DBGPRINT(RT_DEBUG_INFO, ("<---- %s\n", __FUNCTION__)); + if (pP2PCtrl->GONoASchedule.bValid == TRUE) + { + /*pDest = &pAd->BeaconBuf[StartPosition];*/ + /*PUCHAR pDest = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf;*/ + /* Always support attach one NoA.. So.. length is fixed to 0x16. :) */ + RTMPMoveMemory(pDest, P2PIEFixed, 6); + + *(pDest+6) = SUBID_P2P_NOA; + /* Length is 13*n + 2 = 15 when n = 1 */ + *(pDest+7) = 15; + /* Lenght 2nd byte */ + *(pDest+8) = 0; + /* Index. */ + *(pDest+9) = pP2PCtrl->GONoASchedule.Token; + /* CT Windows and OppPS parm */ + *(pDest+10) = pP2PCtrl->CTWindows; + /* Count. Test Plan set to 255. */ + *(pDest+11) = pP2PCtrl->GONoASchedule.Count; + /* Duration */ + RTMPMoveMemory((pDest+12), &pP2PCtrl->GONoASchedule.Duration, 4); + /* Interval */ + RTMPMoveMemory((pDest+16), &pP2PCtrl->GONoASchedule.Interval, 4); + RTMPMoveMemory((pDest+20), &pP2PCtrl->GONoASchedule.StartTime, 4); + pAd->GOBeaconBufNoALen = 24; + } + else + { + } + DBGPRINT(RT_DEBUG_INFO, ("----> %s\n", __FUNCTION__)); + + return pAd->GOBeaconBufNoALen; +} + +/* + ========================================================================== + Description: + Update P2P beacon frame for P2P IE NoA Attribute. When I am GO. + + Parameters: + Note: + + ========================================================================== + */ +ULONG P2pUpdateNoAProbeRsp( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pInbuffer) +{ + PUCHAR pDest; + UCHAR P2PIEFixed[6] = {0xdd, 0x16, 0x00, 0x50, 0xf2, 0x09}; /* length will modify later */ + /*UCHAR i; */ + /*PUCHAR ptr; */ + + RTMPMoveMemory(&P2PIEFixed[2], P2POUIBYTE, 4); + + if (pAd->P2pCfg.GONoASchedule.bValid == TRUE) + { + pDest = pInbuffer; + /* Always support attach one NoA.. So.. length is fixed to 0x16. :) */ + RTMPMoveMemory(pDest, P2PIEFixed, 6); + + *(pDest+6) = SUBID_P2P_NOA; + /* Length is 13*n + 2 = 15 when n = 1 */ + *(pDest+7) = 15; + /* Lenght 2nd byte */ + *(pDest+8) = 0; + /* Index. */ + *(pDest+9) = pAd->P2pCfg.GONoASchedule.Token; + /* CT Windows and OppPS parm. Don't turn on both. So Set CTWindows = 0 */ + *(pDest+10) = 0; + /* Count. Test Plan set to 255. */ + *(pDest+11) = pAd->P2pCfg.GONoASchedule.Count; + /* Duration */ + RTMPMoveMemory((pDest+12), &pAd->P2pCfg.GONoASchedule.Duration, 4); + /* Interval */ + RTMPMoveMemory((pDest+16), &pAd->P2pCfg.GONoASchedule.Interval, 4); + RTMPMoveMemory((pDest+20), &pAd->P2pCfg.GONoASchedule.StartTime, 4); + + return 24; + } + else if (P2P_TEST_BIT(pAd->P2pCfg.CTWindows, P2P_OPPS_BIT)) + { + P2PIEFixed[1] = 0x9; + pDest = pInbuffer; + RTMPMoveMemory(pDest, P2PIEFixed, 6); + *(pDest+6) = SUBID_P2P_NOA; + /* Length is 13*n + 2 = 15 when n = 1 */ + *(pDest+7) = 2; + /* Lenght 2nd byte */ + *(pDest+8) = 0; + /* Index. */ + *(pDest+9) = pAd->P2pCfg.GONoASchedule.Token; + /* CT Windows and OppPS parm */ + *(pDest+10) = pAd->P2pCfg.CTWindows; + return 11; + } + else + { + return 0; + } + + +} + +/* + ========================================================================== + Description: + Update P2P beacon frame and save to BeaconBuf[]. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pUpdateBssBeacon( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pCapability, + IN PUCHAR pIpReqP2ptabindex) +{ +} + +VOID GOUpdateBeaconFrame( + IN PRTMP_ADAPTER pAd) +{ + +} +/* + ========================================================================== + Description: + Make P2P beacon frame and save to BeaconBuf[] + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pMakeBssBeacon( + IN PRTMP_ADAPTER pAd) +{ +} + +/* + ======================================================================== + + Routine Description: + Check REinvoke's invitation Request frame . + + Arguments: + - NIC Adapter pointer + + Return Value: + FALSE - None of channel in ChannelList Match any channel in pAd->ChannelList[] array + + IRQL = DISPATCH_LEVEL + + Note: + ======================================================================== + +*/ +VOID P2pCheckInviteReq( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bIAmGO, + IN UCHAR index, + IN PUCHAR ChannelList, + IN PUCHAR BssidAddr, + IN UCHAR OpChannel, + IN PUCHAR Ssid, + IN UCHAR SsidLen, + IN UCHAR *pRspStatus) +{ + UCHAR i; + *pRspStatus = P2PSTATUS_SUCCESS; + /* Check if have Common Channels. */ + if (FALSE == P2pCheckChannelList(pAd, ChannelList)) + { + DBGPRINT(RT_DEBUG_ERROR, (" P2P - no common channel = %d...\n", *ChannelList)); + *pRspStatus = P2PSTATUS_NO_CHANNEL; + return; + } + /* Invite Req from a CLient doesn't includes group_bssid in the request. So doesn't need check. */ + /* Check Bssid is correct. */ + if (!RTMPEqualMemory(BssidAddr, pAd->P2pTable.PerstEntry[index].Addr, MAC_ADDR_LEN) + && (bIAmGO == FALSE)) + { + *pRspStatus = P2PSTATUS_INVALID_PARM; + DBGPRINT(RT_DEBUG_ERROR, (" P2P - MAc addr invalid .\n")); + return; + } + + /* invite Req from Owner include OpChannel. from Client, doesn't include. */ + if (bIAmGO == FALSE) + { + /* Check Oopchannel is correct. */ + for (i = 0;i < pAd->ChannelListNum;i++) + { + if (pAd->ChannelList[i].Channel == OpChannel) + { + break; + } + } + if ( i == pAd->ChannelListNum) + { + *pRspStatus = P2PSTATUS_NO_CHANNEL; + DBGPRINT(RT_DEBUG_ERROR, (" P2P - 2 P2PSTATUS_NO_CHANNEL .\n")); + return; + } + } + /* Check SSID is correct. */ + if ((SsidLen > 0) && (!RTMPEqualMemory(pAd->P2pTable.PerstEntry[index].Profile.SSID.Ssid, Ssid, SsidLen))) + { + DBGPRINT(RT_DEBUG_ERROR, ("Ssid1[%d] = %s. \n", SsidLen, Ssid)); + DBGPRINT(RT_DEBUG_ERROR, ("Ssid2[%d] = %s. \n", pAd->P2pTable.PerstEntry[index].Profile.SSID.SsidLength, pAd->P2pTable.PerstEntry[index].Profile.SSID.Ssid)); + *pRspStatus = P2PSTATUS_INVALID_PARM; + return; + } + +} + +/* + ======================================================================== + + Routine Description: + Check REinvoke's invitation Request frame . + + Arguments: + - NIC Adapter pointer + + Return Value: + FALSE - None of channel in ChannelList Match any channel in pAd->ChannelList[] array + + IRQL = DISPATCH_LEVEL + + Note: + ======================================================================== + +*/ +VOID P2pCheckInviteReqFromExisting( + IN PRTMP_ADAPTER pAd, + IN PUCHAR ChannelList, + IN PUCHAR BssidAddr, + IN UCHAR OpChannel, + IN PUCHAR Ssid, + IN UCHAR SsidLen, + IN UCHAR *pRspStatus) +{ + UCHAR i; + *pRspStatus = P2PSTATUS_SUCCESS; + /* Check if have Common Channels. */ + if (FALSE == P2pCheckChannelList(pAd, ChannelList)) + { + DBGPRINT(RT_DEBUG_ERROR, (" P2P - no common channel. Channel list is : %d...\n", ChannelList[0])); + *pRspStatus = P2PSTATUS_NO_CHANNEL; + return; + } + + /* invite Req from Owner include OpChannel. from Client, doesn't include. */ + if (OpChannel != 0) + { + /* Check Oopchannel is correct. */ + for (i = 0;i < pAd->ChannelListNum;i++) + { + if (pAd->ChannelList[i].Channel == OpChannel) + { + break; + } + } + if ( i == pAd->ChannelListNum) + { + *pRspStatus = P2PSTATUS_NO_CHANNEL; + DBGPRINT(RT_DEBUG_ERROR, (" P2P - No channel = %d...\n", OpChannel)); + return; + } + } + + /* Check SSID is correct. */ + if ((SsidLen == 0)) + { + DBGPRINT(RT_DEBUG_ERROR, (" P2P - Ssidlen Zero = %d...\n", SsidLen)); + *pRspStatus = P2PSTATUS_INVALID_PARM; + return; + } + +} + +UCHAR ChannelToClass( + IN UCHAR Channel, + IN UCHAR Country) +{ + UCHAR ReturnClass = 1; + if (Country == 1/*COUNTRY_USA*/) + { + /* 0. Decide current regulatory class. P802.11REVmb_D3.0.pdf. TableJ-4 */ + if (Channel <= 11) + { + ReturnClass = 81; + } + else if (Channel <= 48) + { + ReturnClass = 115; /* Atheros suggest to use 1 2010-May */ + } + else if (Channel <= 64) + { + ReturnClass = 118; + } + else if (Channel <= 140) + { + ReturnClass = 121; + } + else if ((Channel == 165) || (Channel == 169)) + { + ReturnClass = 125; + } + else + { + /* 3 when channels are 149.153. 157. 161 */ + ReturnClass = 124; + } + } + return ReturnClass; +} + + diff --git a/mt7620/src/common/p2p_table.c b/mt7620/src/common/p2p_table.c new file mode 100644 index 0000000..c3b6a9f --- /dev/null +++ b/mt7620/src/common/p2p_table.c @@ -0,0 +1,1432 @@ +/* + *************************************************************************** + * 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: + p2p.c + + Abstract: + Peer to peer is also called Wifi Direct. This function handles P2P table management. also include persistent table that saves credential. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Jan Lee 2010-05-21 created for Peer-to-Peer Action frame(Wifi Direct) +*/ +#include "rt_config.h" + +extern UCHAR ZeroSsid[]; + +/* + ========================================================================== + Description: + GUI needs to update whole Persistent table to driver after reload of driver. + + Parameters: + S - pointer to the association state machine + Note: + The state machine looks like the following as name implies its function + ========================================================================== + */ +VOID P2pSetPerstTable( + IN PRTMP_ADAPTER pAd, + IN PVOID pInformationBuffer) +{ + POID_P2P_PERSISTENT_TABLE pP2pPerstTab; + UCHAR i; + + pP2pPerstTab = (POID_P2P_PERSISTENT_TABLE)pInformationBuffer; + DBGPRINT(RT_DEBUG_TRACE,("P2pSetPerstTable Num = %d \n", pP2pPerstTab->PerstNumber)); + pAd->P2pTable.PerstNumber = pP2pPerstTab->PerstNumber; + + if (pAd->P2pTable.PerstNumber == 0) + { + for (i = 0; i < MAX_P2P_TABLE_SIZE;i++) + { + pAd->P2pTable.PerstEntry[i].bValid = FALSE; + } + } + + for (i = 0; i < 1; i++) + { + RTMPMoveMemory(&pAd->P2pTable.PerstEntry[i], &pP2pPerstTab->PerstEntry[i], sizeof(RT_P2P_PERSISTENT_ENTRY)); + P2PPrintP2PPerstEntry(pAd, i ); + } + +} + +/* + ========================================================================== + Description: + This is a periodic routine that check P2P Group Table's Status. One importatn task is to check if some frame + that need transmission result is success or retry fail. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pGroupMaintain( + IN PRTMP_ADAPTER pAd) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + UCHAR i; + PRT_P2P_CLIENT_ENTRY pP2pEntry; + ULONG Data; + /*UCHAR Value;*/ + /*BCN_TIME_CFG_STRUC csr;*/ + BOOLEAN bAllPsm = TRUE; + + if (pP2PCtrl->GONoASchedule.bValid == TRUE) + { + /* Disable OppPS when NoA is ON. */ + P2pStopOpPS(pAd); + RTMP_IO_READ32(pAd, TSF_TIMER_DW1, &Data); + if (Data != pP2PCtrl->GONoASchedule.TsfHighByte) + { + DBGPRINT(RT_DEBUG_ERROR, ("P2pGroupMaintain. Tsf MSB changed to %ld from %ld. restart NoA . \n",Data, pP2PCtrl->GONoASchedule.TsfHighByte )); + /* I want to resume the NoA */ + pP2PCtrl->GONoASchedule.bNeedResumeNoA = TRUE; + P2pStopNoA(pAd, NULL); + /* Ok. Now resume it. */ + pP2PCtrl->GONoASchedule.bNeedResumeNoA = FALSE; + P2pGOStartNoA(pAd); + } + + } + else if ((P2P_GO_ON(pAd)) && (pP2PCtrl->GONoASchedule.bValid == FALSE) + && (IS_OPPS_ON(pAd))) + { + /* Since NoA is OFF, consider to enable OppPS. */ + for (i = 0; i < MAX_LEN_OF_MAC_TABLE;i++) + { + PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i]; + + if (IS_ENTRY_CLIENT(pEntry) + && (pEntry->PsMode == PWR_ACTIVE)) + { + bAllPsm = FALSE; + break; + } + } + if ((bAllPsm == TRUE) && (pAd->MacTab.Size > 0)) + { + /* bit 7 is OppPS bit. set 1 to enable. bit [0:6] is in unit TU. */ + if (IS_OPPS_ON(pAd)) + { + P2pStartOpPS(pAd); + pP2PCtrl->CTWindows = 0x8a; + } + /* case 2 to turn on CTWindows. Not decide the case 2 rule yet. 2010-June */ + else if (0) + { + pP2PCtrl->CTWindows = 0x8a; + } + } + else if (P2P_TEST_BIT(pAd->P2pCfg.CTWindows, P2P_OPPS_BIT)) + { + P2pStopOpPS(pAd); + } + } + + if (pP2PCtrl->p2pidxForServiceCbReq < MAX_P2P_GROUP_SIZE) + { + if (pAd->P2pTable.Client[pAd->P2pCfg.p2pidxForServiceCbReq].ConfigTimeOut > 0) + pAd->P2pTable.Client[pAd->P2pCfg.p2pidxForServiceCbReq].ConfigTimeOut--; + if (pAd->P2pTable.Client[pAd->P2pCfg.p2pidxForServiceCbReq].P2pClientState == P2PSTATE_SERVICE_COMEBACK_COMMAND + && (pAd->P2pTable.Client[pAd->P2pCfg.p2pidxForServiceCbReq].ConfigTimeOut == 0)) + { + /*P2pSendComebackReq(pAd, pAd->P2pCfg.p2pidxForServiceCbReq, pAd->P2pTable.Client[pAd->P2pCfg.p2pidxForServiceCbReq].addr); */ + pP2PCtrl->p2pidxForServiceCbReq = MAX_P2P_GROUP_SIZE; + } + } + + if (IS_PERSISTENT_ON(pAd) + && (!P2P_GO_ON(pAd)) + && (!P2P_CLI_ON(pAd))) + { + for (i = 0; i < MAX_P2P_GROUP_SIZE; i++) + { + pP2pEntry = &pAd->P2pTable.Client[i]; + /* Add some delay to connect to Persistent GO. Because some GO like broadcom need configuration time to start GO. */ + if ((pP2pEntry->P2pClientState == P2PSTATE_REINVOKEINVITE_TILLCONFIGTIME)) + { + if (pP2pEntry->ConfigTimeOut > 0) + pP2pEntry->ConfigTimeOut--; + if (pP2pEntry->ConfigTimeOut == 0) + { + pP2PCtrl->P2PConnectState = P2P_DO_WPS_ENROLLEE; + pP2pEntry->P2pClientState = P2PSTATE_GO_WPS; + P2pWpsDone(pAd, pP2pEntry->addr); + } + } + } + } + + if (P2P_GO_ON(pAd)) + { + for (i = 0; i < MAX_P2P_GROUP_SIZE; i++) + { + pP2pEntry = &pAd->P2pTable.Client[i]; + if (pP2pEntry->P2pClientState == P2PSTATE_WAIT_GO_DISCO_ACK_SUCCESS) + { + ULONG TotalFrameLen; + DBGPRINT(RT_DEBUG_TRACE,("P2P P2PSTATE_WAIT_GO_DISCO_ACK_SUCCESS \n")); + + P2PSendDevDisRsp(pAd, P2PSTATUS_SUCCESS, pAd->P2pCfg.LatestP2pPublicFrame.Token, pAd->P2pCfg.LatestP2pPublicFrame.p80211Header.Addr2, &TotalFrameLen); + pP2pEntry->P2pClientState = P2PSTATE_CLIENT_OPERATING; + } + else if ((pP2pEntry->P2pClientState == P2PSTATE_PROVISION_COMMAND) || (pP2pEntry->P2pClientState == P2PSTATE_INVITE_COMMAND)) + { + if (pP2pEntry->StateCount > 0) + { + /*DBGPRINT(RT_DEBUG_ERROR, ("pEntry[%d] StateCount = %d\n", i, pP2pEntry->StateCount)); */ + pP2pEntry->StateCount--; + } + + if ((pP2pEntry->StateCount == 0) && (pP2pEntry->bValid)) + { + if (pP2pEntry->ReTransmitCnt >= 20) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s:: ReTransmit Probe Req. limit! stop connect this p2p device!\n", + __FUNCTION__)); + P2pLinkDown(pAd, P2P_DISCONNECTED); + pP2pEntry->ReTransmitCnt = 0; + } + pP2pEntry->ReTransmitCnt++; + DBGPRINT(RT_DEBUG_TRACE, ("P2P Table : idx=%d Send Probe Req. \n", i)); + P2pSendProbeReq(pAd, pP2pEntry->ListenChannel); + } + } + } + } + /* time out case. */ + else if ((pP2PCtrl->P2PConnectState == P2P_DO_GO_SCAN_BEGIN) + && (pP2PCtrl->P2pCounter.GoScanBeginCounter100ms > 1200 /*GOSCANBEGINCOUNTER_MAX*/)) + { + DBGPRINT(RT_DEBUG_TRACE, ("P2P_DO_GO_SCAN_BEGIN Timeout. BAck to idle. \n")); + pP2PCtrl->P2PConnectState = P2P_CONNECT_IDLE; + } + else if ((pAd->flg_p2p_OpStatusFlags == 0) && + (!MAC_ADDR_EQUAL(&ZERO_MAC_ADDR, &pP2PCtrl->ConnectingMAC))) + { + for (i = 0; i < MAX_P2P_GROUP_SIZE; i++) + { + pP2pEntry = &pAd->P2pTable.Client[i]; + if (pP2pEntry->P2pClientState == P2PSTATE_NONE) + continue; + if ((pP2pEntry->P2pClientState >= P2PSTATE_SENT_GO_NEG_REQ) && + (pP2pEntry->P2pClientState <= P2PSTATE_WAIT_GO_COMFIRM_ACK)) + { + if (pP2pEntry->StateCount > 0) + { + /*DBGPRINT(RT_DEBUG_ERROR, ("pEntry[%d] StateCount = %d\n", i, pP2pEntry->StateCount)); */ + pP2pEntry->StateCount--; + } + if ((pP2pEntry->StateCount == 0) && ((pP2pEntry->bValid))) + { + if (pP2pEntry->ReTransmitCnt >= 20) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s:: [%s] ReTransmit Probe Req. limit! stop connect this p2p device!\n", + __FUNCTION__, decodeP2PClientState(pP2pEntry->P2pClientState))); + P2pStopConnectThis(pAd); + P2P_WSC_CONF_MTHD_DEFAULT(pAd); + pP2pEntry->ReTransmitCnt = 0; + } + /*pP2pEntry->P2pClientState = P2PSTATE_CONNECT_COMMAND; */ + /*pP2PCtrl->P2PConnectState = P2P_CONNECT_IDLE; */ + /*pP2PCtrl->P2pCounter.Counter100ms = 0; */ + pP2pEntry->StateCount = 50; + pP2pEntry->ReTransmitCnt++; + DBGPRINT(RT_DEBUG_ERROR, ("P2P Table : idx=%d Go Nego Req Retry. \n", i)); + P2pSendProbeReq(pAd, pP2pEntry->ListenChannel); + } + + } + else if (pP2pEntry->P2pClientState == P2PSTATE_GO_COMFIRM_ACK_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR, ("P2P Table : idx=%d Get Confirm Ask Success. p2pState = %d.\n", i, pP2PCtrl->P2PConnectState)); + /* Don't leet ClientState keep in P2PSTATE_GO_COMFIRM_ACK_SUCCESS, */ + /* Or will keep calling P2pGoNegoDone(). */ + /* ClientState will be updated when GO receiving AuthReq. */ + pP2pEntry->P2pClientState = P2PSTATE_GOT_GO_COMFIRM; + P2pGoNegoDone(pAd, pP2pEntry); + } + else if (pP2pEntry->P2pClientState== P2PSTATE_REVOKEINVITE_RSP_ACK_SUCCESS) + { + /* Only when I am GO . I need to check the response ack success or not. */ + /* doesn't check rule. start GO right away. */ + pP2pEntry->P2pClientState = P2PSTATE_CLIENT_WPS; + P2pStartAutoGo(pAd); + DBGPRINT(RT_DEBUG_TRACE,("P2P Table : idx=%d Get Invite Rsp Ask Success. p2pState = %d.\n", i, pP2PCtrl->P2PConnectState)); + + pAd->StaCfg.WscControl.WscState = WSC_STATE_OFF; + /* this is not Auto GO by command from GUI. So set the intent index to != 16 */ + pAd->P2pCfg.GoIntentIdx = 15; + } + else if ((pP2pEntry->P2pClientState == P2PSTATE_CONNECT_COMMAND) || (pP2pEntry->P2pClientState == P2PSTATE_PROVISION_COMMAND) || (pP2pEntry->P2pClientState == P2PSTATE_INVITE_COMMAND)) + { + if (pP2pEntry->StateCount > 0) + { + DBGPRINT(RT_DEBUG_INFO, ("pEntry[%d] State = %s. StateCount = %d\n", i, decodeP2PClientState(pP2pEntry->P2pClientState), pP2pEntry->StateCount)); + pP2pEntry->StateCount--; + } + + if ((pP2pEntry->StateCount == 0) && (pP2pEntry->bValid)) + { + if (pP2pEntry->ReTransmitCnt >= 20) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s:: [%s] ReTransmit Probe Req. limit! stop connect this p2p device!\n", + __FUNCTION__, decodeP2PClientState(pP2pEntry->P2pClientState))); + P2pStopConnectThis(pAd); + P2P_WSC_CONF_MTHD_DEFAULT(pAd); + pP2pEntry->ReTransmitCnt = 0; + } + + pP2pEntry->StateCount = 3; + pP2pEntry->ReTransmitCnt++; + DBGPRINT(RT_DEBUG_TRACE, ("P2P Table : idx=%d Send Probe Req. \n", i)); + P2pSendProbeReq(pAd, pP2pEntry->ListenChannel); + } + + } + else if ((pP2pEntry->P2pClientState == P2PSTATE_DISCOVERY_GO) && (MAC_ADDR_EQUAL(pP2PCtrl->ConnectingMAC, pP2pEntry->addr))) + { + if (pP2pEntry->StateCount > 0) + { + DBGPRINT(RT_DEBUG_INFO, ("pEntry[%d] State = %s. StateCount = %d\n", i, decodeP2PClientState(pP2pEntry->P2pClientState), pP2pEntry->StateCount)); + pP2pEntry->StateCount--; + } + + if ((pP2pEntry->StateCount == 0) && (pP2pEntry->bValid)) + { + if (pP2pEntry->ReTransmitCnt >= 20) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s:: [%s] ReTransmit Probe Req. limit! stop connect this p2p device!\n", + __FUNCTION__, decodeP2PClientState(pP2pEntry->P2pClientState))); + P2pStopConnectThis(pAd); + P2P_WSC_CONF_MTHD_DEFAULT(pAd); + pP2pEntry->ReTransmitCnt = 0; + } + + pP2pEntry->P2pClientState = P2PSTATE_PROVISION_COMMAND; + pP2pEntry->StateCount =0; + pP2pEntry->ReTransmitCnt++; + DBGPRINT(RT_DEBUG_TRACE, ("P2P Table : idx=%d Send Probe Req. \n", i)); + P2pSendProbeReq(pAd, pP2pEntry->ListenChannel); + } + } + } + } +} + +/* + ========================================================================== + Description: + Copy P2P Table's information to Mac Table when the P2P Device is in my group. + + Parameters: + Note: + ========================================================================== + */ +VOID P2pCopyMacTabtoP2PTab( + IN PRTMP_ADAPTER pAd, + IN UCHAR P2pindex, + IN UCHAR Macindex) +{ + MAC_TABLE_ENTRY *pEntry; + RT_P2P_CLIENT_ENTRY *pP2pEntry; + + if ((P2pindex >= MAX_P2P_GROUP_SIZE) || (Macindex >= MAX_LEN_OF_MAC_TABLE)) + return; + + pEntry = &pAd->MacTab.Content[Macindex]; + pP2pEntry = &pAd->P2pTable.Client[P2pindex]; + pP2pEntry->CTWindow= pEntry->P2pInfo.CTWindow; + pP2pEntry->P2pClientState = pEntry->P2pInfo.P2pClientState; + pP2pEntry->P2pFlag = pEntry->P2pInfo.P2pFlag; + pP2pEntry->NoAToken = pEntry->P2pInfo.NoAToken; + pP2pEntry->GeneralToken = pEntry->P2pInfo.GeneralToken; + + pP2pEntry->DevCapability = pEntry->P2pInfo.DevCapability; + pP2pEntry->GroupCapability = pEntry->P2pInfo.GroupCapability; + pP2pEntry->NumSecondaryType = pEntry->P2pInfo.NumSecondaryType; + pP2pEntry->DeviceNameLen = pEntry->P2pInfo.DeviceNameLen; + pP2pEntry->ConfigMethod = pEntry->P2pInfo.ConfigMethod; + + RTMPMoveMemory(pP2pEntry->addr, pEntry->P2pInfo.DevAddr, MAC_ADDR_LEN); + RTMPMoveMemory(pP2pEntry->InterfaceAddr, pEntry->P2pInfo.InterfaceAddr, MAC_ADDR_LEN); + /* Save the bssid with interface address. */ + RTMPMoveMemory(pP2pEntry->bssid, pEntry->P2pInfo.InterfaceAddr, MAC_ADDR_LEN); + RTMPMoveMemory(pP2pEntry->PrimaryDevType, pEntry->P2pInfo.PrimaryDevType, P2P_DEVICE_TYPE_LEN); + RTMPMoveMemory(pP2pEntry->DeviceName, pEntry->P2pInfo.DeviceName, 32); + RTMPMoveMemory(pP2pEntry->SecondaryDevType, pEntry->P2pInfo.SecondaryDevType, P2P_DEVICE_TYPE_LEN); + +} + +/* + ========================================================================== + Description: + Copy P2P Table's information to Mac Table when the P2P Device is in my group. + + Parameters: + Note: + ========================================================================== + */ +VOID P2pCopyP2PTabtoMacTab( + IN PRTMP_ADAPTER pAd, + IN UCHAR P2pindex, + IN UCHAR Macindex) +{ + MAC_TABLE_ENTRY *pEntry; + RT_P2P_CLIENT_ENTRY *pP2pEntry; + + if ((P2pindex >= MAX_P2P_GROUP_SIZE) || (Macindex >= MAX_LEN_OF_MAC_TABLE)) + return; + + pEntry = &pAd->MacTab.Content[Macindex]; + pP2pEntry = &pAd->P2pTable.Client[P2pindex]; + pEntry->P2pInfo.CTWindow = pP2pEntry->CTWindow; + pEntry->P2pInfo.P2pClientState = pP2pEntry->P2pClientState; + pEntry->P2pInfo.P2pFlag = pP2pEntry->P2pFlag; + pEntry->P2pInfo.NoAToken = pP2pEntry->NoAToken; + pEntry->P2pInfo.GeneralToken = pP2pEntry->GeneralToken; + DBGPRINT(RT_DEBUG_TRACE, ("MacTab Add = %s. \n", decodeP2PClientState(pEntry->P2pInfo.P2pClientState))); + pEntry->P2pInfo.ConfigMethod = pP2pEntry->ConfigMethod; + + pEntry->P2pInfo.DevCapability = pP2pEntry->DevCapability; + pEntry->P2pInfo.GroupCapability = pP2pEntry->GroupCapability; + pEntry->P2pInfo.NumSecondaryType = pP2pEntry->NumSecondaryType; + pEntry->P2pInfo.DeviceNameLen = pP2pEntry->DeviceNameLen; + + RTMPMoveMemory(pEntry->P2pInfo.DevAddr, pP2pEntry->addr, MAC_ADDR_LEN); + RTMPMoveMemory(pEntry->P2pInfo.InterfaceAddr, pP2pEntry->InterfaceAddr, MAC_ADDR_LEN); + DBGPRINT(RT_DEBUG_TRACE, ("MacTab InterfaceAddr = %x %x %x %x %x %x . \n", PRINT_MAC(pP2pEntry->InterfaceAddr))); + DBGPRINT(RT_DEBUG_TRACE, ("MacTab DevAddr = %x %x %x %x %x %x. \n", PRINT_MAC(pP2pEntry->addr))); + DBGPRINT(RT_DEBUG_TRACE, ("MacTab DeviceNameLen = %ld . \n", pEntry->P2pInfo.DeviceNameLen)); + RTMPMoveMemory(pEntry->P2pInfo.PrimaryDevType, pP2pEntry->PrimaryDevType, P2P_DEVICE_TYPE_LEN); + RTMPMoveMemory(pEntry->P2pInfo.DeviceName, pP2pEntry->DeviceName, 32); + RTMPMoveMemory(pEntry->P2pInfo.SecondaryDevType, pP2pEntry->SecondaryDevType, P2P_DEVICE_TYPE_LEN); + P2PPrintMac(pAd, Macindex); +} + + +/* + ========================================================================== + Description: + Init P2P Group Table. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pGroupTabInit( + IN PRTMP_ADAPTER pAd) +{ + PRT_P2P_TABLE Tab = &pAd->P2pTable; + UCHAR i; + + DBGPRINT(RT_DEBUG_ERROR, ("P2pGroupTabInit . \n")); + for (i = 0; i < MAX_P2P_GROUP_SIZE; i++) + { + Tab->Client[i].P2pClientState = P2PSTATE_NONE; + Tab->Client[i].Rule = P2P_IS_CLIENT; + Tab->Client[i].DevCapability = 0; + Tab->Client[i].GroupCapability = 0; + RTMPZeroMemory(Tab->Client[i].addr, MAC_ADDR_LEN); + RTMPZeroMemory(Tab->Client[i].bssid, MAC_ADDR_LEN); + RTMPZeroMemory(Tab->Client[i].InterfaceAddr, MAC_ADDR_LEN); + RTMPZeroMemory(Tab->Client[i].Ssid, MAX_LEN_OF_SSID); + RTMPZeroMemory(Tab->Client[i].PrimaryDevType, P2P_DEVICE_TYPE_LEN); + RTMPZeroMemory(Tab->Client[i].SecondaryDevType, P2P_DEVICE_TYPE_LEN); + RTMPZeroMemory(Tab->Client[i].DeviceName, P2P_DEVICE_NAME_LEN); + Tab->Client[i].DeviceNameLen = 0; + Tab->Client[i].SsidLen = 0; + Tab->Client[i].GoIntent = 0; + Tab->Client[i].OpChannel = 0; + Tab->Client[i].ListenChannel = 0; + Tab->Client[i].ConfigMethod = 0; + Tab->Client[i].P2pClientState = P2PSTATE_NONE; + Tab->Client[i].StateCount = 0; + Tab->Client[i].bValid = FALSE; + Tab->Client[i].ReTransmitCnt = 0; + + } + Tab->ClientNumber = 0; + return; +} + +/* + ========================================================================== + Description: + Clean P2P Group Table. If necessary, Send Disassociation + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pGroupTabDisconnect( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bSendDeAuth) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + PRT_P2P_CLIENT_ENTRY pP2pEntry; + UCHAR i; + /*ULONG BytesRead, BytesNeeded; */ + /*MLME_QUEUE_ELEM MsgElem;*/ + MLME_QUEUE_ELEM *pMsgElem = NULL; + /*MLME_DISASSOC_REQ_STRUCT DisReq;*/ + MLME_DEAUTH_REQ_STRUCT DeAuthReq; + + DBGPRINT(RT_DEBUG_ERROR, ("P2pGroupTab Disconnect All==> \n")); + /*pMsgElem = &MsgElem;*/ + if (bSendDeAuth && P2P_CLI_ON(pAd)) + { + os_alloc_mem(pAd, (UCHAR **)&pMsgElem, sizeof(MLME_QUEUE_ELEM)); + + COPY_MAC_ADDR(DeAuthReq.Addr, pP2PCtrl->PortCfg.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); + + return; + } + for (i = 0; i < MAX_P2P_GROUP_SIZE; i++) + { + pP2pEntry = &pAd->P2pTable.Client[i]; + if (pP2pEntry->P2pClientState >= P2PSTATE_CLIENT_OPERATING) + { + + /* this Client is operating, need to send Disassociate frame disconnect. */ + /*Send dis_assoc & de_auth */ + /* + COPY_MAC_ADDR(&DisReq.Addr, pP2pEntry->addr); + DisReq.Reason = REASON_DISASSOC_STA_LEAVING; + pMsgElem->Machine = ASSOC_STATE_MACHINE; + pMsgElem->MsgType = MT2_MLME_DISASSOC_REQ; + pMsgElem->MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT); + pMsgElem->PortNum = pAd->PortList[pAd->P2pCfg.PortNumber]->PortNumber; + NdisMoveMemory(pMsgElem->Msg, &DisReq, sizeof(MLME_DISASSOC_REQ_STRUCT)); + + MlmeDisassocReqAction(pAd, pMsgElem); + */ + if (bSendDeAuth) + { + os_alloc_mem(pAd, (UCHAR **)&pMsgElem, sizeof(MLME_QUEUE_ELEM)); + + COPY_MAC_ADDR(DeAuthReq.Addr, pP2pEntry->addr); + 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); + } + /* Delete this peer from table. */ + pP2pEntry->P2pClientState = P2PSTATE_NONE; + RTMPZeroMemory(pP2pEntry->addr, MAC_ADDR_LEN); + RTMPZeroMemory(pP2pEntry->PrimaryDevType, P2P_DEVICE_TYPE_LEN); + RTMPZeroMemory(pP2pEntry->SecondaryDevType, P2P_DEVICE_TYPE_LEN); + RTMPZeroMemory(pP2pEntry->DeviceName, 32); + pP2pEntry->NumSecondaryType = 0; + pP2pEntry->DeviceNameLen = 0; + + RTMPZeroMemory(pP2pEntry->Ssid, 32); + pP2pEntry->SsidLen = 0; + pP2pEntry->GoIntent = 0; + if (pAd->P2pTable.ClientNumber > 0) + pAd->P2pTable.ClientNumber--; + } + } + + return; + +} + +/* + ========================================================================== + Description: + insert a peer to P2P Group Table. Because this Peer contains P2P IE and P2P Wildwork SSID to indicate that it support P2P + + Parameters: + Note: + + ========================================================================== + */ +UCHAR P2pGroupTabInsert( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr, + IN P2P_CLIENT_STATE State, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR DevCap, + IN UCHAR GrpCap) +{ PRT_P2P_TABLE Tab = &pAd->P2pTable; + UCHAR i; + + RTMP_SEM_LOCK(&pAd->P2pTableSemLock); + + if (NdisEqualMemory(ZeroSsid, Addr, 6)) + { + DBGPRINT(RT_DEBUG_ERROR,("P2pGroupTabInsert . Addr all zero Error. \n")); + RTMP_SEM_UNLOCK(&pAd->P2pTableSemLock); + return P2P_NOT_FOUND; + } + if ((Addr[0] & 0x1) == 0x1) + { + DBGPRINT(RT_DEBUG_ERROR,("P2pGroupTabInsert . Insert mcast Addr Error. \n")); + RTMP_SEM_UNLOCK(&pAd->P2pTableSemLock); + return P2P_NOT_FOUND; + } + + for (i = 0; i < MAX_P2P_GROUP_SIZE; i++) + { + /* This peer already exist, so only update state. */ + if ((Tab->Client[i].P2pClientState != P2PSTATE_NONE) + && (RTMPEqualMemory(Tab->Client[i].addr, Addr, MAC_ADDR_LEN))) + { + if (State != P2PSTATE_NONE) + Tab->Client[i].P2pClientState = State; + if ((SsidLen > 0) && (Ssid != NULL)) + RTMPMoveMemory(Tab->Client[i].Ssid, Ssid, 32); + Tab->Client[i].SsidLen = SsidLen; + + RTMP_SEM_UNLOCK(&pAd->P2pTableSemLock); + return i; + } + else if (Tab->Client[i].P2pClientState == P2PSTATE_NONE) + { + Tab->ClientNumber++; + RTMPMoveMemory(Tab->Client[i].addr, Addr, 6); + + DBGPRINT(RT_DEBUG_ERROR, (" P2pGroupTabInsert[%d] . Arrd[%02x:%02x:%02x:%02x:%02x:%02x] Update State = %s \n", i, Addr[0], Addr[1], Addr[2], Addr[3], Addr[4], Addr[5], decodeP2PClientState(State))); + Tab->Client[i].P2pClientState = State; + if ((SsidLen > 0) && (Ssid != NULL)) + RTMPMoveMemory(Tab->Client[i].Ssid, Ssid, 32); + Tab->Client[i].SsidLen = SsidLen; + pAd->P2pTable.Client[i].Dbm = 0; + pAd->P2pTable.Client[i].GoIntent = 0; + pAd->P2pTable.Client[i].MyGOIndex = 0xff; + pAd->P2pTable.Client[i].Peerip = 0; + pAd->P2pTable.Client[i].ConfigTimeOut = 0; + pAd->P2pTable.Client[i].OpChannel = 0; + pAd->P2pTable.Client[i].ListenChannel = 0; + pAd->P2pTable.Client[i].GeneralToken = RandomByte(pAd); + pAd->P2pTable.Client[i].DevCapability = DevCap; + pAd->P2pTable.Client[i].GroupCapability = GrpCap; + pAd->P2pTable.Client[i].ReTransmitCnt = 0; + + if ((pAd->P2pTable.Client[i].GeneralToken == 0) + || (pAd->P2pTable.Client[i].GeneralToken > 245)) + pAd->P2pTable.Client[i].GeneralToken = 6; + pAd->P2pTable.Client[i].Dpid = DEV_PASS_ID_NOSPEC; + pAd->P2pTable.Client[i].P2pFlag = 0; + if (State == P2PSTATE_DISCOVERY_GO) + pAd->P2pTable.Client[i].Rule = P2P_IS_GO; + else + pAd->P2pTable.Client[i].Rule = P2P_IS_CLIENT; + + RTMP_SEM_UNLOCK(&pAd->P2pTableSemLock); + return i; + } + } + + RTMP_SEM_UNLOCK(&pAd->P2pTableSemLock); + return P2P_NOT_FOUND; + +} + +/* + ========================================================================== + Description: + Delete a peer in P2P Group Table. + + Parameters: + Note: + + ========================================================================== + */ +UCHAR P2pGroupTabDelete( + IN PRTMP_ADAPTER pAd, + IN UCHAR p2pindex, + IN PUCHAR Addr) +{ UCHAR index = 0xff; + PRT_P2P_CLIENT_ENTRY pP2pEntry; + + RTMP_SEM_LOCK(&pAd->P2pTableSemLock); + + if ((p2pindex >= MAX_P2P_GROUP_SIZE) && (Addr != NULL)) + index = P2pGroupTabSearch(pAd, Addr); + else + index = p2pindex; + + DBGPRINT(RT_DEBUG_TRACE,("P2pGroupTabDelete . index = %d. \n", index)); + if (index < MAX_P2P_GROUP_SIZE) + { + pP2pEntry = &pAd->P2pTable.Client[index]; + /* Before connected, there is WPS provisioning process. */ + /* So maybe receive disassoc frame. but we can't delete p2p client entry . */ + /* So need to check P2pClientState is connected, then we can delete the entry. */ + DBGPRINT(RT_DEBUG_ERROR, ("P2pGroupTabDelete index %d. search addr[3~5] is %x %x %x\n", index, Addr[3],Addr[4],Addr[5])); + + RTMPZeroMemory(pP2pEntry->addr, MAC_ADDR_LEN); + RTMPZeroMemory(pP2pEntry->bssid, MAC_ADDR_LEN); + RTMPZeroMemory(pP2pEntry->InterfaceAddr, MAC_ADDR_LEN); + /* Assign a strange address first. */ + pP2pEntry->addr[3] = 0x55; + pP2pEntry->bssid[3] = 0x55; + pP2pEntry->InterfaceAddr[3] = 0x55; + RTMPZeroMemory(pP2pEntry->PrimaryDevType, P2P_DEVICE_TYPE_LEN); + RTMPZeroMemory(pP2pEntry->SecondaryDevType, P2P_DEVICE_TYPE_LEN); + RTMPZeroMemory(pP2pEntry->DeviceName, P2P_DEVICE_NAME_LEN); + pP2pEntry->NumSecondaryType = 0; + pP2pEntry->DeviceNameLen = 0; + pP2pEntry->ConfigMethod = 0; + pP2pEntry->OpChannel = 0; + pP2pEntry->ListenChannel = 0; + pP2pEntry->Dpid = DEV_PASS_ID_NOSPEC; + pP2pEntry->MyGOIndex = 0xff; + pP2pEntry->Peerip = 0; + pP2pEntry->ConfigTimeOut = 0; + pP2pEntry->Rule = P2P_IS_CLIENT; + + RTMPZeroMemory(pP2pEntry->Ssid, MAX_LEN_OF_SSID); + pP2pEntry->SsidLen = 0; + pP2pEntry->GoIntent = 0; + if ((pAd->P2pTable.ClientNumber > 0) && (pP2pEntry->P2pClientState != P2PSTATE_NONE)) + pAd->P2pTable.ClientNumber--; + + pP2pEntry->P2pClientState = P2PSTATE_NONE; + } + + RTMP_SEM_UNLOCK(&pAd->P2pTableSemLock); + + return index; + +} + +/* + ========================================================================== + Description: + Search a peer in P2P Group Table by the same MAc Addr.. + + Parameters: + Note: + + ========================================================================== + */ +UCHAR P2pGroupTabSearch( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr) +{ UCHAR i; + PRT_P2P_TABLE Tab = &pAd->P2pTable; + UCHAR index = P2P_NOT_FOUND; + UCHAR Allff[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + UCHAR AllZero[MAC_ADDR_LEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + + /* find addr can't be 1. multicast, 2. all zero, 3. all 0xff */ + if ((Addr[0] & 0x1) == 0x1) + return index; + + if (NdisEqualMemory(Allff, Addr, MAC_ADDR_LEN)) + return index; + + if (NdisEqualMemory(AllZero, Addr, MAC_ADDR_LEN)) + return index; + + if (NdisEqualMemory(ZeroSsid, Addr, MAC_ADDR_LEN)) + return index; + + for (i = 0; i < MAX_P2P_GROUP_SIZE; i++) + { + /* If addr format is all zero or all 0xff or multicast, return before. So doesn't need to */ + /* check invalid match here. */ + if (((NdisEqualMemory(Tab->Client[i].bssid, Addr, 6)) + || (NdisEqualMemory(Tab->Client[i].InterfaceAddr, Addr, 6)) + || (NdisEqualMemory(Tab->Client[i].addr, Addr, 6))) + && (Tab->Client[i].P2pClientState > P2PSTATE_NONE)) + index = i; + } + + return index; +} + +/* + ========================================================================== + Description: + Clean in P2P Persistent Table. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pPerstTabClean( + IN PRTMP_ADAPTER pAd) +{ PRT_P2P_PERSISTENT_ENTRY pP2pPerstEntry; + UCHAR i; + + DBGPRINT(RT_DEBUG_TRACE,("P2pPerstTabClean . \n")); + + for (i = 0; i < MAX_P2P_TABLE_SIZE; i++) + { + pP2pPerstEntry = &pAd->P2pTable.PerstEntry[i]; + RTMPZeroMemory(pP2pPerstEntry, sizeof(RT_P2P_PERSISTENT_ENTRY)); + pP2pPerstEntry->bValid = FALSE; + } + pAd->P2pTable.PerstNumber = 0; + return; + +} + +/* + ========================================================================== + Description: + Insert a peer into P2P Persistent Table. + + Parameters: + Note: + + ========================================================================== + */ +UCHAR P2pPerstTabInsert( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN PWSC_CREDENTIAL pProfile) +{ PRT_P2P_TABLE Tab = &pAd->P2pTable; + UCHAR i, j; + UCHAR index = 0; + WSC_CREDENTIAL *pPerstProfile; + + index = P2pPerstTabSearch(pAd, pAddr, NULL, NULL); + /* Doesn't have this entry. Add a new one. */ + if (index == P2P_NOT_FOUND) + { + for (i = 0; i < MAX_P2P_TABLE_SIZE; i++) + { + if (Tab->PerstEntry[i].bValid == FALSE) + { + Tab->PerstEntry[i].bValid = TRUE; + Tab->PerstNumber++; + if (P2P_GO_ON(pAd)) + Tab->PerstEntry[i].MyRule = P2P_IS_GO; + else + Tab->PerstEntry[i].MyRule = P2P_IS_CLIENT; + + RTMPMoveMemory(Tab->PerstEntry[i].Addr, pAddr, MAC_ADDR_LEN); + DBGPRINT(RT_DEBUG_ERROR, ("Perst::Registra MacAddr = %x %x %x %x %x %x \n",Tab->PerstEntry[i].Addr[0], Tab->PerstEntry[i].Addr[1], Tab->PerstEntry[i].Addr[2],Tab->PerstEntry[i].Addr[3],Tab->PerstEntry[i].Addr[4],Tab->PerstEntry[i].Addr[5])); + RTMPMoveMemory(&Tab->PerstEntry[i].Profile, pProfile, sizeof(WSC_CREDENTIAL)); + pPerstProfile = &Tab->PerstEntry[i].Profile; + DBGPRINT(RT_DEBUG_ERROR, ("Perst::SsidLen = %d\n",pPerstProfile->SSID.SsidLength)); + DBGPRINT(RT_DEBUG_ERROR, ("Perst::Ssid = %s.\n", pPerstProfile->SSID.Ssid)); + DBGPRINT(RT_DEBUG_ERROR, ("Perst::MacAddr = %02x:%02x:%02x:%02x:%02x:%02x.\n", PRINT_MAC(pPerstProfile->MacAddr))); + DBGPRINT(RT_DEBUG_ERROR, ("Perst::AuthType = 0x%x. EncrType = %d\n",pPerstProfile->AuthType,pPerstProfile->EncrType)); + DBGPRINT(RT_DEBUG_ERROR, ("Perst::KeyIndex = %d\n",pPerstProfile->KeyIndex)); + DBGPRINT(RT_DEBUG_ERROR, ("Perst::KeyLength = %d\n",pPerstProfile->KeyLength)); + DBGPRINT(RT_DEBUG_ERROR, ("Perst::Key ==>\n")); + for (j=0;j<16;) + { + DBGPRINT(RT_DEBUG_ERROR, (" 0x%x 0x%x 0x%x 0x%x\n", + pPerstProfile->Key[j], pPerstProfile->Key[j+1], pPerstProfile->Key[j+2],pPerstProfile->Key[j+3])); + j = j+4; + } + DBGPRINT(RT_DEBUG_ERROR, ("Perst::<===Key =\n")); + /*DBGPRINT(RT_DEBUG_ERROR, ("Perst::MacAddr = %x %x %x %x %x %x\n",pProfile->MacAddr[0], pProfile->MacAddr[1], pProfile->MacAddr[2],pProfile->MacAddr[3],pProfile->MacAddr[4],pProfile->MacAddr[5]));*/ + DBGPRINT(RT_DEBUG_ERROR, (" P2P -P2pPerstTabInsert to index = %x. Rule = %s.\n", i, decodeMyRule(Tab->PerstEntry[i].MyRule))); + return i; + } + } + } + else if (index < MAX_P2P_TABLE_SIZE) + { + + i = index; + Tab->PerstEntry[i].bValid = TRUE; + if (P2P_GO_ON(pAd)) + Tab->PerstEntry[i].MyRule = P2P_IS_GO; + else + Tab->PerstEntry[i].MyRule = P2P_IS_CLIENT; + RTMPMoveMemory(Tab->PerstEntry[i].Addr, pAddr, MAC_ADDR_LEN); + RTMPMoveMemory(&Tab->PerstEntry[i].Profile, pProfile, sizeof(WSC_CREDENTIAL)); + pPerstProfile = &Tab->PerstEntry[i].Profile; + DBGPRINT(RT_DEBUG_ERROR, ("Perst::SsidLen = %d\n",pPerstProfile->SSID.SsidLength)); + DBGPRINT(RT_DEBUG_ERROR, ("Perst::Ssid = %c%c%c%c%c%c%c \n", + pPerstProfile->SSID.Ssid[0], + pPerstProfile->SSID.Ssid[1], + pPerstProfile->SSID.Ssid[2], + pPerstProfile->SSID.Ssid[3], + pPerstProfile->SSID.Ssid[4], + pPerstProfile->SSID.Ssid[5], + pPerstProfile->SSID.Ssid[6])); + DBGPRINT(RT_DEBUG_ERROR, ("Perst::AuthType = 0x%x. EncrType = %d\n",pPerstProfile->AuthType,pPerstProfile->EncrType)); + DBGPRINT(RT_DEBUG_ERROR, ("Perst::KeyIndex = %d\n",pPerstProfile->KeyIndex)); + DBGPRINT(RT_DEBUG_ERROR, ("Perst::KeyLength = %d\n",pPerstProfile->KeyLength)); + DBGPRINT(RT_DEBUG_ERROR, ("Perst::Key ==>\n")); + for (j=0;j<16;) + { + DBGPRINT(RT_DEBUG_ERROR, (" 0x%x 0x%x 0x%x 0x%x\n", + pPerstProfile->Key[j], pPerstProfile->Key[j+1], pPerstProfile->Key[j+2],pPerstProfile->Key[j+3])); + j = j+4; + } + DBGPRINT(RT_DEBUG_ERROR, ("Perst::<===Key =\n")); + DBGPRINT(RT_DEBUG_ERROR, ("Perst::MacAddr = %x %x %x %x %x %x\n", + pPerstProfile->MacAddr[0], + pPerstProfile->MacAddr[1], + pPerstProfile->MacAddr[2], + pPerstProfile->MacAddr[3], + pPerstProfile->MacAddr[4], + pPerstProfile->MacAddr[5])); + DBGPRINT(RT_DEBUG_ERROR, (" P2P -P2pPerstTabInsert update to index = %x.\n", i)); + return i; + } + DBGPRINT(RT_DEBUG_ERROR, ("P2P -P2pPerstTabInsert . PerstNumber = %d.\n", Tab->PerstNumber)); + return index; + +} + +/* + ========================================================================== + Description: + Delete an entry in P2P Persistent Table. + + Parameters: + Note: + + ========================================================================== + */ +UCHAR P2pPerstTabDelete( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pMacList) +{ PRT_P2P_TABLE Tab = &pAd->P2pTable; + UCHAR i; + + for (i = 0; i < MAX_P2P_TABLE_SIZE; i++) + { + if (Tab->PerstEntry[i].bValid == TRUE) + { + if (NdisEqualMemory(Tab->PerstEntry[i].Addr, pMacList, 6)) + { + RTMPZeroMemory(&Tab->PerstEntry[i], sizeof(RT_P2P_PERSISTENT_ENTRY)); + Tab->PerstEntry[i].bValid = FALSE; + + if (Tab->PerstNumber > 0) + { + Tab->PerstNumber--; + } + else + DBGPRINT(RT_DEBUG_ERROR, (" P2P - Persistent table count error. \n")); + + DBGPRINT(RT_DEBUG_ERROR, (" P2P - Delete a Persistent Entry .Table Number = %d. \n", Tab->PerstNumber)); + } + + return i; + } + } + return 0xff; + +} + +/* + ========================================================================== + Description: + SEarch an entry in P2P Persistent Table. All parameters must the same. + + Parameters: + Note: + + ========================================================================== + */ +UCHAR P2pPerstTabSearch( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr, + IN PUCHAR Bssid, + IN PUCHAR InfAddr) +{ + PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; + UCHAR i; + PRT_P2P_TABLE Tab = &pAd->P2pTable; + UCHAR index = P2P_NOT_FOUND; + UCHAR Allff[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + UCHAR AllZero[MAC_ADDR_LEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + + if (Addr && ((Addr[0] & 0x1) == 0x1)) + return index; + + if (Addr && NdisEqualMemory(Allff, Addr, MAC_ADDR_LEN)) + return index; + + if (Addr && NdisEqualMemory(AllZero, Addr, MAC_ADDR_LEN)) + return index; + + for (i = 0; i < MAX_P2P_TABLE_SIZE; i++) + { + if ((Tab->PerstEntry[i].bValid == TRUE) && + ((Addr && NdisEqualMemory(&Tab->PerstEntry[i].Addr, Addr, MAC_ADDR_LEN)) || + (Bssid && NdisEqualMemory(&Tab->PerstEntry[i].Addr, Bssid, MAC_ADDR_LEN)) || + (InfAddr && NdisEqualMemory(&Tab->PerstEntry[i].Addr, InfAddr, MAC_ADDR_LEN))) + ) + { + DBGPRINT(RT_DEBUG_TRACE, (" P2P - i = %d. \n", i)); + index = i; + } + } + + return index; +} + +/* + ========================================================================== + Description: + Clean in P2P Persistent Table. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pCrednTabClean( + IN PRTMP_ADAPTER pAd) +{ + + UCHAR i; + RT_GO_CREDENTIAL_ENTRY *pCrednEntry; + + DBGPRINT(RT_DEBUG_TRACE,("P2pCrednTabClean . \n")); + + for (i = 0; i < 2/*MAX_P2P_SAVECREDN_SIZE*/; i++) + { + pCrednEntry = &pAd->P2pTable.TempCredential[i]; + RTMPZeroMemory(pCrednEntry, sizeof(RT_GO_CREDENTIAL_ENTRY)); + pCrednEntry->bValid = FALSE; + } + return; +} +/* + ========================================================================== + Description: + Insert a peer into P2P Persistent Table. + + Parameters: + Note: + + ========================================================================== + */ +VOID P2pCrednTabInsert( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN WSC_CREDENTIAL *pProfile) +{ + + PRT_P2P_TABLE Tab = &pAd->P2pTable; + UCHAR i = 0; + UCHAR index; + BOOLEAN bExist; + + bExist = P2pCrednEntrySearch(pAd, pAddr, &index); + DBGPRINT(RT_DEBUG_ERROR, (" P2P - P2pCrednTabInsert \n")); + if (bExist == FALSE) + { + i = (RandomByte(pAd))%2; + if (i >= 2/*MAX_P2P_SAVECREDN_SIZE*/) + i = 0; + + for ( i = 0; i < 2/*MAX_P2P_SAVECREDN_SIZE*/;i++) + { + DBGPRINT(RT_DEBUG_ERROR, (" P2P - P2pCrednTabInsert NEW\n")); + Tab->TempCredential[i].bValid = TRUE; + RTMPMoveMemory(&Tab->TempCredential[i].Profile, pProfile, sizeof(WSC_CREDENTIAL)); + RTMPMoveMemory(&Tab->TempCredential[i].InterAddr, pAddr, MAC_ADDR_LEN); + } + } + else if (index < 2/*MAX_P2P_SAVECREDN_SIZE*/) + { + DBGPRINT(RT_DEBUG_ERROR, (" P2P - P2pCrednTabInsert Update Existing\n")); + Tab->TempCredential[index].bValid = TRUE; + RTMPMoveMemory(&Tab->TempCredential[index].Profile, pProfile, sizeof(WSC_CREDENTIAL)); + RTMPMoveMemory(&Tab->TempCredential[index].InterAddr, pAddr, MAC_ADDR_LEN); + } +} + +/* + ========================================================================== + Description: + SEarch an entry in P2P Persistent Table. All parameters must the same. + + Parameters: + Note: + + ========================================================================== + */ +BOOLEAN P2pCrednEntrySearch( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr, + IN PUCHAR ResultIndex) +{ + + UCHAR i; + PRT_P2P_TABLE Tab = &pAd->P2pTable; + BOOLEAN bFind = FALSE; + UCHAR Allff[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + UCHAR AllZero[MAC_ADDR_LEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + + if ((Addr[0] & 0x1) == 0x1) + return bFind; + + if (NdisEqualMemory(Allff, Addr, MAC_ADDR_LEN)) + return bFind; + + if (NdisEqualMemory(AllZero, Addr, MAC_ADDR_LEN)) + return bFind; + + DBGPRINT(RT_DEBUG_ERROR, (" P2P - P2pCrednEntrySearch \n")); + for (i = 0; i < 2/*MAX_P2P_SAVECREDN_SIZE*/; i++) + { + if ((Tab->TempCredential[i].bValid == TRUE) + && NdisEqualMemory(&Tab->TempCredential[i].InterAddr, Addr, MAC_ADDR_LEN)) + { + DBGPRINT(RT_DEBUG_TRACE, (" Find Credential Entry - i = %d. \n", i)); + bFind = TRUE; + *ResultIndex = i; + } + } + + return bFind; +} + +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT +VOID P2pSendWirelessEvent( + IN PRTMP_ADAPTER pAd, + IN INT MsgType, + IN PRT_P2P_CLIENT_ENTRY pP2pEntry, + IN PUCHAR Addr) +{ + RT_P2P_DEV_FOUND p2p_dev_info; + RT_P2P_GROUP_INFO p2p_group_info; + RT_P2P_PROV_DISC_RESP p2p_prov_disc_rsp; + RT_P2P_GO_NEG_REQ_RX p2p_go_neg_req_rx; + UCHAR p2pIdx = P2P_NOT_FOUND; + UINT32 rtsp_port = 0; + + + if (pAd->P2pCfg.bSigmaEnabled == TRUE) + return; + + switch (MsgType) + { + case RT_P2P_DEVICE_FIND: + RTMPZeroMemory(&p2p_dev_info, sizeof(RT_P2P_DEV_FOUND)); + if (Addr) + RTMPMoveMemory(p2p_dev_info.addr, Addr, MAC_ADDR_LEN); + RTMPMoveMemory(p2p_dev_info.dev_addr, pP2pEntry->addr, MAC_ADDR_LEN); + RTMPMoveMemory(p2p_dev_info.dev_name, pP2pEntry->DeviceName, pP2pEntry->DeviceNameLen); + RTMPMoveMemory(p2p_dev_info.pri_dev_type, pP2pEntry->PrimaryDevType, P2P_DEVICE_TYPE_LEN); + p2p_dev_info.config_methods = pP2pEntry->ConfigMethod; + p2p_dev_info.dev_capab = pP2pEntry->DevCapability; + p2p_dev_info.group_capab = pP2pEntry->DevCapability; + p2p_dev_info.rssi = pP2pEntry->Rssi; +#ifdef WFD_SUPPORT + p2p_dev_info.bWfdClient = pP2pEntry->bWfdClient; + if (pP2pEntry->bWfdClient) + { + p2p_dev_info.wfd_devive_type = pP2pEntry->wfd_devive_type; + p2p_dev_info.source_coupled = pP2pEntry->source_coupled; + p2p_dev_info.session_avail = pP2pEntry->session_avail; + p2p_dev_info.sink_coupled = pP2pEntry->sink_coupled; + p2p_dev_info.wfd_service_discovery = pP2pEntry->wfd_service_discovery; + p2p_dev_info.wfd_PC = pP2pEntry->wfd_PC; + p2p_dev_info.wfd_CP = pP2pEntry->wfd_CP; + p2p_dev_info.wfd_time_sync = pP2pEntry->wfd_time_sync; + p2p_dev_info.rtsp_port = pP2pEntry->rtsp_port; + p2p_dev_info.max_throughput = pP2pEntry->max_throughput; + RTMPMoveMemory(p2p_dev_info.assoc_addr, pP2pEntry->assoc_addr, MAC_ADDR_LEN); + p2p_dev_info.coupled_sink_status.CoupledStat = pP2pEntry->coupled_sink_status.CoupledStat; + } +#endif /* WFD_SUPPORT */ + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, RT_P2P_DEVICE_FIND, NULL, &p2p_dev_info, sizeof(RT_P2P_DEV_FOUND)); + break; + case RT_P2P_RECV_PROV_REQ: + { + PRT_P2P_CONFIG pP2pCtrl = &pAd->P2pCfg; + RTMPZeroMemory(&p2p_dev_info, sizeof(RT_P2P_DEV_FOUND)); + printk("RT_P2P_RECV_PROV_REQ\n"); + if (Addr) + RTMPMoveMemory(p2p_dev_info.addr, Addr, MAC_ADDR_LEN); + RTMPMoveMemory(p2p_dev_info.dev_addr, pP2pEntry->addr, MAC_ADDR_LEN); + RTMPMoveMemory(p2p_dev_info.dev_name, pP2pEntry->DeviceName, pP2pEntry->DeviceNameLen); + p2p_dev_info.config_methods = pP2pCtrl->ConfigMethod; + p2p_dev_info.dpid = pP2pCtrl->Dpid; + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, RT_P2P_RECV_PROV_REQ, NULL, &p2p_dev_info, sizeof(RT_P2P_DEV_FOUND)); + } + break; + case RT_P2P_RECV_PROV_RSP: + RTMPMoveMemory(p2p_prov_disc_rsp.peer, pP2pEntry->addr, MAC_ADDR_LEN); + p2p_prov_disc_rsp.config_methods = pP2pEntry->ConfigMethod; + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, RT_P2P_RECV_PROV_RSP, NULL, &p2p_prov_disc_rsp, sizeof(RT_P2P_PROV_DISC_RESP)); + break; + case RT_P2P_RECV_GO_NEGO_REQ: + { + RTMPZeroMemory(&p2p_go_neg_req_rx, sizeof(RT_P2P_GO_NEG_REQ_RX)); + printk("RT_P2P_RECV_GO_NEGO_REQ\n"); + RTMPMoveMemory(p2p_go_neg_req_rx.src, pP2pEntry->addr, MAC_ADDR_LEN); + p2p_go_neg_req_rx.dev_passwd_id = pP2pEntry->ConfigMethod; + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, RT_P2P_RECV_GO_NEGO_REQ, NULL, &p2p_go_neg_req_rx, sizeof(RT_P2P_GO_NEG_REQ_RX)); + } + break; + case RT_P2P_GO_NEG_COMPLETED: + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, RT_P2P_GO_NEG_COMPLETED, NULL, NULL, 0); + break; + + case RT_P2P_WPS_COMPLETED: + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, RT_P2P_WPS_COMPLETED, NULL, NULL, 0); + break; + + case RT_P2P_CONNECTED: + RTMPZeroMemory(&p2p_group_info, sizeof(RT_P2P_GROUP_INFO)); + if (P2P_GO_ON(pAd)) + { + p2p_group_info.Rule = 1; + RTMPMoveMemory(p2p_group_info.Bssid, pAd->P2PCurrentAddress, MAC_ADDR_LEN); + RTMPMoveMemory(p2p_group_info.Ssid, pAd->ApCfg.MBSSID[MAIN_MBSSID].Ssid, pAd->ApCfg.MBSSID[MAIN_MBSSID].SsidLen); + RTMPMoveMemory(p2p_group_info.peer, Addr, MAC_ADDR_LEN); + } + else + { + p2p_group_info.Rule = 2; + RTMPMoveMemory(p2p_group_info.Bssid, pAd->P2pCfg.Bssid, MAC_ADDR_LEN); + RTMPMoveMemory(p2p_group_info.Ssid, pAd->P2pCfg.SSID, pAd->P2pCfg.SSIDLen); + RTMPMoveMemory(p2p_group_info.peer, Addr, MAC_ADDR_LEN); + } +#ifdef WFD_SUPPORT + p2pIdx = P2pGroupTabSearch(pAd, Addr); + if (p2pIdx < MAX_P2P_GROUP_SIZE) + p2p_group_info.rtsp_port = pAd->P2pTable.Client[p2pIdx].rtsp_port; +#endif /* WFD_SUPPORT */ + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, RT_P2P_CONNECTED, NULL, &p2p_group_info, sizeof(RT_P2P_GROUP_INFO)); + break; + case RT_P2P_DISCONNECTED: + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, RT_P2P_DISCONNECTED, NULL, NULL, 0); + break; + case RT_P2P_CONNECT_FAIL: + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, RT_P2P_CONNECT_FAIL, NULL, NULL, 0); + break; + case RT_P2P_LEGACY_CONNECTED: + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, RT_P2P_LEGACY_CONNECTED, NULL, NULL, 0); + break; + case RT_P2P_LEGACY_DISCONNECTED: + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, RT_P2P_LEGACY_DISCONNECTED, NULL, NULL, 0); + break; + } +} +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ + +#ifdef DPA_S +VOID P2pSendDevFoundEvent( + IN PRTMP_ADAPTER pAd, + IN INT flags, + IN CHAR Rssi, + IN PUCHAR pPeerDeviceName, + IN UCHAR DeviceNameLen, + IN PUCHAR P2PSubelement, + IN ULONG P2PSubelementLen) +{ + PUCHAR pBuf = NULL; + ULONG offset = 0, BufLen = P2PSubelementLen + P2P_DEVICE_NAME_LEN + sizeof(INT) + sizeof(CHAR) + sizeof(ULONG); + ULONG p2p_len = 0; + + os_alloc_mem(NULL, &pBuf, BufLen); + if (pBuf) + { + NdisZeroMemory(pBuf, BufLen); + + NdisMoveMemory(pBuf, &flags, sizeof(INT)); + offset += sizeof(INT); + NdisMoveMemory(pBuf+offset, &Rssi, sizeof(CHAR)); + offset += sizeof(CHAR); + if (pPeerDeviceName) + NdisMoveMemory(pBuf+offset, pPeerDeviceName, DeviceNameLen); + offset += P2P_DEVICE_NAME_LEN; + if (P2PSubelementLen != 0) + NdisMoveMemory(pBuf+offset, &P2PSubelementLen, sizeof(ULONG)); + offset += sizeof(ULONG); + if (P2PSubelement) + NdisMoveMemory(pBuf+offset, P2PSubelement, P2PSubelementLen); + + RtmpOSNotifyRawData(pAd->p2p_dev, pBuf, BufLen, 0, ETH_P_DPA_S_NOTIF); + os_free_mem(NULL, pBuf); + } + +} + +VOID P2pSendPeerNegoReqEvent( + IN PRTMP_ADAPTER pAd, + IN INT flags, + IN USHORT PeerDPID, + IN PUCHAR pPeerAddr, + IN UCHAR RspStatus, + IN PUCHAR pPeerDeviceName, + IN UCHAR DeviceNameLen, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN UCHAR PeerDevType, + IN UCHAR LisChannel) +{ + PUCHAR pBuf = NULL; + ULONG offset = 0; + + /* + BufLen: len of (flags+PeerDPID+pPeerAddr+DeviceName+RspStatus+RspStatus+Ssid+SsidLen+PeerDevType+null_terminal) + */ + ULONG BufLen = sizeof(INT) + + sizeof(USHORT) + + MAC_ADDR_LEN + + P2P_DEVICE_NAME_LEN + + sizeof(UCHAR) + + sizeof(UCHAR) + + MAX_LEN_OF_SSID + + sizeof(UCHAR) + + sizeof(UCHAR) + + 1; /* 1 is for null terminal */ + + os_alloc_mem(NULL, &pBuf, BufLen); + if (pBuf) + { + NdisZeroMemory(pBuf, BufLen); + + NdisMoveMemory(pBuf, &flags, sizeof(INT)); + offset += sizeof(INT); + NdisMoveMemory(pBuf+offset, &PeerDPID, sizeof(USHORT)); + offset += sizeof(USHORT); + NdisMoveMemory(pBuf+offset, pPeerAddr, MAC_ADDR_LEN); + offset += MAC_ADDR_LEN; + if (pPeerDeviceName != NULL) + { + pBuf[offset] = DeviceNameLen; + RTMPMoveMemory(pBuf+offset+1, pPeerDeviceName, DeviceNameLen); + } + else + pBuf[offset] = 0; + offset += (P2P_DEVICE_NAME_LEN + sizeof(UCHAR)); + pBuf[offset] = RspStatus; + offset += sizeof(UCHAR); + if (pSsid != NULL) + { + pBuf[offset] = SsidLen; + RTMPMoveMemory(pBuf+offset+1, pSsid, SsidLen); + } + else + pBuf[offset] = 0; + offset += (MAX_LEN_OF_SSID + sizeof(UCHAR)); + pBuf[offset] = PeerDevType; + offset += sizeof(UCHAR); + pBuf[offset] = LisChannel; + hex_dump("P2pSendPeerNegoReqEvent", pBuf, BufLen); + RtmpOSNotifyRawData(pAd->p2p_dev, pBuf, BufLen, 0, ETH_P_DPA_S_NOTIF); + os_free_mem(NULL, pBuf); + } +} + +VOID P2pSendSamsungEvent( + IN PRTMP_ADAPTER pAd, + IN INT flags, + IN PUCHAR pPeerAddr, + IN PUCHAR pPeerDeviceName, + IN UCHAR DeviceNameLen) +{ + PUCHAR pBuf = NULL; + UINT32 offset = 0, BufLen = sizeof(INT) + MAC_ADDR_LEN + P2P_DEVICE_NAME_LEN + sizeof(UCHAR) + 1; /* 1 is for null terminal */ + + os_alloc_mem(NULL, &pBuf, BufLen); + + if (pBuf) + { + RTMPZeroMemory(pBuf, BufLen); + NdisMoveMemory(pBuf, &flags, sizeof(INT)); + offset += sizeof(INT); + RTMPMoveMemory(pBuf+offset, pPeerAddr, MAC_ADDR_LEN); + offset += MAC_ADDR_LEN; + if (pPeerDeviceName != NULL) + { + pBuf[offset] = DeviceNameLen; + RTMPMoveMemory(pBuf+offset+1, pPeerDeviceName, DeviceNameLen); + } + else + pBuf[offset] = 0; + RtmpOSNotifyRawData(pAd->p2p_dev, pBuf, BufLen, 0, ETH_P_DPA_S_NOTIF); + os_free_mem(NULL, pBuf); + } +} + +VOID P2pMaintainGroupTable( + IN PRTMP_ADAPTER pAd, + IN ULONG MaxRxTimeDiff, + IN UCHAR MaxSameRxTimeCount) +{ + INT i, j; + UCHAR total_bssNr = pAd->P2pTable.ClientNumber; + BOOLEAN bDelEntry = FALSE; + ULONG now_time = 0; + PRT_P2P_TABLE pTab = &pAd->P2pTable; + + RTMP_SEM_LOCK(&pAd->P2pTableSemLock); + + for (i = 0; i < total_bssNr; i++) + { + PRT_P2P_CLIENT_ENTRY pP2pEntry = &pTab->Client[i]; + + bDelEntry = FALSE; + if (pP2pEntry->LastRxTimeA != pP2pEntry->LastRxTime) + { + pP2pEntry->LastRxTimeA = pP2pEntry->LastRxTime; + pP2pEntry->SameRxTimeCount = 0; + } + else + pP2pEntry->SameRxTimeCount++; + + NdisGetSystemUpTime(&now_time); + if (pP2pEntry->SameRxTimeCount > MaxSameRxTimeCount) + bDelEntry = TRUE; + else if (RTMP_TIME_AFTER(now_time, pP2pEntry->LastRxTime + (MaxRxTimeDiff * OS_HZ))) + bDelEntry = TRUE; + + if (NdisEqualMemory(pP2pEntry->addr, pAd->P2pCfg.Bssid, MAC_ADDR_LEN)) + bDelEntry = FALSE; + + if (bDelEntry) + { + UCHAR *pOldAddr = NULL; + + P2pSendDevFoundEvent(pAd, P2P_NOTIF_DISCOVER_FOUND_PEERS, 0, NULL, 0, NULL, 0); + + for (j = i; j < (total_bssNr - 1); j++) + { + NdisMoveMemory(&(pTab->Client[j]), &(pTab->Client[j + 1]), sizeof(RT_P2P_CLIENT_ENTRY)); + } + + NdisZeroMemory(&(pTab->Client[total_bssNr - 1]), sizeof(RT_P2P_CLIENT_ENTRY)); + + total_bssNr -= 1; + } + } + pTab->ClientNumber = total_bssNr; + + RTMP_SEM_UNLOCK(&pAd->P2pTableSemLock); +} + +#endif /* DPA_S */ + diff --git a/mt7620/src/common/ps.c b/mt7620/src/common/ps.c new file mode 100644 index 0000000..ab8eb3e --- /dev/null +++ b/mt7620/src/common/ps.c @@ -0,0 +1,497 @@ +/**************************************************************************** + * 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. + +***************************************************************************/ + +#define MODULE_POWER_SAVE +#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( + 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); + +#ifdef DOT11Z_TDLS_SUPPORT + TDLS_UAPSDP_TrafficIndSend(pAd, pMacEntry->Addr); +#endif /* 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( + IN PRTMP_ADAPTER pAd, + IN PQUEUE_HEADER pQueue) +{ + PQUEUE_ENTRY pEntry; + PNDIS_PACKET pPacket; + + DBGPRINT(RT_DEBUG_TRACE, ("RtmpCleanupPsQueue (0x%08lx)...\n", (ULONG)pQueue)); + + while (pQueue->Head) + { + DBGPRINT(RT_DEBUG_TRACE, + ("RtmpCleanupPsQueue %ld...\n",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); + + 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( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN USHORT Aid, + IN BOOLEAN isActive) +{ + PQUEUE_ENTRY pEntry; + PMAC_TABLE_ENTRY pMacEntry; + unsigned long IrqFlags; + + /*DBGPRINT(RT_DEBUG_TRACE,("rcv PS-POLL (AID=%d) from %02x:%02x:%02x:%02x:%02x:%02x\n", */ + /* Aid, pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5])); */ + + pMacEntry = &pAd->MacTab.Content[Aid]; + if (RTMPEqualMemory(pMacEntry->Addr, pAddr, MAC_ADDR_LEN)) + { + /* + 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 */ + } /* End of if */ +#endif /* UAPSD_SUPPORT */ + + /*NdisAcquireSpinLock(&pAd->MacTabLock); */ + /*NdisAcquireSpinLock(&pAd->TxSwQueueLock); */ + 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 */ + + pEntry = RemoveHeadQueue(&pMacEntry->PsQueue); + if ( pMacEntry->PsQueue.Number >=1 ) + RTMP_SET_PACKET_MOREDATA(RTPKT_TO_OSPKT(pEntry), TRUE); + InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QID_AC_BE], pEntry); + +#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(pEntry)) || + RTMP_GET_PACKET_EAPOL(RTPKT_TO_OSPKT(pEntry)) || + RTMP_GET_PACKET_WAI(RTPKT_TO_OSPKT(pEntry))) + { + /* + 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, + 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) + { +/* if (pAd->TxSwQueue[QID_AC_BE].Number <= */ +/* (pAd->PortCfg.TxQueueSize + (MAX_PACKETS_IN_PS_QUEUE>>1))) */ + { + pEntry = RemoveHeadQueue(&pMacEntry->PsQueue); + InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QID_AC_BE], pEntry); + } +/* else */ +/* break; */ + /* End of if */ + } /* End of while */ + } /* End of if */ + + /*NdisReleaseSpinLock(&pAd->TxSwQueueLock); */ + /*NdisReleaseSpinLock(&pAd->MacTabLock); */ + + if ((Aid > 0) && (Aid < MAX_LEN_OF_MAC_TABLE) && + (pMacEntry->PsQueue.Number == 0)) + { + /* clear corresponding TIM bit because no any PS packet */ +#ifdef CONFIG_AP_SUPPORT + WLAN_MR_TIM_BIT_CLEAR(pAd, pMacEntry->apidx, 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", + Aid, pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5])); + + } +} + + +/* + ========================================================================== + 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( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN ULONG Wcid, + IN 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; +/* if (pEntry) */ + { + /* + 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 == PWR_ACTIVE) && (Psm == PWR_SAVE)) + { + DBGPRINT(RT_DEBUG_TRACE, + ("RtmpPsIndicate - %02x:%02x:%02x:%02x:%02x:%02x sleep!\n", + pAddr[0],pAddr[1],pAddr[2],pAddr[3],pAddr[4],pAddr[5])); + } + + if ((old_psmode == PWR_SAVE) && (Psm == PWR_ACTIVE)) + { + /* TODO: For RT2870, how to handle about the BA when STA in PS mode???? */ +#ifdef RTMP_MAC_PCI +#ifdef DOT11_N_SUPPORT + /* When sta wake up, we send BAR to refresh the BA sequence. */ + SendRefreshBAR(pAd, pEntry); +#endif /* DOT11_N_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + + DBGPRINT(RT_DEBUG_TRACE, + ("RtmpPsIndicate - %02x:%02x:%02x:%02x:%02x:%02x wakes up, " + "act like rx PS-POLL\n", + pAddr[0],pAddr[1],pAddr[2],pAddr[3],pAddr[4],pAddr[5])); + + /* sleep station awakes, move all pending frames from PSQ to TXQ if any */ + RtmpHandleRxPsPoll(pAd, pAddr, pEntry->Aid, TRUE); + } + + /* move to above section */ +/* pEntry->NoDataIdleCount = 0; */ +/* pEntry->PsMode = Psm; */ + } +/* else */ +/* { */ + /* not in table, try to learn it ???? why bother? */ +/* } */ + 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( + IN PRTMP_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( + IN PRTMP_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( + IN PRTMP_ADAPTER pAd, + IN 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; +#ifdef DOT11Z_TDLS_SUPPORT + pAd->StaCfg.DefaultListenCount = 1; +#else + pAd->StaCfg.DefaultListenCount = 3; +#endif // DOT11Z_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 */ + +/* End of ps.c */ diff --git a/mt7620/src/common/rt2860.bin b/mt7620/src/common/rt2860.bin new file mode 100755 index 0000000..5a058e1 Binary files /dev/null and b/mt7620/src/common/rt2860.bin differ diff --git a/mt7620/src/common/rt2860.bin.dfs b/mt7620/src/common/rt2860.bin.dfs new file mode 100755 index 0000000..dcdc97b Binary files /dev/null and b/mt7620/src/common/rt2860.bin.dfs differ diff --git a/mt7620/src/common/rt_channel.c b/mt7620/src/common/rt_channel.c new file mode 100644 index 0000000..f755e70 --- /dev/null +++ b/mt7620/src/common/rt_channel.c @@ -0,0 +1,2144 @@ +/* + +*/ +#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); + +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}, + {} +}; + +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, 7, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region8_ChDesc_5GHZ[] = +{ + {52, 4, CHANNEL_DEFAULT_PROP}, + {} +}; + +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}, + {} +}; + +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}, + {} +}; + +CH_DESC Country_Region12_ChDesc_5GHZ[] = +{ + {36, 8, CHANNEL_DEFAULT_PROP}, + {100, 11, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region13_ChDesc_5GHZ[] = +{ + {52, 4, CHANNEL_DEFAULT_PROP}, + {100, 11, CHANNEL_DEFAULT_PROP}, + {149, 4, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region14_ChDesc_5GHZ[] = +{ + {36, 8, CHANNEL_DEFAULT_PROP}, + {100, 5, CHANNEL_DEFAULT_PROP}, + {136, 2, 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, 4, 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}, + {} +}; + +#ifdef CONFIG_SAMSUNG_REGULATORY_SUPPORT +CH_DESC Country_Region30_ChDesc_5GHZ[] = +{ + {36, 4, CHANNEL_DEFAULT_PROP}, + {52, 4, CHANNEL_PASSIVE_SCAN}, + {100, 11, CHANNEL_PASSIVE_SCAN}, + {149, 5, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region31_ChDesc_5GHZ[] = +{ + {52, 4, CHANNEL_PASSIVE_SCAN}, + {100, 11, CHANNEL_PASSIVE_SCAN}, + {149, 5, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region32_ChDesc_5GHZ[] = +{ + {36, 4, CHANNEL_DEFAULT_PROP}, + {52, 4, CHANNEL_PASSIVE_SCAN}, + {100, 11, CHANNEL_PASSIVE_SCAN}, + {149, 4, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region33_ChDesc_5GHZ[] = +{ + {36, 4, CHANNEL_DEFAULT_PROP}, + {52, 4, CHANNEL_PASSIVE_SCAN}, + {100, 11, CHANNEL_PASSIVE_SCAN}, + {} +}; + +CH_DESC Country_Region34_ChDesc_5GHZ[] = +{ + {36, 4, CHANNEL_DEFAULT_PROP}, + {52, 4, CHANNEL_PASSIVE_SCAN}, + {149, 5, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region35_ChDesc_5GHZ[] = +{ + {36, 4, CHANNEL_DEFAULT_PROP}, + {52, 4, CHANNEL_PASSIVE_SCAN}, + {} +}; + +CH_DESC Country_Region36_ChDesc_5GHZ[] = +{ + {36, 4, CHANNEL_DEFAULT_PROP}, + {100, 11, CHANNEL_PASSIVE_SCAN}, + {149, 5, CHANNEL_DEFAULT_PROP}, + {} +}; + +CH_DESC Country_Region37_ChDesc_5GHZ[] = +{ + {36, 4, CHANNEL_DEFAULT_PROP}, + {52, 4, CHANNEL_PASSIVE_SCAN}, + {149, 5, CHANNEL_DEFAULT_PROP}, + {173, 1, CHANNEL_DEFAULT_PROP}, + {} +}; +#endif // CONFIG_SAMSUNG_REGULATORY_SUPPORT // + +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}, +#ifdef CONFIG_SAMSUNG_REGULATORY_SUPPORT + {REGION_30_A_BAND, Country_Region30_ChDesc_5GHZ}, + {REGION_31_A_BAND, Country_Region31_ChDesc_5GHZ}, + {REGION_32_A_BAND, Country_Region32_ChDesc_5GHZ}, + {REGION_33_A_BAND, Country_Region33_ChDesc_5GHZ}, + {REGION_34_A_BAND, Country_Region34_ChDesc_5GHZ}, + {REGION_35_A_BAND, Country_Region35_ChDesc_5GHZ}, + {REGION_36_A_BAND, Country_Region36_ChDesc_5GHZ}, + {REGION_37_A_BAND, Country_Region37_ChDesc_5GHZ}, +#endif // CONFIG_SAMSUNG_REGULATORY_SUPPORT // + {} +}; + +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, 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*/ +}; +/*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 */ + { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 20 */ + { 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, 3, 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}, /* Albania */ + {"DZ", CE, Country_DZ_ChDesp}, /* Algeria */ + {"AR", CE, Country_AR_ChDesp}, /* Argentina */ + {"AM", CE, Country_AM_ChDesp}, /* Armenia */ + {"AW", CE, Country_AW_ChDesp}, /* Aruba */ + {"AU", CE, Country_AU_ChDesp}, /* Australia */ + {"AT", CE, Country_AT_ChDesp}, /* Austria */ + {"AZ", CE, Country_AZ_ChDesp}, /* Azerbaijan */ + {"BH", CE, Country_BH_ChDesp}, /* Bahrain */ + {"BD", CE, Country_BD_ChDesp}, /* Bangladesh */ + {"BB", CE, Country_BB_ChDesp}, /* Barbados */ + {"BY", CE, Country_BY_ChDesp}, /* Belarus */ + {"BE", CE, Country_BE_ChDesp}, /* Belgium */ + {"BZ", CE, Country_BZ_ChDesp}, /* Belize */ + {"BO", CE, Country_BO_ChDesp}, /* Bolivia */ + {"BA", CE, Country_BA_ChDesp}, /* Bosnia and Herzegovina */ + {"BR", CE, Country_BR_ChDesp}, /* Brazil */ + {"BN", CE, Country_BN_ChDesp}, /* Brunei Darussalam */ + {"BG", CE, Country_BG_ChDesp}, /* Bulgaria */ + {"KH", CE, Country_KH_ChDesp}, /* Cambodia */ + {"CA", FCC,Country_CA_ChDesp}, /* Canada */ + {"CL", CE, Country_CL_ChDesp}, /* Chile */ + {"CN", CE, Country_CN_ChDesp}, /* China */ + {"CO", CE, Country_CO_ChDesp}, /* Colombia */ + {"CR", CE, Country_CR_ChDesp}, /* Costa Rica */ + {"HR", CE, Country_HR_ChDesp}, /* Croatia */ + {"CY", CE, Country_CY_ChDesp}, /* Cyprus */ + {"CZ", CE, Country_CZ_ChDesp}, /* Czech Republic */ + {"DK", CE, Country_DK_ChDesp}, /* Denmark */ + {"DO", CE, Country_DO_ChDesp}, /* Dominican Republic */ + {"EC", CE, Country_EC_ChDesp}, /* Ecuador */ + {"EG", CE, Country_EG_ChDesp}, /* Egypt */ + {"SV", CE, Country_SV_ChDesp}, /* El Salvador */ + {"EE", CE, Country_EE_ChDesp}, /* Estonia */ + {"FI", CE, Country_FI_ChDesp}, /* Finland */ + {"FR", CE, Country_FR_ChDesp}, /* France */ + {"GE", CE, Country_GE_ChDesp}, /* Georgia */ + {"DE", CE, Country_DE_ChDesp}, /* Germany */ + {"GR", CE, Country_GR_ChDesp}, /* Greece */ + {"GL", CE, Country_GL_ChDesp}, /* Greenland */ + {"GD", CE, Country_GD_ChDesp}, /* Grenada */ + {"GU", CE, Country_GU_ChDesp}, /* Guam */ + {"GT", CE, Country_GT_ChDesp}, /* Guatemala */ + {"HT", CE, Country_HT_ChDesp}, /* Haiti */ + {"HN", CE, Country_HN_ChDesp}, /* Honduras */ + {"HK", CE, Country_HK_ChDesp}, /* Hong Kong */ + {"HU", CE, Country_HU_ChDesp}, /* Hungary */ + {"IS", CE, Country_IS_ChDesp}, /* Iceland */ + {"IN", CE, Country_IN_ChDesp}, /* India */ + {"ID", CE, Country_ID_ChDesp}, /* Indonesia */ + {"IR", CE, Country_IR_ChDesp}, /* Iran, Islamic Republic of */ + {"IE", CE, Country_IE_ChDesp}, /* Ireland */ + {"IL", CE, Country_IL_ChDesp}, /* Israel */ + {"IT", CE, Country_IT_ChDesp}, /* Italy */ + {"JM", CE, Country_JM_ChDesp}, /* Jamaica */ + {"JP", JAP,Country_JP_ChDesp}, /* Japan */ + {"JO", CE, Country_JO_ChDesp}, /* Jordan */ + {"KZ", CE, Country_KZ_ChDesp}, /* Kazakhstan */ + {"KE", CE, Country_KE_ChDesp}, /* Kenya */ + {"KP", CE, Country_KP_ChDesp}, /* Korea, Democratic People's Republic of */ + {"KR", CE, Country_KR_ChDesp}, /* Korea, Republic of */ + {"KW", CE, Country_KW_ChDesp}, /* Kuwait */ + {"LV", CE, Country_LV_ChDesp}, /* Latvia */ + {"LB", CE, Country_LB_ChDesp}, /* Lebanon */ + {"LI", CE, Country_LI_ChDesp}, /* Liechtenstein */ + {"LT", CE, Country_LT_ChDesp}, /* Lithuania */ + {"LU", CE, Country_LU_ChDesp}, /* Luxembourg */ + {"MO", CE, Country_MO_ChDesp}, /* Macao */ + {"MK", CE, Country_MK_ChDesp}, /* Macedonia, Republic of */ + {"MY", CE, Country_MY_ChDesp}, /* Malaysia */ + {"MT", CE, Country_MT_ChDesp}, /* Malta */ + {"MX", CE, Country_MX_ChDesp}, /* Mexico */ + {"MC", CE, Country_MC_ChDesp}, /* Monaco */ + {"MA", CE, Country_MA_ChDesp}, /* Morocco */ + {"NP", CE, Country_NP_ChDesp}, /* Nepal */ + {"NL", CE, Country_NL_ChDesp}, /* Netherlands */ + {"AN", CE, Country_AN_ChDesp}, /* Netherlands Antilles */ + {"NZ", CE, Country_NZ_ChDesp}, /* New Zealand */ + {"NO", CE, Country_NO_ChDesp}, /* Norway */ + {"OM", CE, Country_OM_ChDesp}, /* Oman */ + {"PK", CE, Country_PK_ChDesp}, /* Pakistan */ + {"PA", CE, Country_PA_ChDesp}, /* Panama */ + {"PG", CE, Country_PG_ChDesp}, /* Papua New Guinea */ + {"PE", CE, Country_PE_ChDesp}, /* Peru */ + {"PH", CE, Country_PH_ChDesp}, /* Philippines */ + {"PL", CE, Country_PL_ChDesp}, /* Poland */ + {"PT", CE, Country_PT_ChDesp}, /* Portuga l*/ + {"PR", CE, Country_PR_ChDesp}, /* Puerto Rico */ + {"QA", CE, Country_QA_ChDesp}, /* Qatar */ + {"RO", CE, Country_RO_ChDesp}, /* Romania */ + {"RU", CE, Country_RU_ChDesp}, /* Russian Federation */ + {"BL", CE, Country_BL_ChDesp}, /* Saint Barth'elemy */ + {"SA", CE, Country_SA_ChDesp}, /* Saudi Arabia */ + {"SG", CE, Country_SG_ChDesp}, /* Singapore */ + {"SK", CE, Country_SK_ChDesp}, /* Slovakia */ + {"SI", CE, Country_SI_ChDesp}, /* Slovenia */ + {"ZA", CE, Country_ZA_ChDesp}, /* South Africa */ + {"ES", CE, Country_ES_ChDesp}, /* Spain */ + {"LK", CE, Country_LK_ChDesp}, /* Sri Lanka */ + {"SE", CE, Country_SE_ChDesp}, /* Sweden */ + {"CH", CE, Country_CH_ChDesp}, /* Switzerland */ + {"SY", CE, Country_SY_ChDesp}, /* Syrian Arab Republic */ + {"TW", FCC,Country_TW_ChDesp}, /* Taiwan */ + {"TH", CE, Country_TH_ChDesp}, /* Thailand */ + {"TT", CE, Country_TT_ChDesp}, /* Trinidad and Tobago */ + {"TN", CE, Country_TN_ChDesp}, /* Tunisia */ + {"TR", CE, Country_TR_ChDesp}, /* Turkey */ + {"UA", CE, Country_UA_ChDesp}, /* Ukraine */ + {"AE", CE, Country_AE_ChDesp}, /* United Arab Emirates */ + {"GB", CE, Country_GB_ChDesp}, /* United Kingdom */ + {"US", FCC,Country_US_ChDesp}, /* United States */ + {"UY", CE, Country_UY_ChDesp}, /* Uruguay */ + {"UZ", CE, Country_UZ_ChDesp}, /* Uzbekistan */ + {"VE", CE, Country_VE_ChDesp}, /* Venezuela */ + {"VN", CE, Country_VN_ChDesp}, /* Viet Nam */ + {"YE", CE, Country_YE_ChDesp}, /* Yemen */ + {"ZW", CE, Country_ZW_ChDesp}, /* Zimbabwe */ + {"EU", CE, Country_EU_ChDesp}, /* Europe */ + {"NA", FCC,Country_NA_ChDesp}, /* North America */ + {"WO", CE, Country_WO_ChDesp}, /* World Wide */ + {"" , 0, NULL} , /* 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) +{ + switch(PhyMode) + { + case PHY_11A: +#ifdef DOT11_N_SUPPORT + case PHY_11AN_MIXED: + case PHY_11N_5G: +#endif /* DOT11_N_SUPPORT */ + *pChType = BAND_5G; + break; + case PHY_11ABG_MIXED: +#ifdef DOT11_N_SUPPORT + case PHY_11AGN_MIXED: + case PHY_11ABGN_MIXED: +#endif /* DOT11_N_SUPPORT */ + *pChType = BAND_BOTH; + break; + + default: + *pChType = BAND_24G; + break; + } +} + +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) && (pAd->CommonCfg.PhyMode != PHY_11B) ) + { + 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; +#endif /* DOT11_N_SUPPORT */ + +#ifdef RT_CFG80211_SUPPORT + CFG80211OS_ChanInfoInit( + pAd->pCfg80211_CB, + j, + pAd->ChannelList[j].Channel, + pAd->ChannelList[j].MaxTxPwr, + (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED), + (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 */ + +#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; +} + +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( + IN PRTMP_ADAPTER pAd) +{ + /*UCHAR ChannelNum = pAd->ChannelListNum;*/ + UCHAR Channel = pAd->CommonCfg.Channel; + + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)) + { + 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)) + { + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; + } + else if ((Channel == 40) || (Channel == 48) || (Channel == 56) || (Channel == 64) || (Channel == 104) || (Channel == 112) || + (Channel == 120) || (Channel == 128) || (Channel == 136) || (Channel == 153) || (Channel == 161)) + { + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; + } + else + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + } + } + 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()*/ + } + } + } + +#ifdef CONFIG_AP_SUPPORT +#ifdef DOT11N_DRAFT3 +#endif /* DOT11N_DRAFT3 */ +#endif /* CONFIG_AP_SUPPORT */ + +} + + +VOID N_SetCenCh( + IN PRTMP_ADAPTER pAd) +{ + if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + { + if (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + { + + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2; + } + else + { + if (pAd->CommonCfg.Channel == 14) + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 1; + else + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2; + } + } + else + { + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + } +} +#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 ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (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 ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && + (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/mt7620/src/common/rt_led.c b/mt7620/src/common/rt_led.c new file mode 100644 index 0000000..442d685 --- /dev/null +++ b/mt7620/src/common/rt_led.c @@ -0,0 +1,1146 @@ +/**************************************************************************** + * 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 + +#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 CONFIG_WIFI_LED_SHARE + case LINK_STATUS_WPS_PRE_STAGE: + pCurrentLedCfg->field.LedActMode = MCU_LED_ACT_WPS_PRE_STAGE; + pWPSLedTimeUnit->OnPeriod = 0.5 * 1000 / LED_CHECK_INTERVAL; + pWPSLedTimeUnit->OffPeriod = 0.5 * 1000 / LED_CHECK_INTERVAL; + pWPSLedTimeUnit->BlinkPeriod = INFINITE_PERIOD; + pWPSLedTimeUnit->RestPeriod = 0; + break; + case LINK_STATUS_WPS_POST_STAGE: + pCurrentLedCfg->field.LedActMode = MCU_LED_ACT_WPS_POST_STAGE; + pWPSLedTimeUnit->OnPeriod = 0.5 * 1000 / LED_CHECK_INTERVAL; + pWPSLedTimeUnit->OffPeriod = 0.5 * 1000 / LED_CHECK_INTERVAL; + pWPSLedTimeUnit->BlinkPeriod = INFINITE_PERIOD; + pWPSLedTimeUnit->RestPeriod = 0; + break; +#endif /* CONFIG_WIFI_LED_SHARE */ +#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_LED_SUPPORT */ +#endif /* WSC_INCLUDED */ + 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 & 0x02); //skip check hcca for wifi 4.2.10 + //return (RegValue & 0x06); +} + +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 complete interrupt + RTMP_IO_WRITE32(pAd, MCU_INT_STATUS, 0x1A); + + 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 + */ +#ifdef RT5350 +//#if defined(RT5350) || defined(RT6352) + LedCfgBuf.field.LED_POL = !pCurrentLedCfg->field.LedActPolarity; +#else + LedCfgBuf.field.LED_POL = pCurrentLedCfg->field.LedActPolarity; +#endif + 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; +} + + +#ifdef CONFIG_WIFI_LED_SHARE +static void WPSChgMacLedCfg(IN PRTMP_ADAPTER pAd) +{ + LED_CFG_T LedCfgBuf; + PWPS_LED_TIME_UNIT pWPSLedTimeUnit = &pAd->LedCntl.SWMCULedCntl.WPSLedTimeUnit; + + if (pWPSLedTimeUnit->LeftBlinkPeriod) + { + if (pWPSLedTimeUnit->LeftOnPeriod) + { + LedCfgBuf.field.G_LED_MODE = MAC_LED_ON; /* Solid on */ + pWPSLedTimeUnit->LeftOnPeriod--; + + if(!pWPSLedTimeUnit->LeftOnPeriod) + { + pWPSLedTimeUnit->LeftOffPeriod = pWPSLedTimeUnit->OffPeriod; + if (!pWPSLedTimeUnit->LeftOffPeriod) + pWPSLedTimeUnit->LeftOnPeriod = pWPSLedTimeUnit->OnPeriod; + } + } + else if (pWPSLedTimeUnit->LeftOffPeriod) + { + LedCfgBuf.field.G_LED_MODE = MAC_LED_OFF; /* Off */ + pWPSLedTimeUnit->LeftOffPeriod--; + + if (!pWPSLedTimeUnit->LeftOffPeriod) + { + pWPSLedTimeUnit->LeftOnPeriod = pWPSLedTimeUnit->OnPeriod; + if (!pWPSLedTimeUnit->LeftOnPeriod) + pWPSLedTimeUnit->LeftOffPeriod = pWPSLedTimeUnit->OffPeriod; + } + } + + pWPSLedTimeUnit->LeftBlinkPeriod--; + + if(!pWPSLedTimeUnit->LeftBlinkPeriod) + { + pWPSLedTimeUnit->LeftRestPeriod = pWPSLedTimeUnit->RestPeriod; + if (!pWPSLedTimeUnit->LeftRestPeriod) + pWPSLedTimeUnit->LeftBlinkPeriod = pWPSLedTimeUnit->BlinkPeriod; + } + } + else if (pWPSLedTimeUnit->LeftRestPeriod) + { + LedCfgBuf.field.G_LED_MODE = MAC_LED_ON; /* Off */ + pWPSLedTimeUnit->LeftRestPeriod--; + if (!pWPSLedTimeUnit->LeftRestPeriod) + { + pWPSLedTimeUnit->LeftBlinkPeriod = pWPSLedTimeUnit->BlinkPeriod; + if (!pWPSLedTimeUnit->LeftBlinkPeriod) + pWPSLedTimeUnit->LeftRestPeriod = pWPSLedTimeUnit->RestPeriod; + } + } + + RTMP_IO_WRITE32(pAd, MAC_LED_CFG, LedCfgBuf.word); +} +#endif /* CONFIG_WIFI_LED_SHARE */ + + +/* 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; +#ifdef CONFIG_WIFI_LED_SHARE + case WPS_LED_MODE_SHARE: + WPSChgMacLedCfg(pAd); + break; +#endif /* CONFIG_WIFI_LED_SHARE */ + 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; +#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 */ + + +#ifdef CONFIG_ZTE_RADIO_ONOFF + if (!pAd->CommonCfg.bRadioEnable) + { + return; + } +#endif /* CONFIG_ZTE_RADIO_ONOFF */ + + LedMode = LED_MODE(pAd); + 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 +#ifdef CONFIG_WIFI_LED_SHARE + case LED_WPS_PRE_STAGE: + if (WscSupportWPSLEDMode(pAd)) + { + LinkStatus = LINK_STATUS_WPS_PRE_STAGE; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_PRE_STAGE; + } + else + bIgnored = TRUE; + break; + case LED_WPS_POST_STAGE: + if (WscSupportWPSLEDMode(pAd)) + { + LinkStatus = LINK_STATUS_WPS_PRE_STAGE; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_POST_STAGE; + } + else + bIgnored = TRUE; + break; +#endif /* CONFIG_WIFI_LED_SHARE */ + 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) +#ifdef CONFIG_WIFI_LED_SHARE + ||(LED_MODE(pAd) == WPS_LED_MODE_SHARE) +#endif /* CONFIG_WIFI_LED_SHARE */ + ) + { + /* 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)) + { +#ifdef CONFIG_WIFI_LED_SHARE + USHORT value; + RT28xx_EEPROM_READ16(pAd, EEPROM_FREQ_OFFSET, value); + pAd->LedCntl.MCULedCntl.word = (value >> 8); +#endif /* CONFIG_WIFI_LED_SHARE */ + 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; + } + + 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.AuthMode == Ndis802_11AuthModeOpen) + && (pAd->StaCfg.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.AuthMode == Ndis802_11AuthModeOpen) && (pAd->StaCfg.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; + { + 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 */ + } + + 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/mt7620/src/common/rt_os_util.c b/mt7620/src/common/rt_os_util.c new file mode 100644 index 0000000..b0d0ceb --- /dev/null +++ b/mt7620/src/common/rt_os_util.c @@ -0,0 +1,224 @@ +/**************************************************************************** + + 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" + + +UINT32 RalinkRate[256] = + {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 109, 110, 111, 112, + 13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234, 260, + 39, 78, 117, 156, 234, 312, 351, 390, + 27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, + 81, 162, 243, 324, 486, 648, 729, 810, + 14, 29, 43, 57, 87, 115, 130, 144, 29, 59, 87, 115, 173, 230, 260, 288, + 43, 87, 130, 173, 260, 317, 390, 433, + 30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600, + 90, 180, 270, 360, 540, 720, 810, 900, + 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, + 20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39, + 40,41,42,43,44,45,46,47}; /* 3*3 +*/ + +VOID RtmpDrvMaxRateGet( + IN VOID *pReserved, +/* IN PHTTRANSMIT_SETTING pHtPhyMode, +*/ + IN UINT8 MODE, + IN UINT8 ShortGI, + IN UINT8 BW, + IN UINT8 MCS, + OUT UINT32 *pRate) +{ + int rate_index = 0; + +#ifdef DOT11_N_SUPPORT + if (MODE >= MODE_HTMIX) + { + /* rate_index = 16 + ((UCHAR)pHtPhyMode->field.BW *16) + ((UCHAR)pHtPhyMode->field.ShortGI *32) + ((UCHAR)pHtPhyMode->field.MCS); +*/ + rate_index = 16 + ((UCHAR)BW *24) + ((UCHAR)ShortGI *48) + ((UCHAR)MCS); + } + else +#endif /* DOT11_N_SUPPORT */ + if (MODE == MODE_OFDM) + rate_index = (UCHAR)(MCS) + 4; + else + rate_index = (UCHAR)(MCS); + + if (rate_index < 0) + rate_index = 0; + + if (rate_index > 255) + rate_index = 255; + + *pRate = RalinkRate[rate_index] * 500000; +} + + +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 MESH_SUPPORT + ULONG WaitCnt; + + + WaitCnt = 0; + do + { + BOOLEAN WaitMeshClose; + wait_queue_head_t wait; + + if (WaitFlag == FALSE) + break; + + WaitMeshClose = FALSE; + init_waitqueue_head(&wait); + + WaitMeshClose = RtmpMeshLinkCheck(pDrvCtrlBK); + + if(WaitMeshClose == TRUE) + wait_event_interruptible_timeout(wait, 0, 10 * OS_HZ/1000); + else + break; + } while (WaitCnt++ < 1000); +#endif /* MESH_SUPPORT */ +} + + +#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; +} + + +#if defined(WPA_SUPPLICANT_SUPPORT) || defined(APCLI_WPA_SUPPLICANT_SUPPORT) +VOID WpaSendMicFailureToWpaSupplicant( + IN PNET_DEV pNetDev, + IN BOOLEAN bUnicast) +{ + 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)); + + return; +} +#endif /* defined(WPA_SUPPLICANT_SUPPORT) || defined(APCLI_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 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 */ + +INT32 RtPrivIoctlSetVal(VOID) +{ + return (INT32)RTPRIV_IOCTL_SET; +} + +/* End of rtmp_os_util.c */ diff --git a/mt7620/src/common/rt_rf.c b/mt7620/src/common/rt_rf.c new file mode 100644 index 0000000..0486e31 --- /dev/null +++ b/mt7620/src/common/rt_rf.c @@ -0,0 +1,410 @@ +/* + *************************************************************************** + * 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 = (RfReg & ~BitMask) | ((Value) & BitMask); + RT30xxWriteRFRegister(pAd, RegID, RfReg); +} + +/* + ======================================================================== + + Routine Description: Write RT30xx 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.field.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.field.RF_CSR_WR = 1; + rfcsr.field.RF_CSR_KICK = 1; + rfcsr.field.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.field.RF_CSR_DATA = IdRf; + RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word); + RtmpOsMsDelay(1); + } + } + + rfcsr.field.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 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)); + + ret = STATUS_UNSUCCESSFUL; + do + { + RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word); + + if (!rfcsr.field.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.field.RF_CSR_WR = 1; + rfcsr.field.RF_CSR_KICK = 1; + rfcsr.field.TESTCSR_RFACC_REGNUM = (regID | (bank << 6)); + + + rfcsr.field.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(("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; ichipOps.AsicRfInit) + pAd->chipOps.AsicRfInit(pAd); +} + +#endif /* RTMP_RF_RW_SUPPORT */ + diff --git a/mt7620/src/common/rtmp_init.c b/mt7620/src/common/rtmp_init.c new file mode 100644 index 0000000..695bfba --- /dev/null +++ b/mt7620/src/common/rtmp_init.c @@ -0,0 +1,4967 @@ +/* + *************************************************************************** + * 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 */ + +#define RT3090A_DEFAULT_INTERNAL_LNA_GAIN 0x0A +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 + + +/* 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)) + + + +/* + ASIC register initialization sets +*/ +#ifdef SPECIFIC_BCN_BUF_SUPPORT +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}, +}; +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ + +RTMP_REG_PAIR MACRegTable[] = { +#if defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x200) + {BCN_OFFSET0, 0xf8f0e8e0}, /* 0x3800(e0), 0x3A00(e8), 0x3C00(f0), 0x3E00(f8), 512B for each beacon */ + {BCN_OFFSET1, 0x6f77d0c8}, /* 0x3200(c8), 0x3400(d0), 0x1DC0(77), 0x1BC0(6f), 512B for each beacon */ +#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 */ + + {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_CFG0, 0x40a06}, Gary,2006-08-23 */ +#ifndef RT6352 + {TX_SW_CFG0, 0x0}, /* Gary,2008-05-21 for CWC test */ + {TX_SW_CFG1, 0x80606}, /* Gary,2006-08-23 */ +#endif /* RT6352 */ + {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*/ + {MAX_LEN_CFG, MAX_AGGREGATION_SIZE | 0x00001000}, /* 0x3018, MAX frame length. Max PSDU = 16kbytes.*/ + {LED_CFG, 0x7f031e46}, /* Gary, 2006-08-23*/ + +#ifdef INF_AMAZON_SE + {PBF_MAX_PCNT, 0x1F3F6F6F}, /*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.*/ +#else + {PBF_MAX_PCNT, 0x1F3FBF9F}, /*0x1F3f7f9f}, Jan, 2006/04/20*/ +#endif /* INF_AMAZON_SE */ + /*{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}, + {PWR_PIN_CFG, 0x00000003}, /* patch for 2880-E*/ +}; + +#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 */ + +#ifdef SPECIFIC_BCN_BUF_SUPPORT +#define NUM_BCN_SPEC_MAC_REG_PARMS (sizeof(BcnSpecMACRegTable) / sizeof(RTMP_REG_PAIR)) +#endif /* SPECIFIC_BCN_BUF_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 */ + + +/* + 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( + IN PVOID handle, + OUT VOID **ppAdapter) +{ + PRTMP_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 + { + /* Allocate RTMP_ADAPTER memory block*/ +/* pBeaconBuf = kmalloc(MAX_BEACON_SIZE, MEM_ALLOC_FLAG);*/ + 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); + + Status = AdapterBlockAllocateMemory(handle, (PVOID *)&pAd, sizeof(RTMP_ADAPTER)); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("Failed to allocate memory - ADAPTER\n")); + break; + } + else + { +#ifdef WORKQUEUE_BH + POS_COOKIE cookie; +#endif /* WORKQUEUE_BH */ + + /* 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 + cookie = (POS_COOKIE)(pAd->OS_Cookie); + cookie->pAd_va = (UINT32)pAd; +#endif /* WORKQUEUE_BH */ + } + pAd->BeaconBuf = pBeaconBuf; + DBGPRINT(RT_DEBUG_OFF, ("\n\n=== pAd = %p, size = %d ===\n\n", pAd, (UINT32)sizeof(RTMP_ADAPTER))); + + if (RtmpOsStatsAlloc(&pAd->stats, &pAd->iw_stats) == FALSE) + { + Status = NDIS_STATUS_FAILURE; + break; + } + + /* Init spin locks*/ + NdisAllocateSpinLock(pAd, &pAd->MgmtRingLock); +#ifdef RTMP_MAC_PCI + NdisAllocateSpinLock(pAd, &pAd->RxRingLock); +#endif /* RTMP_MAC_PCI */ + + + 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 */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef UAPSD_SUPPORT +/* UAPSD_Init(pAd); move to rt28xx_init*/ +#endif /* UAPSD_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + /* assign function pointers*/ +#ifdef MAT_SUPPORT + /* init function pointers, used in OS_ABL */ +/* RTMP_MATOpsInit(pAd); move to rt28xx_init*/ +#endif /* MAT_SUPPORT */ + } while (FALSE); + + if ((Status != NDIS_STATUS_SUCCESS) && (pBeaconBuf)) + { + os_free_mem(NULL, pBeaconBuf); + pAd->BeaconBuf = NULL; + } + + if ((Status != NDIS_STATUS_SUCCESS) && (pAd != NULL)) + { + if (pAd->stats != NULL) + os_free_mem(NULL, pAd->stats); + + if (pAd->iw_stats != NULL) + os_free_mem(NULL, pAd->iw_stats); + } + + if (pAd != NULL) /* compile warning: avoid use NULL pointer when pAd == NULL */ + *ppAdapter = (VOID *)pAd; + + + /* + 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; +} + + +/* + ======================================================================== + + 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( + IN PRTMP_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; + + { + + /* 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 parameters from EEPROM + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID NICReadEEPROMParameters( + IN PRTMP_ADAPTER pAd, + IN PSTRING mac_addr) +{ + UINT32 data = 0; + USHORT i, value, value2; + EEPROM_TX_PWR_STRUC Power; + EEPROM_VERSION_STRUC Version; + EEPROM_ANTENNA_STRUC Antenna; + EEPROM_NIC_CONFIG2_STRUC NicConfig2; + USHORT Addr01,Addr23,Addr45 ; + 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 RTMP_EFUSE_SUPPORT +#endif /* RTMP_EFUSE_SUPPORT */ + } + + /* Init EEPROM Address Number, before access EEPROM; if 93c46, EEPROMAddressNum=6, else if 93c66, EEPROMAddressNum=8*/ + RTMP_IO_READ32(pAd, E2PROM_CSR, &data); + DBGPRINT(RT_DEBUG_TRACE, ("--> E2PROM_CSR = 0x%x\n", data)); + + if((data & 0x30) == 0) + pAd->EEPROMAddressNum = 6; /* 93C46*/ + else if((data & 0x30) == 0x10) + pAd->EEPROMAddressNum = 8; /* 93C66*/ + else + pAd->EEPROMAddressNum = 8; /* 93C86*/ + DBGPRINT(RT_DEBUG_TRACE, ("--> EEPROMAddressNum = %d\n", pAd->EEPROMAddressNum )); + + /* Read MAC setting from EEPROM and record as permanent MAC address */ + DBGPRINT(RT_DEBUG_TRACE, ("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_TRACE, ("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")); + } + else 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_TRACE, ("Use the MAC address what is assigned from Moudle Parameter. \n")); + } + else + { + COPY_MAC_ADDR(pAd->CurrentAddress, pAd->PermanentAddress); + DBGPRINT(RT_DEBUG_TRACE, ("Use the MAC address what is assigned from EEPROM. \n")); + } + + /* 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]; +#ifdef P2P_SUPPORT +#ifdef P2P_ODD_MAC_ADJUST + if ((pAd->CurrentAddress[5] & 0x01) == 0x01) + { + csr3.field.Byte5 = pAd->CurrentAddress[5] - 1; + /* p2p supporting need to use 2 mac addresses. And regarding the p2p odd mac adjust rule. + ** sta's mac should be E2P mac and p2p's mac should be "E2P mac -1" if original mac is odd value. + ** so in order to let MAC chip be able to recv pakcet from 2 those mac address, + ** MAC_ADDR should be original mac - 1. + ** + ** ex. E2P mac is 00:0c:43:00:00:03. + ** in the case, STA MAC will be 00:0c:43:00:03 and p2p MAC will be 00:0c:43:00:00:02 + ** then the MAC_ADDR of MAC should be 00:0c:43:00:00:02 + ** so need to set 2 MAC support for the case. + */ + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, (1<<16)); + } + else +#endif /* P2P_ODD_MAC_ADJUST */ +#endif /* P2P_SUPPORT */ + { + csr3.field.Byte5 = pAd->CurrentAddress[5]; + csr3.field.U2MeMask = 0xff; + } + RTMP_IO_WRITE32(pAd, MAC_ADDR_DW1, csr3.word); + DBGPRINT_RAW(RT_DEBUG_TRACE,("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 RT3883 + if (IS_RT3883(pAd)) + RTMPRT3883ReadChannelPwr(pAd); + else +#endif /* RT3883 */ +#ifdef RT2883 + if (IS_RT2883(pAd)) + RTMPRT2883ReadChannelPwr(pAd); + else +#endif /* RT2883 */ + 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)); + + if (Version.field.Version > VALID_EEPROM_VERSION) + { + DBGPRINT_ERR(("E2PROM: WRONG VERSION 0x%x, should be %d\n",Version.field.Version, VALID_EEPROM_VERSION)); + } + + /* 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; + + RT28xx_EEPROM_READ16(pAd, EEPROM_NIC2_OFFSET, value); + pAd->EEPROMDefaultValue[EEPROM_NIC_CFG2_OFFSET] = value; + + { + RT28xx_EEPROM_READ16(pAd, EEPROM_COUNTRY_REGION, value); /* Country Region*/ + pAd->EEPROMDefaultValue[EEPROM_COUNTRY_REG_OFFSET] = value; + } + + + for(i = 0; i < 8; i++) + { + 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]; + + + + /* must be put here, because RTMP_CHIP_ANTENNA_INFO_DEFAULT_RESET() will clear * + * EPROM 0x34~3 */ +#ifdef TXRX_SW_ANTDIV_SUPPORT + /* EEPROM 0x34[15:12] = 0xF is invalid, 0x2~0x3 is TX/RX SW AntDiv */ + if (((Antenna.word & 0xFF00) != 0xFF00) && (Antenna.word & 0x2000)) + { + pAd->chipCap.bTxRxSwAntDiv = TRUE; /* for GPIO switch */ + DBGPRINT(RT_DEBUG_OFF, ("\x1b[mAntenna word %X/%d, AntDiv %d\x1b[m\n", + Antenna.word, Antenna.field.BoardType, pAd->NicConfig2.field.AntDiversity)); + } +#endif /* TXRX_SW_ANTDIV_SUPPORT */ + + + if ((Antenna.word & 0xFF00) == 0xFF00) +/* 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; + } + } + + + /* EEPROM offset 0x36 - NIC Configuration 1 */ + NicConfig2.word = pAd->EEPROMDefaultValue[EEPROM_NIC_CFG2_OFFSET]; + +#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; + } + +#ifdef RT6352 + if (IS_RT6352(pAd)) + { +#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 */ + } +#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; + 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\n", Antenna.field.RxPath, Antenna.field.TxPath)); + + /* 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; + + /* check if the chip supports 5G band */ + if (PHY_MODE_IS_5G_BAND(pAd->CommonCfg.PhyMode)) + { + if (!RFIC_IS_5G_BAND(pAd)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("phy mode> Error! The chip does not support 5G band %d!\n", + 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->RFICType = RFIC_24GHZ; + } + pAd->RFICType = RFIC_24GHZ | RFIC_5GHZ; + } + else + pAd->RFICType = RFIC_24GHZ; + + RTMP_NET_DEV_NICKNAME_INIT(pAd); + + /* Read TSSI reference and TSSI boundary for temperature compensation. This is ugly. */ + /* 0. 11b/g*/ + { + { +#ifdef RT6352 + if (!IS_RT6352(pAd)) +#endif /* RT6352 */ + { + 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*/ + { + { + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TSSI_BOUND1, Power.word); + pAd->TssiMinusBoundaryA[4] = Power.field.Byte0; + pAd->TssiMinusBoundaryA[3] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TSSI_BOUND2, Power.word); + pAd->TssiMinusBoundaryA[2] = Power.field.Byte0; + pAd->TssiMinusBoundaryA[1] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TSSI_BOUND3, Power.word); + pAd->TssiRefA = Power.field.Byte0; + pAd->TssiPlusBoundaryA[1] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TSSI_BOUND4, Power.word); + pAd->TssiPlusBoundaryA[2] = Power.field.Byte0; + pAd->TssiPlusBoundaryA[3] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TSSI_BOUND5, Power.word); + pAd->TssiPlusBoundaryA[4] = Power.field.Byte0; + pAd->TxAgcStepA = Power.field.Byte1; + pAd->TxAgcCompensateA = 0; + pAd->TssiMinusBoundaryA[0] = pAd->TssiRefA; + pAd->TssiPlusBoundaryA[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[4], pAd->TssiMinusBoundaryA[3], pAd->TssiMinusBoundaryA[2], pAd->TssiMinusBoundaryA[1], + pAd->TssiRefA, + pAd->TssiPlusBoundaryA[1], pAd->TssiPlusBoundaryA[2], pAd->TssiPlusBoundaryA[3], pAd->TssiPlusBoundaryA[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%lx \n", pAd->RfFreqOffset)); + + /*CountryRegion byte offset (38h)*/ +#ifdef RT3883 + if (IS_RT3883(pAd)) + { + value = pAd->EEPROMDefaultValue[EEPROM_COUNTRY_REG_OFFSET] & 0x00FF; // 2.4G band + value2 = pAd->EEPROMDefaultValue[EEPROM_COUNTRY_REG_OFFSET] >> 8; // 5G band + } + else +#endif // RT3883 // + { + 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_32_BG_BAND) || (value == REGION_33_BG_BAND)) + { + pAd->CommonCfg.CountryRegion = ((UCHAR) value) | 0x80; + } + + if (value2 <= REGION_MAXIMUM_A_BAND) + { + pAd->CommonCfg.CountryRegionForABand = ((UCHAR) value2) | 0x80; + } + + + + /* Get RSSI Offset on EEPROM 0x9Ah & 0x9Ch.*/ + /* The valid value are (-10 ~ 10) */ + /* */ + { + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET, value); + pAd->BGRssiOffset0 = value & 0x00ff; + pAd->BGRssiOffset1 = (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->BGRssiOffset2 = value & 0x00ff; + pAd->ALNAGain1 = (value >> 8); + } + + { + RT28xx_EEPROM_READ16(pAd, EEPROM_LNA_OFFSET, value); + pAd->BLNAGain = value & 0x00ff; + pAd->ALNAGain0 = (value >> 8); + } + + /* Validate 11b/g RSSI_0 offset.*/ + if ((pAd->BGRssiOffset0 < -10) || (pAd->BGRssiOffset0 > 10)) + pAd->BGRssiOffset0 = 0; + + /* Validate 11b/g RSSI_1 offset.*/ + if ((pAd->BGRssiOffset1 < -10) || (pAd->BGRssiOffset1 > 10)) + pAd->BGRssiOffset1 = 0; + + /* Validate 11b/g RSSI_2 offset.*/ + if ((pAd->BGRssiOffset2 < -10) || (pAd->BGRssiOffset2 > 10)) + pAd->BGRssiOffset2 = 0; + + { + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_A_OFFSET, value); + pAd->ARssiOffset0 = value & 0x00ff; + pAd->ARssiOffset1 = (value >> 8); + } + + { + RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_A_OFFSET+2), value); + pAd->ARssiOffset2 = value & 0x00ff; + pAd->ALNAGain2 = (value >> 8); + } + +#if defined(RT2883) || defined(RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_LNA_OFFSET2, value); + pAd->ALNAGain1 = value & 0x00ff; + pAd->ALNAGain2 = (value >> 8); + } +#endif /* defined(RT2883) || defined(RT3883) */ + + if (((UCHAR)pAd->ALNAGain1 == 0xFF) || (pAd->ALNAGain1 == 0x00)) + pAd->ALNAGain1 = pAd->ALNAGain0; + if (((UCHAR)pAd->ALNAGain2 == 0xFF) || (pAd->ALNAGain2 == 0x00)) + pAd->ALNAGain2 = pAd->ALNAGain0; + + /* Validate 11a RSSI_0 offset.*/ + if ((pAd->ARssiOffset0 < -10) || (pAd->ARssiOffset0 > 10)) + pAd->ARssiOffset0 = 0; + + /* Validate 11a RSSI_1 offset.*/ + if ((pAd->ARssiOffset1 < -10) || (pAd->ARssiOffset1 > 10)) + pAd->ARssiOffset1 = 0; + + /*Validate 11a RSSI_2 offset.*/ + if ((pAd->ARssiOffset2 < -10) || (pAd->ARssiOffset2 > 10)) + pAd->ARssiOffset2 = 0; + + +#ifdef LED_CONTROL_SUPPORT + /* LED Setting */ + RTMPGetLEDSetting(pAd); +#endif /* LED_CONTROL_SUPPORT */ + +#ifdef RT3883 + if (IS_RT3883(pAd)) + RTMPRT3883ReadTxPwrPerRate(pAd); + else +#endif /* RT3883 */ +#ifdef RT2883 + if (IS_RT2883(pAd) && (Antenna.field.RfIcType == RFIC_2853)) + RTMPRT2883ReadTxPwrPerRate(pAd); + else +#endif /* RT2883 */ +#ifdef RT6352 + if (IS_RT6352(pAd)) + RT6352_RTMPReadTxPwrPerRate(pAd); + else +#endif /* RT6352 */ + RTMPReadTxPwrPerRate(pAd); + +#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&0x3F); + + 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)); + } +#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 + InitSkuRateDiffTable(pAd); +#endif /* SINGLE_SKU_V2 */ + + +#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. + */ + RT28xx_EEPROM_READ16(pAd, EEPROM_NIC2_OFFSET, value); + + 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( + IN PRTMP_ADAPTER pAd) +{ +#ifdef CONFIG_STA_SUPPORT + UINT32 data = 0; + UCHAR BBPR1 = 0; +#endif /* CONFIG_STA_SUPPORT */ + USHORT i; +#ifdef RALINK_ATE + USHORT value; +#endif /* RALINK_ATE */ + EEPROM_NIC_CONFIG2_STRUC NicConfig2; + UCHAR BBPR3 = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitAsicFromEEPROM\n")); + 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); + } + } + + NicConfig2.word = pAd->NicConfig2.word; + + /* finally set primary ant */ + AntCfgInit(pAd); + +#ifdef RTMP_RF_RW_SUPPORT + /*Init RT30xx RFRegisters after read RFIC type from EEPROM*/ + NICInitRFRegisters(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 + if (pAd->StaCfg.bRadio == FALSE) + { + RTMPSetLED(pAd, LED_RADIO_OFF); + } + else + { + RTMPSetLED(pAd, LED_RADIO_ON); + } +#endif /* LED_CONTROL_SUPPORT */ + +#ifdef RTMP_MAC_PCI + if (pAd->StaCfg.bRadio == TRUE) + { + AsicSendCommandToMcu(pAd, 0x30, PowerRadioOffCID, 0xff, 0x02, FALSE); + AsicCheckCommanOk(pAd, PowerRadioOffCID); + + /*AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02, FALSE);*/ + AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x00, FALSE); + /* 2-1. wait command ok.*/ + AsicCheckCommanOk(pAd, PowerWakeCID); + } +#endif /* RTMP_MAC_PCI */ + } +#ifdef PCIE_PS_SUPPORT +#endif /* PCIE_PS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + /* Turn off patching for cardbus controller*/ + if (NicConfig2.field.CardbusAcceleration == 1) + { +/* pAd->bTest1 = TRUE;*/ + } + + 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)))) + { + /* + 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 // + /* Since BBP has been progamed, to make sure BBP setting will be */ + /* upate inside of AsicAntennaSelect, so reset to UNKNOWN_BAND!!*/ + + pAd->CommonCfg.BandState = UNKNOWN_BAND; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); + BBPR3 &= (~0x18); + if(pAd->Antenna.field.RxPath == 3) + { + BBPR3 |= (0x10); + } + else if(pAd->Antenna.field.RxPath == 2) + { + BBPR3 |= (0x8); + } + else if(pAd->Antenna.field.RxPath == 1) + { + BBPR3 |= (0x0); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* Handle the difference when 1T*/ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1); + +#ifdef RT3883 + if (IS_RT3883(pAd)) + { + BBPR1 &= ~0x18; + if (pAd->Antenna.field.TxPath == 3) + BBPR1 |= 0x10; + else if (pAd->Antenna.field.TxPath == 2) + BBPR1 |= 0x08; + else if (pAd->Antenna.field.TxPath == 1) + BBPR1 |= 0x00; + } + else +#endif /* RT3883 */ + { + if(pAd->Antenna.field.TxPath == 1) + { + BBPR1 &= (~0x18); + } + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1); + + 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")); +} + + +NDIS_STATUS NICInitBBP( + IN RTMP_ADAPTER *pAd) +{ + INT Index = 0; + UCHAR R0 = 0xff; +#ifdef MICROWAVE_OVEN_SUPPORT + UINT8 BBPValue; +#endif /* MICROWAVE_OVEN_SUPPORT */ + + /* Read BBP register, make sure BBP is up and running before write new data*/ + Index = 0; + do + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R0, &R0); + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return NDIS_STATUS_FAILURE; + DBGPRINT(RT_DEBUG_TRACE, ("BBP version = %x\n", R0)); + } while ((++Index < 20) && ((R0 == 0xff) || (R0 == 0x00))); + + if ((R0 == 0xff) || (R0 == 0x00)) + return NDIS_STATUS_FAILURE; + + /* Initialize BBP register to default value*/ + for (Index = 0; Index < NUM_BBP_REG_PARMS; Index++) + { + 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 *pbbpRegTb = pAd->chipCap.pBBPRegTable; + + for (Index = 0; Index < pAd->chipCap.bbpRegTbSize; Index++) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, + pbbpRegTb[Index].Register, + pbbpRegTb[Index].Value); + DBGPRINT(RT_DEBUG_TRACE, ("BBP_R%d=0x%x\n", + pbbpRegTb[Index].Register, + pbbpRegTb[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 !defined(RT5350) + if (((pAd->MACVersion & 0xffff) != 0x0101) && + !(IS_RT30xx(pAd)|| IS_RT3572(pAd) || IS_RT5390(pAd) || IS_RT5392(pAd) || IS_RT3290(pAd))) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R84, 0x19); +#endif /* RT5350 */ + + + 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); + } + +#ifdef MICROWAVE_OVEN_SUPPORT + /* Backup BBP_R65 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R65, &BBPValue); + pAd->CommonCfg.MO_Cfg.Stored_BBP_R65 = BBPValue; + DBGPRINT(RT_DEBUG_TRACE("Stored_BBP_R65=%x @%s \n", pAd->CommonCfg.MO_Cfg.Stored_BBP_R65, __FUNCTION__)); +#endif /* MICROWAVE_OVEN_SUPPORT */ + + return NDIS_STATUS_SUCCESS; +} + + +/* + ======================================================================== + + Routine Description: + Initialize NIC hardware + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS NICInitializeAdapter( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bHardReset) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + WPDMA_GLO_CFG_STRUC GloCfg; +#ifdef RTMP_MAC_PCI + UINT32 Value; + DELAY_INT_CFG_STRUC IntCfg; +#endif /* RTMP_MAC_PCI */ +/* INT_MASK_CSR_STRUC IntMask;*/ + ULONG i =0; + ULONG j=0; + /*AC_TXOP_CSR0_STRUC csr0;*/ + + DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAdapter\n")); + + /* 3. Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits:*/ +retry: + i = 0; + do + { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) + break; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return NDIS_STATUS_FAILURE; + RTMPusecDelay(1000); + i++; + }while ( i<100); + DBGPRINT(RT_DEBUG_TRACE, ("<== DMA offset 0x208 = 0x%x\n", GloCfg.word)); + GloCfg.word &= 0xff0; + GloCfg.field.EnTXWriteBackDDONE =1; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); + + /* Record HW Beacon offset*/ + pAd->BeaconOffset[0] = pAd->chipCap.BcnBase[0]; + pAd->BeaconOffset[1] = pAd->chipCap.BcnBase[1]; + pAd->BeaconOffset[2] = pAd->chipCap.BcnBase[2]; + pAd->BeaconOffset[3] = pAd->chipCap.BcnBase[3]; + pAd->BeaconOffset[4] = pAd->chipCap.BcnBase[4]; + pAd->BeaconOffset[5] = pAd->chipCap.BcnBase[5]; + pAd->BeaconOffset[6] = pAd->chipCap.BcnBase[6]; + pAd->BeaconOffset[7] = pAd->chipCap.BcnBase[7]; + +#ifdef SPECIFIC_BCN_BUF_SUPPORT + if (pAd->chipCap.FlgIsSupSpecBcnBuf == TRUE) + { + pAd->BeaconOffset[8] = pAd->chipCap.BcnBase[8]; + pAd->BeaconOffset[9] = pAd->chipCap.BcnBase[9]; + pAd->BeaconOffset[10] = pAd->chipCap.BcnBase[10]; + pAd->BeaconOffset[11] = pAd->chipCap.BcnBase[11]; + pAd->BeaconOffset[12] = pAd->chipCap.BcnBase[12]; + pAd->BeaconOffset[13] = pAd->chipCap.BcnBase[13]; + pAd->BeaconOffset[14] = pAd->chipCap.BcnBase[14]; + pAd->BeaconOffset[15] = pAd->chipCap.BcnBase[15]; + } +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ + + + /* write all shared Ring's base address into ASIC*/ + + + /* asic simulation sequence put this ahead before loading firmware.*/ + /* pbf hardware reset*/ +#ifdef RTMP_MAC_PCI + RTMP_IO_WRITE32(pAd, WPDMA_RST_IDX, 0x1003f); /* 0x10000 for reset rx, 0x3f resets all 6 tx rings.*/ + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe1f); + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe00); +#endif /* RTMP_MAC_PCI */ + + /* 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 (j++ == 0) + { + NICLoadFirmware(pAd); + goto retry; + } + } + return NDIS_STATUS_FAILURE; + } + +#ifdef RTMP_MAC_PCI + /* Write AC_BK base address register*/ + Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_BK].Cell[0].AllocPa); + RTMP_IO_WRITE32(pAd, TX_BASE_PTR1, Value); + DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR1 : 0x%x\n", Value)); + + /* Write AC_BE base address register*/ + Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_BE].Cell[0].AllocPa); + RTMP_IO_WRITE32(pAd, TX_BASE_PTR0, Value); + DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR0 : 0x%x\n", Value)); + + /* Write AC_VI base address register*/ + Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_VI].Cell[0].AllocPa); + RTMP_IO_WRITE32(pAd, TX_BASE_PTR2, Value); + DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR2 : 0x%x\n", Value)); + + /* Write AC_VO base address register*/ + Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_VO].Cell[0].AllocPa); + RTMP_IO_WRITE32(pAd, TX_BASE_PTR3, Value); + DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR3 : 0x%x\n", Value)); + + /* Write HCCA base address register*/ + Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_HCCA].Cell[0].AllocPa); + RTMP_IO_WRITE32(pAd, TX_BASE_PTR4, Value); + DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR4 : 0x%x\n", Value)); + + /* Write MGMT_BASE_CSR register*/ + Value = RTMP_GetPhysicalAddressLow(pAd->MgmtRing.Cell[0].AllocPa); + RTMP_IO_WRITE32(pAd, TX_BASE_PTR5, Value); + DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR5 : 0x%x\n", Value)); + + /* Write RX_BASE_CSR register*/ + Value = RTMP_GetPhysicalAddressLow(pAd->RxRing.Cell[0].AllocPa); + RTMP_IO_WRITE32(pAd, RX_BASE_PTR, Value); + DBGPRINT(RT_DEBUG_TRACE, ("--> RX_BASE_PTR : 0x%x\n", Value)); + + /* Init RX Ring index pointer*/ + pAd->RxRing.RxSwReadIdx = 0; + pAd->RxRing.RxCpuIdx = RX_RING_SIZE-1; + RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); + + /* Init TX rings index pointer*/ + { + for (i=0; iTxRing[i].TxSwFreeIdx = 0; + pAd->TxRing[i].TxCpuIdx = 0; + RTMP_IO_WRITE32(pAd, (TX_CTX_IDX0 + i * 0x10) , pAd->TxRing[i].TxCpuIdx); + } + } + + /* init MGMT ring index pointer*/ + pAd->MgmtRing.TxSwFreeIdx = 0; + pAd->MgmtRing.TxCpuIdx = 0; + RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); + + + /* set each Ring's SIZE into ASIC. Descriptor Size is fixed by design.*/ + + + /* Write TX_RING_CSR0 register*/ + Value = TX_RING_SIZE; + RTMP_IO_WRITE32(pAd, TX_MAX_CNT0, Value); + RTMP_IO_WRITE32(pAd, TX_MAX_CNT1, Value); + RTMP_IO_WRITE32(pAd, TX_MAX_CNT2, Value); + RTMP_IO_WRITE32(pAd, TX_MAX_CNT3, Value); + RTMP_IO_WRITE32(pAd, TX_MAX_CNT4, Value); + Value = MGMT_RING_SIZE; + RTMP_IO_WRITE32(pAd, TX_MGMTMAX_CNT, Value); + + /* Write RX_RING_CSR register*/ + Value = RX_RING_SIZE; + RTMP_IO_WRITE32(pAd, RX_MAX_CNT, Value); +#endif /* RTMP_MAC_PCI */ + +#ifdef RTMP_MAC_PCI + /* 3. Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits:*/ + i = 0; + do + { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) + break; + + RTMPusecDelay(1000); + i++; + }while ( i < 100); + + 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 */ + + + /* reset action*/ + /* Load firmware*/ + /* Status = NICLoadFirmware(pAd);*/ + + 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( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bHardReset) +{ + ULONG Index = 0; + UINT32 MacCsr12 = 0; +#ifdef RTMP_PCI_SUPPORT + UINT32 Value; +#endif /* RTMP_PCI_SUPPORT */ + USHORT KeyIdx; + UCHAR BbpReg = 0; + + + DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAsic\n")); + +#ifdef RTMP_MAC_PCI + RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x3); /* To fix driver disable/enable hang issue when radio off*/ + RtmpOsMsDelay(100); + + if (bHardReset == TRUE) + { +#ifdef RT6352 + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1); + + 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); +#else + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x3); +#endif + } + else + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1); + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); + /* Initialize MAC register to default value*/ + for (Index = 0; Index < NUM_MAC_REG_PARMS; Index++) + { + RTMP_IO_WRITE32(pAd, + MACRegTable[Index].Register, + MACRegTable[Index].Value); + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + for (Index = 0; Index < NUM_AP_MAC_REG_PARMS; Index++) + { + RTMP_IO_WRITE32(pAd, + APMACRegTable[Index].Register, + APMACRegTable[Index].Value); + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + for (Index = 0; Index < NUM_STA_MAC_REG_PARMS; Index++) + { + RTMP_IO_WRITE32(pAd, + STAMACRegTable[Index].Register, + STAMACRegTable[Index].Value); + } + } +#endif /* CONFIG_STA_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + + { + UINT32 macValue; + + RTMP_IO_READ32(pAd, PBF_CFG, &macValue); + macValue = (macValue | 0x8); + RTMP_IO_WRITE32(pAd, PBF_CFG, macValue); + } + +#ifdef RTMP_PCI_SUPPORT + pAd->CommonCfg.bPCIeBus = FALSE; /* PCI bus*/ + + if ((pAd->infType == RTMP_DEV_INF_PCI || + pAd->infType == RTMP_DEV_INF_PCIE) + ) + { + /* PCI and PCIe have different value in US_CYC_CNT*/ + RTMP_IO_READ32(pAd, PCI_CFG, &Value); + if ((Value & 0x10000) == 0) + { + US_CYC_CNT_STRUC USCycCnt; + UINT32 Value; + + RTMP_IO_READ32(pAd, US_CYC_CNT, &Value); + USCycCnt.word = Value; + USCycCnt.field.UsCycCnt = 0x7D; + RTMP_IO_WRITE32(pAd, US_CYC_CNT, USCycCnt.word); + + pAd->CommonCfg.bPCIeBus = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("NICInitializeAsic::act as PCIe driver \n")); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("NICInitializeAsic::act as PCI driver \n")); + } + } + DBGPRINT(RT_DEBUG_TRACE, ("%s: pAd->CommonCfg.bPCIeBus = %d\n", + __FUNCTION__, pAd->CommonCfg.bPCIeBus)); +#endif /* RTMP_PCI_SUPPORT */ + + + +#ifdef SPECIFIC_BCN_BUF_SUPPORT + if (pAd->chipCap.FlgIsSupSpecBcnBuf == TRUE) + { + /* re-set beacon offset */ + for(Index=0; IndexchipOps.AsicMacInit != NULL) + pAd->chipOps.AsicMacInit(pAd); + + + /* Before program BBP, we need to wait BBP/RF get wake up.*/ + Index = 0; + do + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacCsr12); + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return NDIS_STATUS_FAILURE; + + if ((MacCsr12 & 0x03) == 0) /* if BB.RF is stable*/ + break; + + DBGPRINT(RT_DEBUG_TRACE, ("Check MAC_STATUS_CFG = Busy = %x\n", MacCsr12)); + RTMPusecDelay(1000); + } while (Index++ < 100); + + if (Index >= 100) + { + DBGPRINT(RT_DEBUG_ERROR, ("Check MAC_STATUS_CFG still Busy !!!!!\n")); + } + +#ifdef RTMP_MAC_PCI + /* The commands to firmware should be after these commands, these commands will init firmware*/ + /* PCI and USB are not the same because PCI driver needs to wait for PCI bus ready*/ + RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, 0); /* initialize BBP R/W access agent*/ + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, 0); + AsicSendCommandToMcu(pAd, 0x72, 0, 0, 0, FALSE); +#endif /* RTMP_MAC_PCI */ + + + /* Wait to be stable.*/ + RTMPusecDelay(1000); + pAd->LastMCUCmd = 0x72; + + NICInitBBP(pAd); + +#ifdef RTMP_MAC_PCI + /* TODO: check MACVersion, currently, rbus-based chip use this.*/ + if (pAd->MACVersion == 0x28720200) + { + /*UCHAR value;*/ + UINT32 value2; + + /*disable MLD by Bruce 20080704*/ + /*BBP_IO_READ8_BY_REG_ID(pAd, BBP_R105, &value);*/ + /*BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R105, value | 4);*/ + + /*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)) || +#ifdef RT6352 + (IS_RT6352(pAd)) || +#endif /* RT6352 */ + ((pAd->MACVersion >= RALINK_2880E_VERSION) && + (pAd->MACVersion < RALINK_3070_VERSION))) /* 3*3*/ + { + /* enlarge MAX_LEN_CFG*/ + UINT32 csr; + RTMP_IO_READ32(pAd, MAX_LEN_CFG, &csr); +#if defined(RT2883) || defined(RT3883) || defined(RT3593) + if (IS_RT2883(pAd) || IS_RT3883(pAd) || IS_RT3593(pAd)) + { + csr |= 0x3FFF; /* fix me*/ + } + else +#endif /* defined(RT2883) || defined(RT3883) || defined(RT3593) */ +#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 + /* Add radio off control*/ + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + 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) + { + for (KeyIdx = 0; KeyIdx < 4; KeyIdx++) + { + RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4*KeyIdx, 0); + } + + /* Clear all pairwise key table when initial*/ + for (KeyIdx = 0; KeyIdx < 256; KeyIdx++) + { + RTMP_IO_WRITE32(pAd, MAC_WCID_ATTRIBUTE_BASE + (KeyIdx * HW_WCID_ATTRI_SIZE), 1); + } + } + + /* assert HOST ready bit*/ +/* RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x0); 2004-09-14 asked by Mark*/ +/* RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x4);*/ + + /* 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++) + { + for (i = 0; i < HW_BEACON_OFFSET; i+=4) + RTMP_CHIP_UPDATE_BEACON(pAd, pAd->BeaconOffset[apidx] + i, 0x00, 4); + + } +#endif /* CONFIG_AP_SUPPORT */ + } + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + /* for rt2860E and after, init TXOP_CTRL_CFG with 0x583f. This is for extension channel overlapping IOT.*/ + if ((pAd->MACVersion&0xffff) != 0x0101) + RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x583f); + } +#endif /* CONFIG_STA_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( + IN PRTMP_ADAPTER pAd) +{ + /* 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)) + { + /* Must using 40MHz.*/ + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + } + else + { + /* Must using 20MHz.*/ + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.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 */ +} +#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 + + ======================================================================== +*/ +static VOID ClearTxRingClientAck( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry) + +{ + INT index; + USHORT TxIdx; + PRTMP_TX_RING pTxRing; + PTXD_STRUC pTxD; + PTXWI_STRUC pTxWI; +#ifdef RT_BIG_ENDIAN + PTXD_STRUC pDestTxD; + TXD_STRUC TxD; + PTXWI_STRUC pDestTxWI; + TXWI_STRUC TxWI; +#endif /* RT_BIG_ENDIAN */ + UINT8 TXWISize; + + if (!pAd || !pEntry) + return; + + TXWISize = pAd->chipCap.TXWISize; + + 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 = (PTXWI_STRUC) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + NdisMoveMemory((PUCHAR)&TxWI, (PUCHAR)pDestTxWI, TXWISize); + pTxWI = &TxWI; + RTMPWIEndianChange(pAd, (PUCHAR)pTxWI, TYPE_TXWI); +#else + pTxWI = (PTXWI_STRUC) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; +#endif /* RT_BIG_ENDIAN */ + if (pTxWI->WirelessCliID == pEntry->Aid) + pTxWI->ACK = FALSE; +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, (PUCHAR)pTxWI, TYPE_TXWI); + NdisMoveMemory((PUCHAR)pDestTxWI, (PUCHAR)pTxWI, TXWISize); +#endif /* RT_BIG_ENDIAN */ + } + } + } +} +#endif /* RTMP_MAC_PCI */ +#endif /* CONFIG_AP_SUPPORT */ + +VOID NICUpdateFifoStaCounters( + IN PRTMP_ADAPTER pAd) +{ + TX_STA_FIFO_STRUC StaFifo; + MAC_TABLE_ENTRY *pEntry = NULL; + UINT32 i = 0; + UCHAR pid = 0, wcid = 0; + INT32 reTry; + UCHAR succMCS; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + +#ifdef RALINK_ATE + /* Nothing to do in ATE mode */ + if (ATE_ON(pAd)) + return; +#endif /* RALINK_ATE */ + + + + +#ifdef MAC_REPEATER_SUPPORT + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + do + { + 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 >= MaxWcidNum)) + { + i++; + continue; + } + + /* PID store Tx MCS Rate */ + pid = (UCHAR)StaFifo.field.PidType; + + pEntry = &pAd->MacTab.Content[wcid]; + + 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++; + + if (pEntry->FIFOCount >= 1) + { + DBGPRINT(RT_DEBUG_TRACE, ("#")); +#ifdef DOT11_N_SUPPORT + //pEntry->NoBADataCountDown = 64; +#endif /* DOT11_N_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef DOT11Z_TDLS_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if(IS_ENTRY_TDLS(pEntry)) + { + pEntry->TdlsTxFailCount++; + if (pEntry->TdlsTxFailCount >= 15) + { + DBGPRINT(RT_DEBUG_OFF, ("TDLS: TxFail >= 15 LinkTearDown !!!\n")); + TDLS_TearDownPeerLink(pAd, pEntry->Addr, FALSE); + } + } + } +#endif /* DOT11Z_TDLS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + /* Update the continuous transmission counter.*/ + pEntry->ContinueTxFailCnt++; + + if(pEntry->PsMode == PWR_ACTIVE) + { + +#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", + pEntry->Addr[0],pEntry->Addr[1],pEntry->Addr[2],pEntry->Addr[3], + pEntry->Addr[4],pEntry->Addr[5],pEntry->ContinueTxFailCnt )); + + pEntry->LockEntryTx = TRUE; + } +#endif /* WDS_SUPPORT */ + } + + /*pEntry->FIFOCount = 0;*/ + } + /*pEntry->bSendBAR = TRUE;*/ +#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 +#ifdef DOT11Z_TDLS_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if(IS_ENTRY_TDLS(pEntry)) + pEntry->TdlsTxFailCount = 0; + } +#endif /* DOT11Z_TDLS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + } + + 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 + { + pEntry->TXMCSAutoFallBack[pid][succMCS]++; + } + } + else + { + 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; + } + + i++; + /* ASIC store 16 stack*/ + } while ( i < (TX_RING_SIZE<<1) ); + +} + + +#ifdef FIFO_EXT_SUPPORT +BOOLEAN NicGetMacFifoTxCnt( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry) +{ + if (pEntry->Aid >= 1 && pEntry->Aid <= 8) + { + WCID_TX_CNT_STRUC wcidTxCnt; + UINT32 regAddr; + + regAddr = WCID_TX_CNT_0 + (pEntry->Aid - 1) * 4; + RTMP_IO_READ32(pAd, regAddr, &wcidTxCnt.word); + + pEntry->fifoTxSucCnt += wcidTxCnt.field.succCnt; + pEntry->fifoTxRtyCnt += wcidTxCnt.field.reTryCnt; + } + + return TRUE; +} + + +VOID AsicFifoExtSet(IN RTMP_ADAPTER *pAd) +{ + if (pAd->chipCap.FlgHwFifoExtCap) + { + RTMP_IO_WRITE32(pAd, WCID_MAPPING_0, 0x04030201); + RTMP_IO_WRITE32(pAd, WCID_MAPPING_1, 0x08070605); + } +} + + +VOID AsicFifoExtEntryClean( + IN RTMP_ADAPTER * pAd, + IN MAC_TABLE_ENTRY *pEntry) +{ + WCID_TX_CNT_STRUC wcidTxCnt; + UINT32 regAddr; + + if (pAd->chipCap.FlgHwFifoExtCap) + { + /* We clean the fifo info when MCS is 0 and Aid is from 1~8 */ + if (pEntry->Aid >=1 && pEntry->Aid <= 8) + { + regAddr = WCID_TX_CNT_0 + (pEntry->Aid - 1) * 4; + RTMP_IO_READ32(pAd, regAddr, &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: + 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( + IN PRTMP_ADAPTER pAd) +{ +#ifdef RALINK_ATE + PATE_INFO pATEInfo = &(pAd->ate); +#endif /* RALINK_ATE */ + 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_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; + +#ifdef RALINK_ATE + if (pATEInfo->bQAEnabled == FALSE) + { +#endif /* RALINK_ATE */ + RTMP_IO_READ32(pAd, RX_STA_CNT0, &RxStaCnt0.word); + RTMP_IO_READ32(pAd, RX_STA_CNT2, &RxStaCnt2.word); +#ifdef RALINK_ATE + } +#endif /* RALINK_ATE */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef CARRIER_DETECTION_SUPPORT + if ((pAd->CommonCfg.CarrierDetect.Enable == FALSE) || (pAd->OpMode == OPMODE_STA)) +#endif /* CARRIER_DETECTION_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + { +#ifdef RALINK_ATE + if (pATEInfo->bQAEnabled == FALSE) + { +#endif /* RALINK_ATE */ + RTMP_IO_READ32(pAd, RX_STA_CNT1, &RxStaCnt1.word); + /* Update RX PLCP error counter*/ + pAd->PrivateInfo.PhyRxErrCnt += RxStaCnt1.field.PlcpErr; + /* Update False CCA counter*/ + pAd->RalinkCounters.OneSecFalseCCACnt += RxStaCnt1.field.FalseCca; + pAd->RalinkCounters.OneSecFalseCCACnt1 = RxStaCnt1.field.FalseCca; + pAd->RalinkCounters.FalseCCACnt += RxStaCnt1.field.FalseCca; +#ifdef RALINK_ATE + } +#endif /* RALINK_ATE */ + } + +#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); + } + + + /*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; + + pDiag = &pAd->DiagStruct; + ArrayCurIdx = pDiag->ArrayCurIdx; + + if (pDiag->inited == 0) + { + NdisZeroMemory(pDiag, sizeof(struct _RtmpDiagStrcut_)); + pDiag->ArrayStartIdx = pDiag->ArrayCurIdx = 0; + pDiag->inited = 1; + } + else + { + /* Tx*/ + pDiag->TxFailCnt[ArrayCurIdx] = TxStaCnt0.field.TxFailCount; + pDiag->TxAggCnt[ArrayCurIdx] = TxAggCnt.field.AggTxCount; + pDiag->TxNonAggCnt[ArrayCurIdx] = TxAggCnt.field.NonAggTxCount; + + pDiag->TxAMPDUCnt[ArrayCurIdx][0] = TxAggCnt0.field.AggSize1Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][1] = TxAggCnt0.field.AggSize2Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][2] = TxAggCnt1.field.AggSize3Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][3] = TxAggCnt1.field.AggSize4Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][4] = TxAggCnt2.field.AggSize5Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][5] = TxAggCnt2.field.AggSize6Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][6] = TxAggCnt3.field.AggSize7Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][7] = TxAggCnt3.field.AggSize8Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][8] = TxAggCnt4.field.AggSize9Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][9] = TxAggCnt4.field.AggSize10Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][10] = TxAggCnt5.field.AggSize11Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][11] = TxAggCnt5.field.AggSize12Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][12] = TxAggCnt6.field.AggSize13Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][13] = TxAggCnt6.field.AggSize14Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][14] = TxAggCnt7.field.AggSize15Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][15] = TxAggCnt7.field.AggSize16Count; + + pDiag->RxCrcErrCnt[ArrayCurIdx] = RxStaCnt0.field.CrcErr; + + INC_RING_INDEX(pDiag->ArrayCurIdx, DIAGNOSE_TIME); + ArrayCurIdx = pDiag->ArrayCurIdx; + for (i =0; i < 9; i++) + { + pDiag->TxDescCnt[ArrayCurIdx][i]= 0; + pDiag->TxSWQueCnt[ArrayCurIdx][i] =0; + pDiag->TxMcsCnt[ArrayCurIdx][i] = 0; + pDiag->RxMcsCnt[ArrayCurIdx][i] = 0; + } + pDiag->TxDataCnt[ArrayCurIdx] = 0; + pDiag->TxFailCnt[ArrayCurIdx] = 0; + pDiag->RxDataCnt[ArrayCurIdx] = 0; + pDiag->RxCrcErrCnt[ArrayCurIdx] = 0; +/* for (i = 9; i < 16; i++)*/ + for (i = 9; i < 24; i++) /* 3*3*/ + { + pDiag->TxDescCnt[ArrayCurIdx][i] = 0; + pDiag->TxMcsCnt[ArrayCurIdx][i] = 0; + pDiag->RxMcsCnt[ArrayCurIdx][i] = 0; +} + + if (pDiag->ArrayCurIdx == pDiag->ArrayStartIdx) + INC_RING_INDEX(pDiag->ArrayStartIdx, DIAGNOSE_TIME); + } + } +#endif /* DBG_DIAGNOSE */ + + +} + +NDIS_STATUS NICLoadFirmware( + IN PRTMP_ADAPTER pAd) +{ + /* + 1. For PCI: + (1) Write SYS_CTRL bit16(HST_PM_SEL) to 1 + (2) Write 8051 firmware to RAM. + (3) Write SYS_CTRL to 0. + (4) Write SYS_CTRL bit0(MCU_RESET) to 1 to do MCU HW reset. + + 2. For USB: + (1)Get current firmware operation mode via VendorRequest(0x1, 0x11) command. + (2) Write SYS_CTRL bit7(MCU_READY) to 0. + (3) Write SYS_CTRL bit0(MCU_RESET) to 1 to do MCU reset to run 8051 on ROM. + (4) Check MCU ready via SYS_CTRL bit7(MCU_READY). + (5) Write 8051 firmware to RAM. + (6) Write MAC 0x7014 to 0xffffffff. + (7) Write MAC 0x701c to 0xffffffff. + (8) Change 8051 from ROM to RAM site via VendorRequest(0x01, 0x8) command. + */ + + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + if (pAd->chipOps.loadFirmware) + status = pAd->chipOps.loadFirmware(pAd); + + return status; +} + + +/* + ======================================================================== + + Routine Description: + erase 8051 firmware image in MAC ASIC + + Arguments: + Adapter Pointer to our adapter + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +VOID NICEraseFirmware( + IN PRTMP_ADAPTER pAd) +{ + if (pAd->chipOps.eraseFirmware) + pAd->chipOps.eraseFirmware(pAd); + +}/* End of NICEraseFirmware */ + + +/* + ======================================================================== + + Routine Description: + Load Tx rate switching parameters + + Arguments: + Adapter Pointer to our adapter + + Return Value: + NDIS_STATUS_SUCCESS firmware image load ok + NDIS_STATUS_FAILURE image not found + + IRQL = PASSIVE_LEVEL + + Rate Table Format: + 1. (B0: Valid Item number) (B1:Initial item from zero) + 2. Item Number(Dec) Mode(Hex) Current MCS(Dec) TrainUp(Dec) TrainDown(Dec) + + ======================================================================== +*/ +NDIS_STATUS NICLoadRateSwitchingParams( + IN PRTMP_ADAPTER pAd) +{ + return NDIS_STATUS_SUCCESS; +} + + +/* + ======================================================================== + + 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( + IN PVOID pSrc1, + IN PVOID pSrc2, + IN 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( + IN PVOID pSrc, + IN 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( + OUT PVOID pDest, + IN PVOID pSrc, + IN 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( + IN RTMP_ADAPTER *pAd) +{ +#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 */ + + pAd->CommonCfg.bEnTemperatureTrack = FALSE; + +#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( + IN PRTMP_ADAPTER pAd) +{ + UINT i; +#ifdef CONFIG_AP_SUPPORT + UINT j; +#endif /* CONFIG_AP_SUPPORT */ +/* EDCA_PARM DefaultEdcaParm;*/ + 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 */ +#endif /* RTMP_MAC_PCI */ + + pAd->bAutoTxAgcA = FALSE; /* Default is OFF*/ + pAd->bAutoTxAgcG = FALSE; /* Default is OFF*/ + +#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 */ + + 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 = 0xff; + pAd->CommonCfg.BandState = UNKNOWN_BAND; + +#ifdef RTMP_RBUS_SUPPORT + if (pAd->infType == RTMP_DEV_INF_RBUS) + { +#ifdef RT2880 + RTMP_SYS_IO_READ32(0xa030000c, &pAd->CommonCfg.CID); +#else + RTMP_SYS_IO_READ32(0xb000000c, &pAd->CommonCfg.CID); + RTMP_SYS_IO_READ32(0xb0000000, &pAd->CommonCfg.CN); +#endif /* RT2880 */ + DBGPRINT(RT_DEBUG_TRACE, ("CN: %lx\tCID = %lx\n", + pAd->CommonCfg.CN, pAd->CommonCfg.CID)); + } +#endif /* RTMP_RBUS_SUPPORT */ + +#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 */ + + pAd->Dot11_H.ChMovingTime = 65; + +#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_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 */ + + NdisZeroMemory(&pAd->CommonCfg.AddHTInfo, sizeof(pAd->CommonCfg.AddHTInfo)); + pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE; + 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.HTPhyMode.field.BW = BW_20;*/ + /*pAd->CommonCfg.HTPhyMode.field.MCS = MCS_AUTO;*/ + /*pAd->CommonCfg.HTPhyMode.field.ShortGI = GI_800;*/ + /*pAd->CommonCfg.HTPhyMode.field.STBC = STBC_NONE;*/ + 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 STREAM_MODE_SUPPORT + if (pAd->chipCap.FlgHwStreamMode) + { + pAd->CommonCfg.StreamMode = 3; + pAd->CommonCfg.StreamModeMCS = 0x0B0B; + } +#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; + pAd->CommonCfg.FixedRate = -1; +#endif // NEW_RATE_ADAPT_SUPPORT // + +#if defined(RT2883) || defined(RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + { +#ifdef PRE_ANT_SWITCH + pAd->CommonCfg.PreAntSwitch = 1; + pAd->CommonCfg.PreAntSwitchRSSI = -76; + pAd->CommonCfg.PreAntSwitchTimeout = 0; +#endif /* PRE_ANT_SWITCH */ + pAd->CommonCfg.PhyRateLimit = 0; + pAd->CommonCfg.FixedRate = -1; // Disable + } +#endif // defined (RT2883) || defined (RT3883) // + + +#ifdef CFO_TRACK +#ifdef RT3883 + if (IS_RT3883(pAd)) + pAd->CommonCfg.CFOTrack = 8; // No tracking +#endif /* RT3883 */ +#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; + + /* Tx Sw queue length setting */ + pAd->TxSwQMaxLen = MAX_PACKETS_IN_QUEUE; + + 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.DefaultKeyId = 0; + + /* 802.1x port control*/ + pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pAd->StaCfg.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;*/ +#ifdef DOT11Z_TDLS_SUPPORT + pAd->StaCfg.DefaultListenCount = 1; +#endif /* DOT11Z_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.bAutoTxRateSwitch = TRUE; + pAd->StaCfg.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 = PHY_11BG_MIXED; /* 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*/ + pAd->StaCfg.bAutoReconnect = TRUE; + + /* 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.IEEE8021X = FALSE; + pAd->StaCfg.IEEE8021x_required_keys = FALSE; + pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE; + pAd->StaCfg.bRSN_IE_FromWpaSupplicant = FALSE; +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE; +#ifdef PROFILE_STORE + pAd->bWriteDat = TRUE; +#endif /* PROFILE_STORE */ +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + pAd->StaCfg.bLostAp = FALSE; + pAd->StaCfg.pWpsProbeReqIe = NULL; + pAd->StaCfg.WpsProbeReqIeLen = 0; + pAd->StaCfg.pWpaAssocIe = NULL; + pAd->StaCfg.WpaAssocIeLen = 0; + pAd->StaCfg.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 */ +#ifdef P2P_SUPPORT + pWscControl->WscConfigMethods |= 0x0100; +#endif /* P2P_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); + + + 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; + + + pAd->ApCfg.ScanChannelCnt = 0; + pAd->ApCfg.bImprovedScan = TRUE; + /* */ + /* part III. AP configurations*/ + +#ifdef CONFIG_AP_SUPPORT +#ifndef P2P_APCLI_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_APCLI_SUPPORT */ + { + /* Set MBSS Default Configurations*/ + pAd->ApCfg.BssidNum = MAX_MBSSID_NUM(pAd); + for(j = BSS0; j < pAd->ApCfg.BssidNum; j++) + { + pAd->ApCfg.MBSSID[j].AuthMode = Ndis802_11AuthModeOpen; + pAd->ApCfg.MBSSID[j].WepStatus = Ndis802_11EncryptionDisabled; + pAd->ApCfg.MBSSID[j].GroupKeyWepStatus = Ndis802_11EncryptionDisabled; + pAd->ApCfg.MBSSID[j].DefaultKeyId = 0; + pAd->ApCfg.MBSSID[j].WpaMixPairCipher = MIX_CIPHER_NOTUSE; + pAd->ApCfg.MBSSID[j].RekeyCountDown = 0; /* it's used for WPA rekey */ + +#ifdef SPECIFIC_TX_POWER_SUPPORT + pAd->ApCfg.MBSSID[j].TxPwrAdj = -1; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + +#ifdef DOT1X_SUPPORT + pAd->ApCfg.MBSSID[j].IEEE8021X = FALSE; + pAd->ApCfg.MBSSID[j].PreAuth = FALSE; + + /* PMK cache setting*/ + pAd->ApCfg.MBSSID[j].PMKCachePeriod = (10 * 60 * OS_HZ); /* unit : tick(default: 10 minute)*/ + NdisZeroMemory(&pAd->ApCfg.MBSSID[j].PMKIDCache, sizeof(NDIS_AP_802_11_PMKID)); + + /* dot1x related per BSS */ + pAd->ApCfg.MBSSID[j].radius_srv_num = 0; + pAd->ApCfg.MBSSID[j].NasIdLen = 0; +#endif /* DOT1X_SUPPORT */ + + /* VLAN related */ + pAd->ApCfg.MBSSID[j].VLAN_VID = 0; + + /* Default MCS as AUTO*/ + pAd->ApCfg.MBSSID[j].bAutoTxRateSwitch = TRUE; + pAd->ApCfg.MBSSID[j].DesiredTransmitSetting.field.MCS = MCS_AUTO; + + /* Default is zero. It means no limit.*/ + pAd->ApCfg.MBSSID[j].MaxStaNum = 0; + pAd->ApCfg.MBSSID[j].StaCount = 0; + +#ifdef WSC_AP_SUPPORT + pAd->ApCfg.MBSSID[j].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 = &pAd->ApCfg.MBSSID[j].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 P2P_SUPPORT + pWscControl->WscConfigMethods |= 0x0108; +#endif /* P2P_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; +#ifdef P2P_SUPPORT + /* + Set defaule value of WscConfMode to be (WSC_REGISTRAR | WSC_ENROLLEE) for WiFi P2P. + */ + pWscControl->WscConfMode = (WSC_REGISTRAR | WSC_ENROLLEE); +#else /* P2P_SUPPORT */ + pWscControl->WscConfMode = 0; +#endif /* !P2P_SUPPORT */ + 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; +#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; + pWscControl->SetupLockTime = WSC_WPS_AP_SETUP_LOCK_TIME; + pWscControl->MaxPinAttack = WSC_WPS_AP_MAX_PIN_ATTACK; +#endif /* WSC_V2_SUPPORT */ + } +#endif /* WSC_AP_SUPPORT */ + +#ifdef EASY_CONFIG_SETUP + AutoProvisionGenWpsPTK(pAd, j); + pAd->ApCfg.MBSSID[j].EasyConfigInfo.RssiThreshold = -50; + pAd->ApCfg.MBSSID[j].EasyConfigInfo.bEnable = TRUE; + NdisZeroMemory(pAd->ApCfg.MBSSID[j].EasyConfigInfo.WpsPinCode, MAC_ADDR_LEN); +#endif /* EASY_CONFIG_SETUP */ +#ifdef WAC_SUPPORT + pAd->ApCfg.MBSSID[j].EasyConfigInfo.bEnableWAC = TRUE; + initList(&pAd->ApCfg.MBSSID[j].EasyConfigInfo.WAC_PeerList); + NdisAllocateSpinLock(pAd, &pAd->ApCfg.MBSSID[j].EasyConfigInfo.WAC_PeerListSemLock); +#ifdef WAC_QOS_PRIORITY + initList(&pAd->ApCfg.MBSSID[j].EasyConfigInfo.WAC_ForcePriorityList); + NdisAllocateSpinLock(pAd, &pAd->ApCfg.MBSSID[j].EasyConfigInfo.WAC_ForcePriorityListSemLock); +#endif /* WAC_QOS_PRIORITY */ + pAd->ApCfg.MBSSID[j].EasyConfigInfo.pVendorInfoForBeacon = NULL; + pAd->ApCfg.MBSSID[j].EasyConfigInfo.pVendorInfoForProbeRsp = NULL; +#endif /* WAC_SUPPORT */ + + for(i = 0; i < WLAN_MAX_NUM_OF_TIM; i++) + pAd->ApCfg.MBSSID[j].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 +#endif /* CONFIG_AP_SUPPORT */ +#endif /* WSC_INCLUDED */ + +#ifdef APCLI_SUPPORT + pAd->ApCfg.FlgApCliIsUapsdInfoUpdated = FALSE; +#ifdef APCLI_CERT_SUPPORT + pAd->bApCliCertTest = FALSE; +#endif /* APCLI_CERT_SUPPORT */ + for(j = 0; j < MAX_APCLI_NUM; j++) + { + pAd->ApCfg.ApCliTab[j].AuthMode = Ndis802_11AuthModeOpen; + pAd->ApCfg.ApCliTab[j].WepStatus = Ndis802_11WEPDisabled; + pAd->ApCfg.ApCliTab[j].bAutoTxRateSwitch = TRUE; + pAd->ApCfg.ApCliTab[j].DesiredTransmitSetting.field.MCS = MCS_AUTO; + pAd->ApCfg.ApCliTab[j].UapsdInfo.bAPSDCapable = FALSE; + +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + pAd->ApCfg.ApCliTab[j].IEEE8021X=FALSE; + pAd->ApCfg.ApCliTab[j].IEEE8021x_required_keys=FALSE; + pAd->ApCfg.ApCliTab[j].bRSN_IE_FromWpaSupplicant=FALSE; + pAd->ApCfg.ApCliTab[j].bLostAp=FALSE; + pAd->ApCfg.ApCliTab[j].bScanReqIsFromWebUI=FALSE; + pAd->ApCfg.ApCliTab[j].bConfigChanged=FALSE; + pAd->ApCfg.ApCliTab[j].DesireSharedKeyId=0; + pAd->ApCfg.ApCliTab[j].WpaSupplicantUP=WPA_SUPPLICANT_DISABLE; + pAd->ApCfg.ApCliTab[j].WpaSupplicantScanCount=0; + pAd->ApCfg.ApCliTab[j].pWpsProbeReqIe=NULL; + pAd->ApCfg.ApCliTab[j].WpsProbeReqIeLen=0; + pAd->ApCfg.ApCliTab[j].pWpaAssocIe=NULL; + pAd->ApCfg.ApCliTab[j].WpaAssocIeLen=0; + pAd->ApCfg.ApCliTab[j].SavedPMKNum=0; + RTMPZeroMemory(pAd->ApCfg.ApCliTab[j].SavedPMK, (PMKID_NO * sizeof(BSSID_INFO))); +#endif/*APCLI_WPA_SUPPLICANT_SUPPORT*/ + pAd->ApCfg.ApCliTab[j].bBlockAssoc=FALSE; + pAd->ApCfg.ApCliTab[j].MicErrCnt=0; + + } +#endif /* APCLI_SUPPORT */ + pAd->ApCfg.EntryClientCount = 0; + } +#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 */ + + + /* 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; + + pAd->Bbp94 = BBPR94_DEFAULT; + pAd->BbpForCCK = FALSE; + + /* Default is FALSE for test bit 1*/ + /*pAd->bTest1 = 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);*/ + +#ifdef MESH_SUPPORT + pAd->MeshTab.AuthMode = Ndis802_11AuthModeOpen; + pAd->MeshTab.WepStatus = Ndis802_11EncryptionDisabled; + pAd->MeshTab.DefaultKeyId = 0; +#endif /* MESH_SUPPORT */ + + pAd->CommonCfg.bWiFiTest = FALSE; +#ifdef RTMP_MAC_PCI + pAd->bPCIclkOff = FALSE; +#endif /* RTMP_MAC_PCI */ + +#ifdef CONFIG_AP_SUPPORT + pAd->ApCfg.EntryLifeCheck = MAC_ENTRY_LIFE_CHECK_CNT; + +#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++) + { + PBSS_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 P2P_SUPPORT + P2pCfgInit(pAd); +#endif /* P2P_SUPPORT */ + +#ifdef RT3883 + if (IS_RT3883(pAd)) + pAd->FlgCWC = 0; +#endif /* RT3883 */ + +#ifdef WOW_SUPPORT +#endif /* WOW_SUPPORT */ + + /* 802.11H and DFS related params*/ + pAd->Dot11_H.CSCount = 0; + pAd->Dot11_H.CSPeriod = 10; + pAd->Dot11_H.RDMode = RD_NORMAL_MODE; + pAd->Dot11_H.bDFSIndoor = 1; + + + pAd->bEnableMacWD = TRUE; + pAd->CommonCfg.bRcvBSSWidthTriggerEvents = FALSE; + + +#ifdef MCS_LUT_SUPPORT + pAd->bUseHwTxLURate = TRUE; +#endif /* MCS_LUT_SUPPORT */ + +#if defined(MICROWAVE_OVEN_SUPPORT) || defined(DYNAMIC_VGA_SUPPORT) + pAd->CommonCfg.MO_Cfg.bEnable = FALSE; +#ifdef DYNAMIC_VGA_SUPPORT + pAd->CommonCfg.MO_Cfg.bDyncVGAEnable = TRUE; +#endif /* DYNAMIC_VGA_SUPPORT */ + pAd->CommonCfg.MO_Cfg.nFalseCCATh = 600; + pAd->CommonCfg.MO_Cfg.nLowFalseCCATh = 100; +#endif /* defined(MICROWAVE_OVEN_SUPPORT) || defined(DYNAMIC_VGA_SUPPORT) */ + +#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 RT6352 + 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; + pAd->bExtPA = FALSE; + pAd->bDoReCalibration = FALSE; +#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 */ + + pAd->CommonCfg.bEnTemperatureTrack = FALSE; + + 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*/ +/* destlen - size of dest*/ + +/* 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 destlen) +{ + PSTRING srcptr; + PUCHAR destTemp; + + srcptr = src; + destTemp = (PUCHAR) dest; + + while(destlen--) + { + *destTemp = BtoH(*srcptr++) << 4; /* Put 1st ascii byte in upper nibble.*/ + *destTemp += BtoH(*srcptr++); /* Add 2nd ascii byte to above.*/ + destTemp++; + } +} + + +/*+++not use now, need to remove after confirm*/ +/*---not use now, need to remove after confirm*/ + + +/* +======================================================================== +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( + IN PRTMP_ADAPTER pAd, + IN 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); + DBGPRINT(RT_DEBUG_ERROR, ("%s: add timer obj %lx!\n", __FUNCTION__, (ULONG)pRsc)); + } +} + + +/* +======================================================================== +Routine Description: + Cancel all timers in the timer list. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RTMP_TimerListRelease( + IN PRTMP_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_TRACE, ("%s: Cancel timer obj %lx!\n", __FUNCTION__, (ULONG)(pObj->pRscObj))); + RTMPReleaseTimer(pObj->pRscObj, &Cancel); + pObjOld = pObj; + pObj = pObj->pNext; + 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 PRTMP_ADAPTER pAd, + IN PRALINK_TIMER_STRUCT pTimer, + IN PVOID pTimerFunc, + IN PVOID 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_TRACE,("%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( + IN PRALINK_TIMER_STRUCT pTimer, + IN 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_INFO,("%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( + IN PRALINK_TIMER_STRUCT pTimer, + IN 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_TRACE,("%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( + IN PRALINK_TIMER_STRUCT pTimer, + OUT 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 */ + + DBGPRINT(RT_DEBUG_INFO,("%s: %lx\n",__FUNCTION__, (ULONG)pTimer)); + } + else + { + //DBGPRINT(RT_DEBUG_INFO,("RTMPCancelTimer failed, Timer hasn't been initialize!\n")); + DBGPRINT_ERR(("RTMPCancelTimer failed, Timer hasn't been initialize!\n")); + } + + RTMP_SEM_UNLOCK(&TimerSemLock); +} + + +VOID RTMPReleaseTimer( + IN PRALINK_TIMER_STRUCT pTimer, + OUT 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; + + DBGPRINT(RT_DEBUG_INFO,("%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( + IN PRTMP_ADAPTER pAd) +{ +/* WPDMA_GLO_CFG_STRUC GloCfg;*/ +/* ULONG i = 0;*/ + UINT32 rx_filter_flag; + + DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPEnableRxTx\n")); + + /* Enable Rx DMA.*/ + RT28XXDMAEnable(pAd); + + /* 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 */ + + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, rx_filter_flag); /* enable RX of DMA block*/ + } +#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.*/ + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, rx_filter_flag); + } +#endif /* CONFIG_STA_SUPPORT */ + + { + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC); + } + DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPEnableRxTx\n")); +} + + +void CfgInitHook(PRTMP_ADAPTER pAd) +{ + /*pAd->bBroadComHT = TRUE;*/ +} + + +static INT RtmpChipOpsRegister( + IN RTMP_ADAPTER *pAd, + IN INT infType) +{ + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + int status; + + memset(pChipOps, 0, sizeof(RTMP_CHIP_OP)); + + RtmpChipOpsHook(pAd); + + /* set eeprom related hook functions */ + status = RtmpChipOpsEepromHook(pAd, infType); + + /* set mcu related hook functions */ + switch(infType) + { +#ifdef RTMP_PCI_SUPPORT + case RTMP_DEV_INF_PCI: + case RTMP_DEV_INF_PCIE: + pChipOps->loadFirmware = RtmpAsicLoadFirmware; + pChipOps->eraseFirmware = RtmpAsicEraseFirmware; + pChipOps->sendCommandToMcu = RtmpAsicSendCommandToMcu; + break; +#endif /* RTMP_PCI_SUPPORT */ + + +#ifdef RTMP_RBUS_SUPPORT + case RTMP_DEV_INF_RBUS: + pChipOps->sendCommandToMcu = RtmpAsicSendCommandToSwMcu; + break; +#endif /*RTMP_RBUS_SUPPORT */ + default: + break; + } + + return status; +} + + +INT RtmpRaDevCtrlInit( + IN VOID *pAdSrc, + IN RTMP_INF_TYPE infType) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + /*VOID *handle;*/ + + /* Assign the interface type. We need use it when do register/EEPROM access.*/ + pAd->infType = infType; + +#ifdef CONFIG_STA_SUPPORT + pAd->OpMode = OPMODE_STA; + DBGPRINT(RT_DEBUG_TRACE, ("STA Driver version-%s\n", STA_DRIVER_VERSION)); +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + pAd->OpMode = OPMODE_AP; + DBGPRINT(RT_DEBUG_ERROR, ("AP Driver version-%s\n", AP_DRIVER_VERSION)); +#endif /* CONFIG_AP_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 */ + +#ifdef P2P_SUPPORT + pAd->OpMode = OPMODE_STA; +#endif /* P2P_SUPPORT */ + + + RtmpChipOpsRegister(pAd, infType); + +#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 */ + + + return 0; +} + + +BOOLEAN RtmpRaDevCtrlExit(IN VOID *pAdSrc) +{ + PRTMP_ADAPTER pAd = (PRTMP_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 */ + + + + + /* + 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( + IN PRTMP_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); +} + +VOID RTMP_BBP_IO_READ8_BY_REG_ID( + PRTMP_ADAPTER pAd, + UINT32 Offset, + UINT8 *pValue) +{ + _RTMP_BBP_IO_READ8_BY_REG_ID(pAd, Offset, pValue); +} + +VOID RTMP_BBP_IO_READ8( + PRTMP_ADAPTER pAd, + UCHAR Offset, + UINT8 *pValue, + BOOLEAN FlgValidMCR) +{ + _RTMP_BBP_IO_READ8(pAd, Offset, pValue, FlgValidMCR); +} + +VOID RTMP_BBP_IO_WRITE8_BY_REG_ID( + PRTMP_ADAPTER pAd, + UINT32 Offset, + UINT8 Value) +{ + _RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, Offset, Value); +} + +VOID RTMP_BBP_IO_WRITE8( + PRTMP_ADAPTER pAd, + UCHAR Offset, + UINT8 Value, + BOOLEAN FlgValidMCR) +{ + _RTMP_BBP_IO_WRITE8(pAd, Offset, Value, FlgValidMCR); +} +#endif /* VENDOR_FEATURE3_SUPPORT */ + + +#ifdef RTMP_MAC_PCI +VOID CMDHandler( + IN PRTMP_ADAPTER pAd) +{ + PCmdQElmt cmdqelmt; + PUCHAR pData; + NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS; +/* ULONG Now = 0;*/ +/* NTSTATUS ntStatus;*/ +/* unsigned long IrqFlags;*/ + + while (pAd && pAd->CmdQ.size > 0) + { + NdisStatus = NDIS_STATUS_SUCCESS; + + NdisAcquireSpinLock(&pAd->CmdQLock); + RTThreadDequeueCmd(&pAd->CmdQ, &cmdqelmt); + NdisReleaseSpinLock(&pAd->CmdQLock); + + if (cmdqelmt == NULL) + break; + + pData = cmdqelmt->buffer; + + 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 phymode > PHY_11ABGN_MIXED 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); + } + } /* end of while */ +} +#endif /* RTMP_MAC_PCI */ + +VOID AntCfgInit( +IN PRTMP_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, ("\x1b[mAntenna word %X/%d, AntDiv %d\x1b[m\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, ("\x1b[m%s: primary/secondary ant %d/%d\n\x1b[m", + __FUNCTION__, + pAd->RxAnt.Pair1PrimaryRxAnt, + pAd->RxAnt.Pair1SecondaryRxAnt)); +} + +#ifdef MICROWAVE_OVEN_SUPPORT +UINT32 NICSumFalseCCACnt( +IN PRTMP_ADAPTER pAd) +{ + UCHAR Idx; + UINT32 FalseCCACnt = 0; + + for (Idx = 0; Idx < MLME_TASK_EXEC_MULTIPLE; Idx++) + FalseCCACnt += pAd->RalinkCounters.FalseCCACnt_100MS[Idx]; + + return FalseCCACnt; +} + +UINT32 NICSumPLCPErrCnt( +IN PRTMP_ADAPTER pAd) +{ + UCHAR Idx; + UINT32 PLCPErrCnt = 0; + + for (Idx = 0; Idx < MLME_TASK_EXEC_MULTIPLE; Idx++) + PLCPErrCnt += pAd->RalinkCounters.PLCPErrCnt_100MS[Idx]; + + return PLCPErrCnt; +} +#endif /* MICROWAVE_OVEN_SUPPORT */ + diff --git a/mt7620/src/common/rtmp_init_inf.c b/mt7620/src/common/rtmp_init_inf.c new file mode 100644 index 0000000..f7378ca --- /dev/null +++ b/mt7620/src/common/rtmp_init_inf.c @@ -0,0 +1,1657 @@ +/* + *************************************************************************** + * 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 CONFIG_STA_SUPPORT +#ifdef PROFILE_STORE +NDIS_STATUS WriteDatThread( + IN 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; +#ifdef MBSS_SUPPORT + pDrvOps->MBSS_PacketSend = MBSS_PacketSend; +#endif /* MBSS_SUPPORT */ +#ifdef WDS_SUPPORT + pDrvOps->WDS_PacketSend = WDS_PacketSend; +#endif /* WDS_SUPPORT */ +#ifdef APCLI_SUPPORT + pDrvOps->APC_PacketSend = APC_PacketSend; +#endif /* APCLI_SUPPORT */ +#ifdef MESH_SUPPORT + pDrvOps->MESH_PacketSend = MESH_PacketSend; +#endif /* MESH_SUPPORT */ +#ifdef P2P_SUPPORT + pDrvOps->P2P_PacketSend = P2P_PacketSend; +#endif /* P2P_SUPPORT */ + + 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( + IN VOID *pAdSrc, + IN PSTRING pDefaultMac, + IN PSTRING pHostName) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + UINT index; + UCHAR TmpPhy; + NDIS_STATUS Status; + + if (pAd == NULL) + return FALSE; + + +#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 */ + + /* reset Adapter flags*/ + RTMP_CLEAR_FLAGS(pAd); + + /* Init BssTab & ChannelInfo tabbles for auto channel select.*/ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +/*#ifdef AUTO_CH_SELECT_ENHANCE*/ + AutoChBssTableInit(pAd); + ChannelInfoInit(pAd); +/*#endif AUTO_CH_SELECT_ENHANCE */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#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 */ + + /* Make sure MAC gets ready.*/ + index = 0; + if (WaitForAsicReady(pAd) != TRUE) + goto err1; + + DBGPRINT(RT_DEBUG_TRACE, ("MAC[Ver:Rev=0x%08x]\n", pAd->MACVersion)); + + + 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 RTMP_MAC_PCI + + /* To fix driver disable/enable hang issue when radio off*/ + RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x2); +#endif /* RTMP_MAC_PCI */ + + /* Disable DMA*/ + RT28XXDMADisable(pAd); + + + /* Load 8051 firmware*/ + Status = NICLoadFirmware(pAd); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("NICLoadFirmware failed, Status[=0x%08x]\n", Status)); + goto err1; + } + + NICLoadRateSwitchingParams(pAd); + + /* Disable interrupts here which is as soon as possible*/ + /* This statement should never be true. We might consider to remove it later*/ +#ifdef RTMP_MAC_PCI + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) + { + RTMP_ASIC_INTERRUPT_DISABLE(pAd); + } +#endif /* RTMP_MAC_PCI */ + +#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; + } + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); + + /* initialize MLME*/ +#ifdef RT6352 + 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; + } + +#ifdef RMTP_RBUS_SUPPORT +#ifdef VIDEO_TURBINE_SUPPORT + VideoConfigInit(pAd); +#endif /* VIDEO_TURBINE_SUPPORT */ +#endif /* RMTP_RBUS_SUPPORT */ + + /* Initialize pAd->StaCfg, pAd->ApCfg, pAd->CommonCfg to manufacture default*/ + + UserCfgInit(pAd); + +#ifdef MESH_SUPPORT + /* Initialize Mesh configuration*/ + MeshCfgInit(pAd, pHostName); +#endif /* MESH_SUPPORT */ + + Status = RtmpNetTaskInit(pAd); + if (Status != NDIS_STATUS_SUCCESS) + goto err5; + +/* COPY_MAC_ADDR(pAd->ApCfg.MBSSID[apidx].Bssid, netif->hwaddr);*/ +/* pAd->bForcePrintTX = TRUE;*/ + + CfgInitHook(pAd); + +#ifdef CONFIG_AP_SUPPORT + if ((pAd->OpMode == OPMODE_AP) +#ifdef P2P_SUPPORT + || TRUE +#endif /* P2P_SUPPORT */ + ) + APInitialize(pAd); +#endif /* CONFIG_AP_SUPPORT */ + +#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; + } + + + /* 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_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + } +#endif /* CONFIG_AP_SUPPORT */ + + /* Read parameters from Config File */ + /* unknown, it will be updated in NICReadEEPROMParameters */ + pAd->RfIcType = RFIC_UNKNOWN; + Status = RTMPReadParametersHook(pAd); + + if(pAd->CommonCfg.Channel==0) + { + RTMPSetDefaultChannel(pAd); + } + +#ifdef CONFIG_STA_SUPPORT +#ifdef CREDENTIAL_STORE + RecoverConnectInfo(pAd); +#endif /* CREDENTIAL_STORE */ +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_OFF, ("1. Phy Mode = %d\n", pAd->CommonCfg.PhyMode)); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("RTMPReadParametersHook failed, Status[=0x%08x]\n",Status)); + goto err6; + } + + +#ifdef DOT11_N_SUPPORT + /*Init Ba Capability parameters.*/ +/* RT28XX_BA_INIT(pAd);*/ + 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*/ + + /* Load 8051 firmware; crash when FW image not existent*/ + /* Status = NICLoadFirmware(pAd);*/ + /* if (Status != NDIS_STATUS_SUCCESS)*/ + /* break;*/ + + DBGPRINT(RT_DEBUG_OFF, ("2. Phy Mode = %d\n", pAd->CommonCfg.PhyMode)); + + /* We should read EEPROM for all cases. rt2860b*/ + 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", + 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 */ +#endif /* CONFIG_STA_SUPPORT */ + + DBGPRINT(RT_DEBUG_OFF, ("3. Phy Mode = %d\n", pAd->CommonCfg.PhyMode)); + +#ifdef LED_CONTROL_SUPPORT + /* Send LED Setting to MCU */ + RTMPInitLEDMode(pAd); +#endif /* LED_CONTROL_SUPPORT */ + + NICInitAsicFromEEPROM(pAd); /* rt2860b */ + +#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%lx)\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 */ + + InitRfPaModeTable(pAd); + +#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*/ + TmpPhy = pAd->CommonCfg.PhyMode; + pAd->CommonCfg.PhyMode = 0xff; + RTMPSetPhyMode(pAd, TmpPhy); +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif /* DOT11_N_SUPPORT */ + + /* No valid channels.*/ + 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 CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef AP_QLOAD_SUPPORT + /* init QBSS Element */ + 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 CONFIG_AP_SUPPORT + + /* Initialize RF register to default value*/ + + if (pAd->OpMode == OPMODE_AP) + { + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + } +#endif /* CONFIG_AP_SUPPORT */ + +#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)) + { + + /* Undo everything if it failed*/ + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { +/* NdisMDeregisterInterrupt(&pAd->Interrupt);*/ + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); + } +/* RTMPFreeAdapter(pAd); we will free it in disconnect()*/ + } + 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); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE); + + 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)) + { + UINT8 BBPValue = 0; + + /* Enable Interrupt first due to we need to scan channel to receive beacons.*/ + RTMP_IRQ_ENABLE(pAd); + /* Now Enable RxTx*/ + RTMPEnableRxTx(pAd); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP); + + /* Let BBP register at 20MHz to do scan */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + DBGPRINT(RT_DEBUG_ERROR, ("SYNC - BBP R4 to 20MHz.l\n")); + + /* 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 phymode > PHY_11ABGN_MIXED 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].Bssid))); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef RT6352 + pAd->bCalibrationDone = TRUE; + if (IS_RT6352(pAd)) + { +#ifdef DYNAMIC_VGA_SUPPORT + if (pAd->CommonCfg.MO_Cfg.bDyncVGAEnable) + { + 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); + } +#endif /* DYNAMIC_VGA_SUPPORT */ + } +#endif /* RT6352 */ + + }/* end of else*/ + + /* Set up the Mac address*/ +#ifdef CONFIG_AP_SUPPORT +#ifndef P2P_APCLI_SUPPORT + RtmpOSNetDevAddrSet(pAd->OpMode, pAd->net_dev, &pAd->CurrentAddress[0], NULL); +#endif /* P2P_APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + RtmpOSNetDevAddrSet(pAd->OpMode, pAd->net_dev, &pAd->CurrentAddress[0], (PUCHAR)(pAd->StaCfg.dev_name)); +#endif /* CONFIG_STA_SUPPORT */ + + /* Various AP function init*/ +#ifdef CONFIG_AP_SUPPORT +#ifdef P2P_SUPPORT + +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { +#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) */ +/* RT28xx_MBSS_Init(pAd, pAd->net_dev); os abl move to rt_main_dev.c*/ +#endif /* MBSS_SUPPORT */ + +#ifdef WDS_SUPPORT +/* RT28xx_WDS_Init(pAd, pAd->net_dev);*/ +#endif /* WDS_SUPPORT */ + +#ifdef APCLI_SUPPORT +/* RT28xx_ApCli_Init(pAd, pAd->net_dev);*/ +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_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 MESH_SUPPORT +/* RTMP_Mesh_Init(pAd, pAd->net_dev, pHostName);*/ +#endif /* MESH_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 P2P_SUPPORT +/* RTMP_P2P_Init(pAd, pAd->net_dev); */ +#endif /* P2P_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 */ + RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, 0xedcba980); /* Fallback MCS8->MCS0 */ + +#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 */ + +#if defined(RT2883) || defined(RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + { + UINT8 BBPValue = 0; + BBP_IO_READ8_BY_REG_ID(pAd, BBP_R65, &BBPValue); + + if (pAd->CommonCfg.FineAGC) + BBPValue |= 0x40; /* turn on fine AGC*/ + else + BBPValue &= ~0x40; /* turn off fine AGC*/ + BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R65, BBPValue); + } +#endif /* defined(RT2883) || defined(RT3883) */ + +#ifdef DOT11_N_SUPPORT +#ifdef TXBF_SUPPORT + 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); + } + + if (pAd->CommonCfg.ETxBfTimeout) + { + RTMP_IO_WRITE32(pAd, TX_TXBF_CFG_3, pAd->CommonCfg.ETxBfTimeout); + } +#endif /* TXBF_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef RT305x + RTMP_CHIP_SPECIFIC(pAd, RT305x_INITIALIZATION, NULL, 0); +#endif /* RT305x */ + + + + DBGPRINT_S(Status, ("<==== rt28xx_init, Status=%x\n", Status)); + + return TRUE; + +/*err7: + APStop(pAd);*/ +err6: + +#ifdef IGMP_SNOOP_SUPPORT + MultiCastFilterTableReset(&pAd->pMulticastFilterTable); +#endif /* IGMP_SNOOP_SUPPORT */ + + MeasureReqTabExit(pAd); + TpcReqTabExit(pAd); +err5: + RtmpNetTaskExit(pAd); + UserCfgExit(pAd); +err4: + MlmeHalt(pAd); + RTMP_TimerListRelease(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: + +#ifdef CONFIG_AP_SUPPORT + /* 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 */ + + /* shall not set priv to NULL here because the priv didn't been free yet.*/ + /*net_dev->priv = 0;*/ +#ifdef INF_AMAZON_SE +err0: +#endif /* INF_AMAZON_SE */ +#ifdef ST +err0: +#endif /* ST */ + + DBGPRINT(RT_DEBUG_ERROR, ("!!! rt28xx Initialized fail !!!\n")); + return FALSE; +} + + +VOID RTMPDrvOpen( + IN VOID *pAdSrc) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + + /* Enable Interrupt*/ + RTMP_IRQ_ENABLE(pAd); + + /* Now Enable RxTx*/ + RTMPEnableRxTx(pAd); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP); + + { + UINT32 reg = 0; + RTMP_IO_READ32(pAd, 0x1300, ®); /* clear garbage interrupts*/ + printk("0x1300 = %08x\n", reg); + } + + { +/* u32 reg;*/ +/* UINT8 byte;*/ +/* u16 tmp;*/ + +/* RTMP_IO_READ32(pAd, XIFS_TIME_CFG, ®);*/ + +/* tmp = 0x0805;*/ +/* reg = (reg & 0xffff0000) | tmp;*/ +/* RTMP_IO_WRITE32(pAd, XIFS_TIME_CFG, reg);*/ + + } + + +#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 */ + + +#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 */ + + +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef WSC_INCLUDED +#ifdef CONFIG_AP_SUPPORT + if ((pAd->OpMode == OPMODE_AP) +#ifdef P2P_SUPPORT + /* P2P will use ApCfg.MBSSID and ApCfg.ApCliTab also. */ + || TRUE +#endif /* P2P_SUPPORT */ + ) + { + INT index; + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[index].Hostapd == TRUE) + { + 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 */ +} + + +VOID RTMPDrvClose( + IN VOID *pAdSrc, + IN VOID *net_dev) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + BOOLEAN Cancelled; + UINT32 i = 0; + + + Cancelled = FALSE; + +#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 */ + + 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; +#endif /* EXT_BUILD_CHANNEL_LIST */ + pAd->CommonCfg.bCountryFlag = 0; + + +#ifdef MESH_SUPPORT + /* close all mesh link before the interface go down.*/ + if (MESH_ON(pAd)) + MeshDown(pAd, TRUE); +#endif /* MESH_SUPPORT */ + +#ifdef WDS_SUPPORT + WdsDown(pAd); +#endif /* WDS_SUPPORT */ + + 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 + 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(WOW_IFDOWN_SUPPORT) + if (pAd->WOW_Cfg.bEnable == TRUE) + RT28xxUsbAsicWOWEnable(pAd); + else +#endif /* WOW_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 */ + /* Shutdown Access Point function, release all related resources */ + APShutdown(pAd); + +/*#ifdef AUTO_CH_SELECT_ENHANCE*/ + /* Free BssTab & ChannelInfo tabbles.*/ +/* AutoChBssTableDestroy(pAd); */ +/* ChannelInfoDestroy(pAd); */ +/*#endif AUTO_CH_SELECT_ENHANCE */ + } +#endif /* CONFIG_AP_SUPPORT */ + + MeasureReqTabExit(pAd); + TpcReqTabExit(pAd); + +#ifdef LED_CONTROL_SUPPORT + RTMPExitLEDMode(pAd); +#endif // LED_CONTROL_SUPPORT + + + /* 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 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) + { + 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; + + 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 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 +#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_TimerListRelease(pAd); + +#ifdef RTMP_TIMER_TASK_SUPPORT + NdisFreeSpinLock(&pAd->TimerQLock); +#endif /* RTMP_TIMER_TASK_SUPPORT */ +} + + +VOID RTMPInfClose( + IN VOID *pAdSrc) +{ + PRTMP_ADAPTER pAd = (PRTMP_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 MESH_SUPPORT + MeshMakeBeacon(pAd, MESH_BEACON_IDX(pAd)); + MeshUpdateBeaconFrame(pAd, MESH_BEACON_IDX(pAd)); +#endif /* MESH_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(WOW_IFDOWN_SUPPORT) /* In WOW state, can't issue disassociation reqeust */ + pAd->WOW_Cfg.bEnable == FALSE && +#endif /* WOW_SUPPORT */ + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + MLME_DISASSOC_REQ_STRUCT DisReq; + MLME_QUEUE_ELEM *MsgElem;/* = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);*/ + + 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); +/* kfree(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.pWpsProbeReqIe) + { +/* kfree(pAd->StaCfg.pWpsProbeReqIe);*/ + os_free_mem(NULL, pAd->StaCfg.pWpsProbeReqIe); + pAd->StaCfg.pWpsProbeReqIe = NULL; + pAd->StaCfg.WpsProbeReqIeLen = 0; + } + + if (pAd->StaCfg.pWpaAssocIe) + { +/* kfree(pAd->StaCfg.pWpaAssocIe);*/ + os_free_mem(NULL, pAd->StaCfg.pWpaAssocIe); + pAd->StaCfg.pWpaAssocIe = NULL; + pAd->StaCfg.WpaAssocIeLen = 0; + } +#endif /* WPA_SUPPLICANT_SUPPORT */ + + + } +#endif /* CONFIG_STA_SUPPORT */ +} + + + + +PNET_DEV RtmpPhyNetDevMainCreate( + IN VOID *pAdSrc) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + PNET_DEV pDevNew; + UINT32 MC_RowID = 0, IoctlIF = 0; + + + pAd = pAd; + +#ifdef MULTIPLE_CARD_SUPPORT + MC_RowID = pAd->MC_RowID; +#endif /* MULTIPLE_CARD_SUPPORT */ +#ifdef HOSTAPD_SUPPORT + IoctlIF = pAd->IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + + pDevNew = RtmpOSNetDevCreate((INT32)MC_RowID, (UINT32 *)&IoctlIF, + INT_MAIN, 0, sizeof(PRTMP_ADAPTER), INF_MAIN_DEV_NAME); + +#ifdef HOSTAPD_SUPPORT + pAd->IoctlIF = IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + + return pDevNew; +} + +#ifdef CONFIG_STA_SUPPORT +#ifdef PROFILE_STORE +static void WriteConfToDatFile( + IN PRTMP_ADAPTER pAd) +{ + 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; +// INT tempStrLen = 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 kmalloc 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 kmalloc 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 kmalloc 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_11Encryption2Enabled) + sprintf(pTempStr, "EncrypType=TKIP"); + else if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + sprintf(pTempStr, "EncrypType=AES"); + } + RtmpOSFileWrite(file_w, pTempStr, strlen(pTempStr)); + RtmpOSFileWrite(file_w, "\n", 1); + } + else + { + break; + } + } + RtmpOSFileClose(file_w); + } + +WriteErr: + if (pTempStr) +/* kfree(pTempStr); */ + os_free_mem(NULL, pTempStr); +ReadErr: +WriteFileOpenErr: + if (cfgData) +/* kfree(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 */ + +/* End of rtmp_init_inf.c */ diff --git a/mt7620/src/common/rtmp_mcu.c b/mt7620/src/common/rtmp_mcu.c new file mode 100644 index 0000000..d5d0df3 --- /dev/null +++ b/mt7620/src/common/rtmp_mcu.c @@ -0,0 +1,720 @@ +/* + *************************************************************************** + * 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: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#include "rt_config.h" +#include "firmware.h" + + + +/* New 8k byte firmware size for RT3071/RT3072*/ +#define FIRMWAREIMAGE_MAX_LENGTH 0x2000 +#ifdef WOW_SUPPORT +#define FIRMWAREIMAGE_WOW_LENGTH 0x3000 /* WOW support firmware(12KB) */ +#endif/*WOW_SUPPORT*/ +#define FIRMWAREIMAGE_LENGTH (sizeof (FirmwareImage) / sizeof(UCHAR)) +#define FIRMWARE_MAJOR_VERSION 0 + +#define FIRMWAREIMAGEV1_LENGTH 0x1000 +#define FIRMWAREIMAGEV2_LENGTH 0x1000 +#ifdef WOW_SUPPORT +#define FIRMWAREIMAGEV3_LENGTH 0x2000 /* WOW support firmware */ +#endif/*WOW_SUPPORT*/ + +#ifdef RTMP_MAC_PCI +#define FIRMWARE_MINOR_VERSION 2 +#endif /* RTMP_MAC_PCI */ + +const unsigned short ccitt_16Table[] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 +}; +#define ByteCRC16(v, crc) \ + (unsigned short)((crc << 8) ^ ccitt_16Table[((crc >> 8) ^ (v)) & 255]) + +unsigned char BitReverse(unsigned char x) +{ + int i; + unsigned char Temp=0; + for(i=0; ; i++) + { + if(x & 0x80) Temp |= 0x80; + if(i==7) break; + x <<= 1; + Temp >>= 1; + } + return Temp; +} + + +/* + ======================================================================== + + Routine Description: + erase 8051 firmware image in MAC ASIC + + Arguments: + Adapter Pointer to our adapter + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +INT RtmpAsicEraseFirmware( + IN PRTMP_ADAPTER pAd) +{ + ULONG i; + + for(i=0; i= 100) + Status = NDIS_STATUS_FAILURE; + + return Status; +} + +NDIS_STATUS isMCUnotReady( + IN PRTMP_ADAPTER pAd) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + ULONG Index; + UINT32 MacReg; + + Index = 0; + + do { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return NDIS_STATUS_FAILURE; + + RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &MacReg); + + if (MacReg & 0x80) /* check bit 7*/ + break; + + RTMPusecDelay(1000); + } while (Index++ < 1000); + + if (Index >= 1000) + Status = NDIS_STATUS_FAILURE; + + return Status; +} +/* + ======================================================================== + + Routine Description: + Load 8051 firmware file into MAC ASIC + + Arguments: + Adapter Pointer to our adapter + + Return Value: + NDIS_STATUS_SUCCESS firmware image load ok + NDIS_STATUS_FAILURE image not found + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +NDIS_STATUS RtmpAsicLoadFirmware( + IN PRTMP_ADAPTER pAd) +{ +#ifdef BIN_IN_FILE +#define NICLF_DEFAULT_USE() \ + flg_default_firm_use = TRUE; \ + DBGPRINT(RT_DEBUG_OFF, ("%s - Use default firmware!\n", __FUNCTION__)); + + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + PUCHAR src; + RTMP_OS_FD srcf; + INT retval, i; + PUCHAR pFirmwareImage; + INT FileLength = 0; + UINT32 MacReg; + ULONG Index; + ULONG firm; + BOOLEAN flg_default_firm_use = FALSE; + RTMP_OS_FS_INFO osFSInfo; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s\n", __FUNCTION__)); + + /* init */ + pFirmwareImage = NULL; + src = RTMP_FIRMWARE_FILE_NAME; + + RtmpOSFSInfoChange(&osFSInfo, TRUE); + + pAd->FirmwareVersion = (FIRMWARE_MAJOR_VERSION << 8) + \ + FIRMWARE_MINOR_VERSION; + + + /* allocate firmware buffer */ +/* pFirmwareImage = kmalloc(MAX_FIRMWARE_IMAGE_SIZE, MEM_ALLOC_FLAG);*/ + os_alloc_mem(pAd, (UCHAR **)&pFirmwareImage, MAX_FIRMWARE_IMAGE_SIZE); + if (pFirmwareImage == NULL) + { + /* allocate fail, use default firmware array in firmware.h */ + DBGPRINT(RT_DEBUG_ERROR, ("%s - Allocate memory fail!\n", __FUNCTION__)); + NICLF_DEFAULT_USE(); + } + else + { + /* allocate ok! zero the firmware buffer */ + memset(pFirmwareImage, 0x00, MAX_FIRMWARE_IMAGE_SIZE); + } /* End of if */ + + + /* if ok, read firmware file from *.bin file */ + if (flg_default_firm_use == FALSE) + { + do + { + /* open the bin file */ + srcf = RtmpOSFileOpen(src, O_RDONLY, 0); + + if (IS_FILE_OPEN_ERR(srcf)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s - Error opening file %s\n", __FUNCTION__, src)); + NICLF_DEFAULT_USE(); + break; + } + + + /* read the firmware from the file *.bin */ + FileLength = RtmpOSFileRead(srcf, pFirmwareImage, MAX_FIRMWARE_IMAGE_SIZE); + if (FileLength != MAX_FIRMWARE_IMAGE_SIZE) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: error file length (=%d) in RT2860AP.BIN\n", + __FUNCTION__, FileLength)); + NICLF_DEFAULT_USE(); + break; + } + else + { + PUCHAR ptr = pFirmwareImage; + USHORT crc = 0xffff; + + + /* calculate firmware CRC */ + for(i=0; i<(MAX_FIRMWARE_IMAGE_SIZE-2); i++, ptr++) + crc = ByteCRC16(BitReverse(*ptr), crc); + /* End of for */ + + if ((pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-2] != \ + (UCHAR)BitReverse((UCHAR)(crc>>8))) || + (pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-1] != \ + (UCHAR)BitReverse((UCHAR)crc))) + { + /* CRC fail */ + DBGPRINT(RT_DEBUG_ERROR, ("%s: CRC = 0x%02x 0x%02x " + "error, should be 0x%02x 0x%02x\n", + __FUNCTION__, + pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-2], + pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-1], + (UCHAR)(crc>>8), (UCHAR)(crc))); + NICLF_DEFAULT_USE(); + break; + } + else + { + /* firmware is ok */ + pAd->FirmwareVersion = \ + (pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-4] << 8) + + pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-3]; + + /* check if firmware version of the file is too old */ + if ((pAd->FirmwareVersion) < \ + ((FIRMWARE_MAJOR_VERSION << 8) + + FIRMWARE_MINOR_VERSION)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: firmware version too old!\n", __FUNCTION__)); + NICLF_DEFAULT_USE(); + break; + } /* End of if */ + } /* End of if */ + + DBGPRINT(RT_DEBUG_TRACE, + ("NICLoadFirmware: CRC ok, ver=%d.%d\n", + pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-4], + pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-3])); + } /* End of if (FileLength == MAX_FIRMWARE_IMAGE_SIZE) */ + break; + } while(TRUE); + + /* close firmware file */ + if (IS_FILE_OPEN_ERR(srcf)) + ; + else + { + retval = RtmpOSFileClose(srcf); + if (retval) + { + DBGPRINT(RT_DEBUG_ERROR, ("--> Error %d closing %s\n", -retval, src)); + } + } + } + + + /* write firmware to ASIC */ + if (flg_default_firm_use == TRUE) + { + /* use default fimeware, free allocated buffer */ + if (pFirmwareImage != NULL) +/* kfree(pFirmwareImage);*/ + os_free_mem(NULL, pFirmwareImage); + /* End of if */ + + /* use default *.bin array */ + pFirmwareImage = FirmwareImage; + FileLength = sizeof(FirmwareImage); + } /* End of if */ + + /* enable Host program ram write selection */ + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x10000); + + for(i=0; iMACVersion >> 16); + + + pFirmwareImage = FirmwareImage; + FileLength = sizeof(FirmwareImage); + + + /* New 8k byte firmware size for RT3071/RT3072*/ + /*DBGPRINT(RT_DEBUG_TRACE, ("Usb Chip\n"));*/ + if (FIRMWAREIMAGE_LENGTH == FIRMWAREIMAGE_MAX_LENGTH) + /*The firmware image consists of two parts. One is the origianl and the other is the new.*/ + /*Use Second Part*/ + { +#ifdef RTMP_MAC_PCI + if ((Version == 0x2860) || (Version == 0x3572) || IS_RT3090(pAd) + || IS_RT3390(pAd) || IS_RT3593(pAd) || IS_RT5390(pAd) || IS_RT5392(pAd)) + { + pFirmwareImage = FirmwareImage; + FileLength = FIRMWAREIMAGE_LENGTH; + } +#endif /* RTMP_MAC_PCI */ + } + else + { +#if defined(WOW_SUPPORT) && defined(RTMP_MAC_USB) + /* WOW firmware is 12KB */ + if ((Version != 0x2860) && (Version != 0x2872) && (Version != 0x3070)) + { + if (FIRMWAREIMAGE_LENGTH == FIRMWAREIMAGE_WOW_LENGTH) /* size 0x3000 */ + { + if (pAd->WOW_Cfg.bWOWFirmware == TRUE) + { + pFirmwareImage = (PUCHAR)&FirmwareImage[FIRMWAREIMAGEV3_LENGTH]; /* WOW offset: 0x2000 */ + FileLength = FIRMWAREIMAGEV1_LENGTH; /* 0x1000 */ + DBGPRINT(RT_DEBUG_OFF, ("%s: Load WOW firmware!!\n", __FUNCTION__)); + } + else + { + pFirmwareImage = (PUCHAR)&FirmwareImage[FIRMWAREIMAGEV2_LENGTH]; /* normal offset: 0x1000 */ + FileLength = FIRMWAREIMAGEV1_LENGTH; /* 0x1000 */ + DBGPRINT(RT_DEBUG_OFF, ("%s: Load normal firmware!!\n", __FUNCTION__)); + } + + } + } + else +#endif /* defined(WOW_SUPPORT) && defined(RTMP_MAC_USB) */ + { + DBGPRINT(RT_DEBUG_ERROR, ("KH: bin file should be 8KB.\n")); + Status = NDIS_STATUS_FAILURE; + } + } + + RTMP_WRITE_FIRMWARE(pAd, pFirmwareImage, FileLength); + +#endif + + if (isMCUnotReady(pAd)) + { + DBGPRINT(RT_DEBUG_ERROR, ("NICLoadFirmware: MCU is not ready\n\n\n")); + Status = NDIS_STATUS_FAILURE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("<=== %s (status=%d)\n", __FUNCTION__, Status)); + + return Status; +} + + +INT RtmpAsicSendCommandToMcu( + IN PRTMP_ADAPTER pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1, + IN BOOLEAN FlgIsNeedLocked) +{ + HOST_CMD_CSR_STRUC H2MCmd; + H2M_MAILBOX_STRUC H2MMailbox; + INT i = 0; + int ret; + + +#ifdef RTMP_MAC_PCI +#ifdef SPECIFIC_BCN_BUF_SUPPORT + ULONG IrqFlags = 0; +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef PCIE_PS_SUPPORT + ULONG Configuration; + ULONG offset; +#endif /* PCIE_PS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT +#ifdef PCIE_PS_SUPPORT + + + /* 3090F power solution 3 has hw limitation that needs to ban all mcu command */ + /* when firmware is in radio state. For other chip doesn't have this limitation. */ + if ((((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd) + || IS_RT3593(pAd) || IS_RT5390(pAd) || IS_RT5392(pAd)) + && IS_VERSION_AFTER_F(pAd)) || IS_RT5592(pAd) || IS_RT3290(pAd)) + && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) + && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) + { + + RTMP_SEM_LOCK(&pAd->McuCmdLock); + + if ((pAd->brt30xxBanMcuCmd == TRUE) + && (Command != WAKE_MCU_CMD) && (Command != RFOFF_MCU_CMD)) + { + + DBGPRINT(RT_DEBUG_TRACE, (" Ban Mcu Cmd %x in sleep mode\n", Command)); + RTMP_SEM_UNLOCK(&pAd->McuCmdLock); + return FALSE; + } + else if ((Command == SLEEP_MCU_CMD) + ||(Command == RFOFF_MCU_CMD)) + { + pAd->brt30xxBanMcuCmd = TRUE; + } + else if (Command != WAKE_MCU_CMD) + { + pAd->brt30xxBanMcuCmd = FALSE; + } + + RTMP_SEM_UNLOCK(&pAd->McuCmdLock); + + + } + + + if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd) + || IS_RT3593(pAd) || IS_RT5390(pAd) || IS_RT5392(pAd) + || IS_RT5592(pAd)) + && IS_VERSION_AFTER_F(pAd) + && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) + && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) + && (Command == WAKE_MCU_CMD)) + ) + { +#ifdef RTMP_MAC_PCI +#ifdef SPECIFIC_BCN_BUF_SUPPORT + if (FlgIsNeedLocked == TRUE) + { + RTMP_MAC_SHR_MSEL_PROTECT_LOCK(pAd, IrqFlags); + } +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + /* don't check MailBox for 0x84, 0x31*/ + if ((Command != 0x84) && (Command != WAKE_MCU_CMD)) + { + do + { + RTMP_IO_FORCE_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word); + if (H2MMailbox.field.Owner == 0) + break; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + { +#ifdef RTMP_MAC_PCI +#ifdef SPECIFIC_BCN_BUF_SUPPORT + if (FlgIsNeedLocked == TRUE) + RTMP_MAC_SHR_MSEL_PROTECT_UNLOCK(pAd, IrqFlags); +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + return FALSE; + } + RTMPusecDelay(2); + DBGPRINT(RT_DEBUG_INFO, ("AsicSendCommanToMcu::Mail box is busy\n")); + } while(i++ < 100); + + if (i >= 100) + { + DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n")); +#ifdef RTMP_MAC_PCI +#ifdef SPECIFIC_BCN_BUF_SUPPORT + if (FlgIsNeedLocked == TRUE) + RTMP_MAC_SHR_MSEL_PROTECT_UNLOCK(pAd, IrqFlags); +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + return FALSE; + } + } + + H2MMailbox.field.Owner = 1; /* pass ownership to MCU*/ + H2MMailbox.field.CmdToken = Token; + H2MMailbox.field.HighByte = Arg1; + H2MMailbox.field.LowByte = Arg0; + RTMP_IO_FORCE_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word); + + H2MCmd.word = 0; + H2MCmd.field.HostCommand = Command; + RTMP_IO_FORCE_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word); +#ifdef RTMP_MAC_PCI +#ifdef SPECIFIC_BCN_BUF_SUPPORT + if (FlgIsNeedLocked == TRUE) + RTMP_MAC_SHR_MSEL_PROTECT_UNLOCK(pAd, IrqFlags); +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + + } + else +#endif /* PCIE_PS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + { +#ifdef RTMP_MAC_PCI +#ifdef SPECIFIC_BCN_BUF_SUPPORT + if (FlgIsNeedLocked == TRUE) + { + RTMP_MAC_SHR_MSEL_PROTECT_LOCK(pAd, IrqFlags); + } +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + + + ret = FALSE; + do + { + RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word); + if (H2MMailbox.field.Owner == 0) + break; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + { +#ifdef RTMP_MAC_PCI +#ifdef SPECIFIC_BCN_BUF_SUPPORT + if (FlgIsNeedLocked == TRUE) + RTMP_MAC_SHR_MSEL_PROTECT_UNLOCK(pAd, IrqFlags); +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + goto done; + } + RTMPusecDelay(2); + } while(i++ < 100); + + if (i >= 100) + { +#ifdef RTMP_MAC_PCI +#ifdef RALINK_ATE + if (IS_PCI_INF(pAd) && (pAd->ate.bFWLoading == TRUE)) + { + ; /* wait for firmware loading */ + } + else +#endif /* RALINK_ATE */ +#endif /* RTMP_MAC_PCI */ + { + DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n")); + } +#ifdef RTMP_MAC_PCI +#ifdef SPECIFIC_BCN_BUF_SUPPORT + if (FlgIsNeedLocked == TRUE) + RTMP_MAC_SHR_MSEL_PROTECT_UNLOCK(pAd, IrqFlags); +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + goto done; + } +#ifdef RTMP_MAC_PCI +#ifdef RALINK_ATE + else if (IS_PCI_INF(pAd) && (pAd->ate.bFWLoading == TRUE)) + { + /* mail box is not busy anymore */ + /* reloading of firmware is completed */ + pAd->ate.bFWLoading = FALSE; + } +#endif /* RALINK_ATE */ +#endif /* RTMP_MAC_PCI */ + + H2MMailbox.field.Owner = 1; /* pass ownership to MCU*/ + H2MMailbox.field.CmdToken = Token; + H2MMailbox.field.HighByte = Arg1; + H2MMailbox.field.LowByte = Arg0; + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word); + + H2MCmd.word = 0; + H2MCmd.field.HostCommand = Command; + RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word); +#ifdef RTMP_MAC_PCI +#ifdef SPECIFIC_BCN_BUF_SUPPORT + if (FlgIsNeedLocked == TRUE) + RTMP_MAC_SHR_MSEL_PROTECT_UNLOCK(pAd, IrqFlags); +#endif // SPECIFIC_BCN_BUF_SUPPORT // +#endif /* RTMP_MAC_PCI */ +} + +#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 ((((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd) + || IS_RT3593(pAd) || IS_RT5390(pAd) || IS_RT5392(pAd)) && IS_VERSION_AFTER_F(pAd)) || IS_RT5592(pAd) || IS_RT3290(pAd)) + && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) + && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) + { + /*Put this is after RF programming. */ + /*NdisAcquireSpinLock(&pAd->McuCmdLock);*/ + /*pAd->brt30xxBanMcuCmd = FALSE;*/ + /*NdisReleaseSpinLock(&pAd->McuCmdLock);*/ + switch (Command) + { + case WAKE_MCU_CMD : + RTMPusecDelay(2500); + + if ((pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) && + (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) + { + /* Put this is after RF program. */ + pAd->brt30xxBanMcuCmd = FALSE; + } + break; + case SLEEP_MCU_CMD : + RTMPusecDelay(2000); + break; + } + } + +#endif /* PCIE_PS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + if (Command == WAKE_MCU_CMD) + pAd->LastMCUCmd = Command; + + ret = TRUE; + +done: + + return ret; +} + diff --git a/mt7620/src/common/rtmp_swmcu.c b/mt7620/src/common/rtmp_swmcu.c new file mode 100644 index 0000000..488dc09 --- /dev/null +++ b/mt7620/src/common/rtmp_swmcu.c @@ -0,0 +1,150 @@ +/* + *************************************************************************** + * 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 WSC_LED_SUPPORT + case MCU_SET_WPS_LED_MODE: + pSWMCULedCntl->LedParameter.LedMode = Arg0; + pSWMCULedCntl->LinkStatus = Arg1; + SetWPSLinkStatus(pAd); + break; +#endif /* WSC_LED_SUPPORT */ +#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/mt7620/src/common/rtmp_timer.c b/mt7620/src/common/rtmp_timer.c new file mode 100644 index 0000000..d213db2 --- /dev/null +++ b/mt7620/src/common/rtmp_timer.c @@ -0,0 +1,408 @@ +/* + *************************************************************************** + * 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 CONFIG_STA_SUPPORT +#ifdef ADHOC_WPA2PSK_SUPPORT +BUILD_TIMER_FUNCTION(Adhoc_WpaRetryExec); +#endif /* ADHOC_WPA2PSK_SUPPORT */ +#endif /* CONFIG_STA_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 */ + +#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 PCIE_PS_SUPPORT +BUILD_TIMER_FUNCTION(PsPollWakeExec); +BUILD_TIMER_FUNCTION(RadioOnExec); +#endif /* PCIE_PS_SUPPORT */ +#ifdef QOS_DLS_SUPPORT +BUILD_TIMER_FUNCTION(DlsTimeoutAction); +#endif /* QOS_DLS_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT +BUILD_TIMER_FUNCTION(TDLS_TimeoutAction); +#endif /* DOT11Z_TDLS_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); +#ifdef WSC_V2_SUPPORT +BUILD_TIMER_FUNCTION(WscSetupLockTimeout); +#endif /* WSC_V2_SUPPORT */ +#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 MESH_SUPPORT +BUILD_TIMER_FUNCTION(MeshPathReqTimeoutAction); +#endif /* MESH_SUPPORT */ + + +#ifdef TXBF_SUPPORT +BUILD_TIMER_FUNCTION(eTxBfProbeTimerExec); +#endif /* TXBF_SUPPORT */ + +#ifdef P2P_SUPPORT +BUILD_TIMER_FUNCTION(P2PCTWindowTimer); +BUILD_TIMER_FUNCTION(P2pSwNoATimeOut); +BUILD_TIMER_FUNCTION(P2pPreAbsenTimeOut); +BUILD_TIMER_FUNCTION(P2pWscTimeOut); +BUILD_TIMER_FUNCTION(P2pReSendTimeOut); +BUILD_TIMER_FUNCTION(P2pCliReConnectTimeOut); +#endif /* 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 */ + +#ifdef RTMP_TIMER_TASK_SUPPORT +static void RtmpTimerQHandle(RTMP_ADAPTER *pAd) +{ +/*#ifndef KTHREAD_SUPPORT*/ + int status; +/*#endif*/ + 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); + } + } + +/*#ifndef KTHREAD_SUPPORT*/ + if (status != 0) + { + pAd->TimerQ.status = RTMP_TASK_STAT_STOPED; + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + break; + } +/*#endif*/ + } +} + + +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/mt7620/src/common/spectrum.c b/mt7620/src/common/spectrum.c new file mode 100644 index 0000000..c3e9fb2 --- /dev/null +++ b/mt7620/src/common/spectrum.c @@ -0,0 +1,2459 @@ +/**************************************************************************** + * 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 + + /* 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; + PMEASURE_REQ_ENTRY pPrevEntry = 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 + { + pPrevEntry = pEntry; + 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; + PTPC_REQ_ENTRY pPrevEntry = 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 + { + pPrevEntry = pEntry; + 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, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + 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, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + 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, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + 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, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + 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 */ +} + +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 Aid = 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; + 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__)); + goto END_OF_MEASURE_REQ; + } + + ArgIdx = 1; + while ((thisChar = strsep((char **)&arg, "-")) != NULL) + { + switch(ArgIdx) + { + case 1: /* Aid.*/ + Aid = (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__, Aid, MeasureReqType, MeasureCh)); + if (!VALID_WCID(Aid)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, Aid)); + 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[Aid].Addr, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + pAd->CurrentAddress); + + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + TotalLen = sizeof(MEASURE_REQ_INFO) + sizeof(MEASURE_REQ); + + MakeMeasurementReqFrame(pAd, pOutBuffer, &FrameLen, + sizeof(MEASURE_REQ_INFO), CATEGORY_RM, RM_BASIC, + 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 Aid; + + UINT8 TpcReqToken = RandomByte(pAd); + + Aid = (UINT) simple_strtol(arg, 0, 16); + + DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __FUNCTION__, Aid)); + if (!VALID_WCID(Aid)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, Aid)); + return TRUE; + } + + TpcReqInsert(pAd, TpcReqToken); + + EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].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; +} + + +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/mt7620/src/common/uapsd.c b/mt7620/src/common/uapsd.c new file mode 100644 index 0000000..7fe22be --- /dev/null +++ b/mt7620/src/common/uapsd.c @@ -0,0 +1,2410 @@ +/**************************************************************************** + * 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 function body. + + Two EOSP sent mechanism: + 1. Use DMA Done to do the check. + a. safe but not accuracy, because maybe all packets are still in hardware + DMA, not yet be sent to air, but DMA Done are all 1 + b. in USB chip, the data completion does not mean a packet is sent, it + means a block of data is sent, so we need to use another method to + know how many packets are sent in the data completion function + + 2. Use TX Statistics to do the check. + a. unsafe but accuracy, because too many traffic are sent before TX Done + Interrupt occurs and the statistics count will be overwrited. + b. management frames will not be counted + c. frames using 1Mbps (CCK) will no be counted + d. legacy ps frame sent after a PS-Poll frame is also be counted, we + need to handle the mix mode case: some AC are legacy PS and some AC + are UAPSD + e. in USB chip, only one statistics counter for all station entries; + so only use DMA Done mechanism in USB device; but in PCI chip, + one statistics counter for each station entries. + + All ACs have two UAPSD modes: + 1. Delivery-enabled + meaningful mode for AC in AP + + 2. Trigger-enabled + meaningful mode for AC in STA + + Only WMM ACM is used, we need to discriminate between Delivery-enabled and + Trigger-enabled AC, or all AC are Delivery/Trigger-enabled or not + Delivery/Trigger-enabled. + +***************************************************************************/ + +#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 +static VOID UAPSD_InsertTailQueueAc( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN QUEUE_HEADER *pQueueHeader, + IN QUEUE_ENTRY *pQueueEntry); +#endif /* VENDOR_FEATURE3_SUPPORT */ + + + + +/* +======================================================================== +Routine Description: + UAPSD Module Init. + +Arguments: + pAd Pointer to our adapter + +Return Value: + None + +Note: +======================================================================== +*/ +VOID UAPSD_Init( + IN PRTMP_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 */ +} /* End of UAPSD_Init */ + + +/* +======================================================================== +Routine Description: + UAPSD Module Release. + +Arguments: + pAd Pointer to our adapter + +Return Value: + None + +Note: +======================================================================== +*/ +VOID UAPSD_Release( + IN PRTMP_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( + IN PRTMP_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 */ +} /* End of RtmpAsicSleepHandle */ + + + +/* +======================================================================== +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( + IN PRTMP_ADAPTER pAd, + IN 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; + } /* End of if */ + + /* re-init SP related parameters */ + pEntry->UAPSDTxNum = 0; + //pEntry->bAPSDFlagSPStart = 0; + pEntry->bAPSDFlagEOSPOK = 0; + pEntry->bAPSDFlagLegacySent = 0; + UAPSD_SP_END(pAd, pEntry); + + } /* End of if */ + + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + } /* End of if */ +} /* End of UAPSD_SP_Close */ + +/* +======================================================================== +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( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry) +{ + BOOLEAN FlgIsSpClosed = TRUE; + + + RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock); + if ((pEntry != NULL) && (pEntry->PsMode == PWR_SAVE)) + { + if (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( + IN PRTMP_ADAPTER pAd, + IN 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; + } /* End of if */ + + UAPSD_INSERT_QUEUE_AC(pAd, pEntry, &pAd->TxSwQueue[QueId], + pEntry->pUAPSDEOSPFrame); + + pEntry->pUAPSDEOSPFrame = NULL; + pEntry->UAPSDTxNum = 0; + } /* End of if */ + + /* 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); + } /* End of while */ + } /* End of for */ + + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); +} /* End of UAPSD_AllPacketDeliver */ + + +/* +======================================================================== +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 PRTMP_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]; + + } /* End of for */ + + 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); + } /* End of if */ + + 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; + } /* End of if */ + + pEntry->VirtualTimeout = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("apsd> MaxSPLength = %d\n", pEntry->MaxSPLength)); + } /* End of if */ +} /* End of UAPSD_AssocParse */ + + +/* +======================================================================== +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(%ld) 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 = %ld)...\n", + (ULONG)pPacket, IdAc, + pQueUapsd->Number)); + } /* End of if */ +#endif /* UAPSD_DEBUG */ + } /* End of if */ +} /* End of UAPSD_PacketEnqueue */ + + +/* +======================================================================== +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 PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR *pDstMac) +{ + HEADER_802_11 *pHeader; + MAC_TABLE_ENTRY *pEntry; + INT_SOURCE_CSR_STRUC IntSrcReg; + + + /* sanity check */ + if (pPacket == NULL) + return; + /* End of if */ + + /* check if the packet is a U-APSD packet, must be QoS Null frame */ + if (RTMP_GET_PACKET_UAPSD_Flag(pPacket) != TRUE) + return; + /* End of if */ + + /* check if the packet sub type is QoS Null */ + if (pDstMac == NULL) + return; + /* End of if */ + + pHeader = (HEADER_802_11 *)pDstMac; + + /* find the destination STATION */ + pEntry = MacTableLookup(pAd, pHeader->Addr1); + + if ((pHeader->FC.Type == BTYPE_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 it */ + RELEASE_NDIS_PACKET(pAd, + QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame), + NDIS_STATUS_FAILURE); + pEntry->pUAPSDEOSPFrame = NULL; + } /* End of if */ + + pEntry->UAPSDTxNum = 0; + + /* check if rx done interrupt exists */ + RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSrcReg.word); + + if (IntSrcReg.field.RxDone == 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; + } /* End of if */ + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> close SP in QoSNullTxDoneHandle()!\n")); +#endif /* UAPSD_DEBUG */ + } /* End of if */ + + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + } + else if ((pHeader->FC.Type == BTYPE_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 management 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; + } /* End of if */ + + 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. + */ + } /* End of if */ + } /* End of if */ + + /* a UAPSD frame is transmitted so counter -- */ + pEntry->UAPSDTxNum --; + } + else + { + /* UAPSDTxNum == 0 so the packet is the EOSP packet */ + + if (pEntry->bAPSDFlagSPStart != 0) + { + INT_SOURCE_CSR_STRUC IntSrcReg; + + /* 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.word); + + if (IntSrcReg.field.RxDone == 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); + +#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; + } /* End of if */ + } /* End of if */ + } /* End of if */ + + 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! + */ +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pCookie->uapsd_eosp_sent_work); +#else + RTMP_OS_TASKLET_SCHE(&pCookie->uapsd_eosp_sent_task); +#endif /* WORKQUEUE_BH */ + + } /* End of if */ + } + else + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + /* End of if (pEntry != NULL) */ + } /* End of if */ +} /* End of UAPSD_QoSNullTxMgmtTxDoneHandle */ + + +/* +======================================================================== +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( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry) +{ + QUEUE_HEADER *pQue; + UINT32 IdAc; + BOOLEAN FlgUapsdPkt, FlgEospPkt; + + + /* sanity check */ + if (gUAPSD_FlgNotQueueMaintain) + return; + /* End of if */ + + if (pEntry->PsMode != PWR_SAVE) + return; /* UAPSD packet only for power-save STA, not active STA */ + /* End of if */ + + /* 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; + /* End of if */ + + /* 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")); + } /* End of if */ + + if (FlgEospPkt) + { + DBGPRINT(RT_DEBUG_TRACE, + ("uapsd> UAPSD EOSP timeout! clean the EOSP frame!\n")); + } /* End of if */ + + /* 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; + } /* End of if */ + + 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); + } /* End of if */ +#endif /* CONFIG_AP_SUPPORT */ + } /* End of if */ + + } + else + { + /* clear idle counter */ + pEntry->UAPSDQIdleCount = 0; + } /* End of if (FlgUapsdPkt) */ + + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + + /* virtual timeout handle */ + RTMP_PS_VIRTUAL_TIMEOUT_HANDLE(pEntry); +} /* End of UAPSD_QueueMaintenance */ + + +/* +======================================================================== +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; + /* End of if */ + + 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; + } /* End of if */ + + 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 */ + } /* End of if */ + +#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 */ + } /* End of if */ + + /* 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; + } /* End of if */ + + UAPSD_INSERT_QUEUE_AC(pAd, pEntry, &pAd->TxSwQueue[QueId], + pEntry->pUAPSDEOSPFrame); + + pEntry->pUAPSDEOSPFrame = NULL; + FlgEosp = TRUE; + } /* End of if */ + } /* End of if */ + + /* 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; + + 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! + */ +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pCookie->uapsd_eosp_sent_work); +#else + RTMP_OS_TASKLET_SCHE(&pCookie->uapsd_eosp_sent_task); +#endif /* WORKQUEUE_BH */ + } /* End of if */ + + /* 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; + } /* End of if */ + + 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 */ + } /* End of if */ + } /* End of if */ + + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + } /* End of if (pEntry != NULL) */ +#endif /* UAPSD_SP_ACCURATE */ +} /* End of UAPSD_SP_AUE_Handle */ + + + +/* +======================================================================== +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( + IN PRTMP_ADAPTER pAd) +{ + UINT32 IdEntry; + int FirstWcid = 0; + + + if (pAd->MacTab.fAnyStationInPsm == FALSE) + return; /* no any station is in power save mode */ + /* End of if */ + +#ifdef P2P_SUPPORT + FirstWcid = 2; +#endif /* 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 UAPSD_SP_CloseInRVDone()!\n\n\n")); +#endif /* UAPSD_DEBUG */ + + //pEntry->bAPSDFlagSPStart = 0; + pEntry->bAPSDFlagEOSPOK = 0; + pEntry->bAPSDFlagLegacySent = 0; + UAPSD_SP_END(pAd, pEntry); + } /* End of if */ + + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + } /* End of for */ +} /* End of UAPSD_SP_CloseInRVDone */ + + +/* +======================================================================== +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 PRTMP_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; + /* End of if */ +#endif /* RALINK_ATE */ + + /* sanity check */ + if (pPacket == NULL) + return; + /* End of if */ + + /* + 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; + /* End of if */ + + /* + 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; + } /* End of if */ + + pHeader = (HEADER_802_11 *)(pDstMac); + + if (pHeader != NULL) + { + if (((pHeader->FC.Type == BTYPE_DATA) && + (pHeader->FC.SubType == SUBTYPE_QOS_NULL)) || + ((pHeader->FC.Type == BTYPE_MGMT) && + (pHeader->FC.SubType == SUBTYPE_ACTION))) + { + /* the packet is a QoS NULL frame */ + UAPSD_QoSNullTxMgmtTxDoneHandle(pAd, pPacket, pDstMac); + return; + } /* End of if */ + + /* Addr1 = receiver address */ + pEntry = MacTableLookup(pAd, pHeader->Addr1); + } /* End of if */ + + 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; + } /* End of if */ + + 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. + */ + } /* End of if */ + } /* End of if */ + + /* 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) + { + INT_SOURCE_CSR_STRUC IntSrcReg; + + /* 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.word); + + if (IntSrcReg.field.RxDone == 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; + } /* End of if */ + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> close SP in SP_PacketCheck()!\n")); +#endif /* UAPSD_DEBUG */ + } /* End of if */ + } /* End of if */ + } /* End of if (pEntry != NULL) */ + + 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! + */ +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pCookie->uapsd_eosp_sent_work); +#else + RTMP_OS_TASKLET_SCHE(&pCookie->uapsd_eosp_sent_task); +#endif /* WORKQUEUE_BH */ + } /* End of if */ +} /* End of UAPSD_SP_PacketCheck */ + + +#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( + IN UINT32 Flag) +{ + if (gUAPSD_TimingFlag == UAPSD_TIMING_CTRL_SUSPEND) + return; + /* End of if */ + + gUAPSD_TimingFlag = Flag; +} /* End of UAPSD_TimingRecordCtrl */ + + +/* +======================================================================== +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( + IN PRTMP_ADAPTER pAd, + IN UINT32 Type) +{ + UINT32 Index; + + if (gUAPSD_TimingFlag == UAPSD_TIMING_CTRL_STOP) + return; + /* End of if */ + + if ((gUAPSD_TimingFlag == UAPSD_TIMING_CTRL_SUSPEND) && + (Type != UAPSD_TIMING_RECORD_TX2AIR)) + { + return; + } /* End of if */ + + 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(); + } /* End of if */ + 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; + } /* End of if */ + + /* ok, a record is finished; prepare to record the next one */ + gUAPSD_TimingIndexUapsd ++; + + if (gUAPSD_TimingIndexUapsd >= UAPSD_TIMING_RECORD_MAX) + gUAPSD_TimingIndexUapsd = 0; + /* End of if */ + + /* 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; + } /* End of switch */ +} /* End of UAPSD_TimingRecord */ + + +/* +======================================================================== +Routine Description: + Record the loop index for received packet handle. + +Arguments: + pAd Pointer to our adapter + LoopIndex The RxProcessed in APRxDoneInterruptHandle() + +Return Value: + None + +Note: +======================================================================== +*/ +VOID UAPSD_TimeingRecordLoopIndex( + IN UINT32 LoopIndex) +{ + gUAPSD_TimingLoopIndex = LoopIndex; +} /* End of UAPSD_TimeingRecordLoopIndex */ + +#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( + IN PRTMP_ADAPTER pAd, + IN 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; + + + /* sanity check */ + if (pEntry == NULL) + return FALSE; /* fatal error */ + /* End of if */ + + /* init */ + FlgQueEmpty = TRUE; + pAcSwQue = NULL; + pQuedPkt = NULL; + + /* sanity check */ + RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock); + + if (pEntry->bAPSDAllAC == 0) + { + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + return FALSE; /* not all AC are delivery-enabled */ + } /* End of if */ + + if (pEntry->bAPSDFlagSPStart != 0) + { + RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock); + return FALSE; /* its service period is not yet ended */ + } /* End of if */ + + /* 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; + /* End of if */ + + /* 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); + } /* End of if */ + } /* End of while */ + + if (pAcPsQue->Head != NULL) + { + /* still have packets in queue */ + FlgQueEmpty = FALSE; + break; + } /* End of if */ + } /* End of for */ + + 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); + } /* End of if */ + + UAPSD_INSERT_QUEUE_AC(pAd, pEntry, pAcSwQue, pQuedPkt); + } /* End of if */ + + /* 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); + } /* End of if */ +#endif /* CONFIG_AP_SUPPORT */ + } /* End of if */ + + /* 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) +{ + /* init */ + *pFlgIsAnyPktForBK = FALSE; + *pFlgIsAnyPktForBE = FALSE; + *pFlgIsAnyPktForVI = FALSE; + *pFlgIsAnyPktForVO = FALSE; + + /* sanity check */ + 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( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN 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 */ + } /* End of if */ + +#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; + } /* End of if */ +#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; + } /* End of if */ + + +#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; + /* End of if */ + + 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; + /* End of if */ + } /* End of if */ +#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 */ + /* End of if */ + + /* get the AC ID of incoming packet */ + AcQueId = MapUserPriorityToAccessCategory[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; + } /* End of if */ + + + /* 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; + /* End of for */ + + /* + 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; + /* End of if */ + + /* 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; + } /* End of if */ + } /* End of if */ + + /* count U-APSD packet number */ + TxPktNum ++; + + /* queue last U-APSD packet */ + if (pQuedPkt != NULL) + { + /* enqueue U-APSD packet to transmission 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); + } /* End of if */ + + /* 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; + /* End of if */ + + /* + 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); + } /* End of if */ + + /* backup its software queue pointer */ + pLastAcSwQue = pAcSwQue; + } /* End of while */ + + if (FlgQueEmpty == FALSE) + { + /* FlgQueEmpty will be FALSE only when TxPktNum >= SpMaxLen */ + break; + } /* End of if */ + } /* End of for */ + + /* + 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; + /* End of if */ + + /* + 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); + } /* End of if */ + } /* End of if */ + + //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 */ + } /* End of if */ + + /* + 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 */ + } /* End of if */ + +#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")); + } /* End of if */ +#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 */ + } /* End of if */ +#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); + } /* End of if */ +#endif /* CONFIG_AP_SUPPORT */ + } /* End of if */ + + /* 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 */ + } /* End of if */ + +#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); +} /* End of UAPSD_TriggerFrameHandle */ + + + + +#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); +} /* End of InsertTailQueueAc */ +#endif /* VENDOR_FEATURE3_SUPPORT */ + +#endif /* UAPSD_SUPPORT */ + +/* End of ap_uapsd.c */ diff --git a/mt7620/src/common/wapi.c b/mt7620/src/common/wapi.c new file mode 100644 index 0000000..33cbdba --- /dev/null +++ b/mt7620/src/common/wapi.c @@ -0,0 +1,1307 @@ +/* + *************************************************************************** + * 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].WepStatus; + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + cipher_mode = pAd->StaCfg.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].AuthMode == Ndis802_11AuthModeWAIPSK) + { + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeOpen; + pAd->ApCfg.MBSSID[apidx].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].AuthMode = Ndis802_11AuthModeOpen; + pAd->ApCfg.MBSSID[apidx].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->MSSIDDev != NULL) + { + PNET_DEV dev = pMbss->MSSIDDev; + + 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->AuthMode == Ndis802_11AuthModeWAICERT) + pConf->auth_mode = WAPI_AUTH_CERT; + else if (pMbss->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].DefaultKeyId = pAd->ApCfg.MBSSID[apidx].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].GroupKeyWepStatus, + apidx, + pAd->ApCfg.MBSSID[apidx].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->Aid)); + 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].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)) + { + NdisZeroMemory(tx_tsc, LEN_WAPI_TSC); + + /* Read IVEIV from Asic */ + offset = MAC_IVEIV_TABLE_BASE + (Wcid * HW_IVEIV_ENTRY_SIZE); + for (i=0 ; i < HW_IVEIV_ENTRY_SIZE; i++) + RTMP_IO_READ8(pAd, offset+i, &tx_tsc[i]); + + /* Read WAPI PM from Asic */ + offset = WAPI_PN_TABLE_BASE + (Wcid * WAPI_PN_ENTRY_SIZE); + for (i=0 ; i < WAPI_PN_ENTRY_SIZE; i++) + RTMP_IO_READ8(pAd, offset+i, &tx_tsc[HW_IVEIV_ENTRY_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->Aid)); + 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->Aid, CONST_WAPI_PN + 1, CONST_WAPI_PN); + else + AsicUpdateWCIDIVEIV(pAd, pEntry->Aid, CONST_WAPI_PN, CONST_WAPI_PN); + AsicUpdateWAPIPN(pAd, pEntry->Aid, CONST_WAPI_PN, CONST_WAPI_PN); + + /* Add Pair-wise key to Asic */ + AsicAddPairwiseKeyEntry( + pAd, + (UCHAR)pEntry->Aid, + &pEntry->PairwiseKey); + + /* update WCID attribute table and IVEIV table for this entry */ + AsicUpdateWcidAttributeEntry( + pAd, + pEntry->apidx, + pEntry->usk_id, + pEntry->PairwiseKey.CipherAlg, + (UCHAR)pEntry->Aid, + 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 */ + RTMP_ASIC_SHARED_KEY_TABLE(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/mt7620/src/common/wsc.c b/mt7620/src/common/wsc.c new file mode 100644 index 0000000..a5822ba --- /dev/null +++ b/mt7620/src/common/wsc.c @@ -0,0 +1,12072 @@ +/* + *************************************************************************** + * 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 + +char WSC_MSG_SIGNATURE[]={"RAWSCMSG"}; + +extern UCHAR WPS_OUI[]; +extern UCHAR RALINK_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 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].Bssid[0], sizeof(uuid_t.node)); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef P2P_SUPPORT + /* copy the Mac address as the value of node */ + if (apIdx >= MIN_NET_DEVICE_FOR_P2P_GO) + NdisMoveMemory(&uuid_t.node[0], &pAd->ApCfg.MBSSID[MAIN_MBSSID].Bssid[0], sizeof(uuid_t.node)); + else +#endif /* P2P_SUPPORT */ + 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); + + 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); +#ifdef WSC_V2_SUPPORT + WSC_TIMER_INIT(pAd, pWScControl, &pWScControl->WscSetupLockTimer, pWScControl->WscSetupLockTimerRunning, WscSetupLockTimeout); +#endif /* WSC_V2_SUPPORT */ + } + +#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); + +#ifdef P2P_SUPPORT + pWScControl = &pAd->ApCfg.MBSSID[MAIN_MBSSID].WscControl; + pWScControl->EntryIfIdx = MIN_NET_DEVICE_FOR_P2P_GO; + WscInitCommonTimers(pAd, pWScControl); + pWScControl->WscUpdatePortCfgTimerRunning = FALSE; + WSC_TIMER_INIT(pAd, pWScControl, &pWScControl->WscUpdatePortCfgTimer, pWScControl->WscUpdatePortCfgTimerRunning, WscUpdatePortCfgTimeout); + + pWScControl = &pAd->ApCfg.ApCliTab[MAIN_MBSSID].WscControl; + pWScControl->EntryIfIdx = MIN_NET_DEVICE_FOR_P2P_CLI; + WscInitCommonTimers(pAd, pWScControl); + WscInitClientTimers(pAd, pWScControl); +#endif /* P2P_SUPPORT */ + } +#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; +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx != BSS0) + CurOpMode = AP_MODE; +#endif /* P2P_SUPPORT */ +#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; +#ifdef P2P_SUPPORT + if (Elem->OpMode != OPMODE_STA) + CurOpMode = AP_MODE; +#endif /* P2P_SUPPORT */ +#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; + } + } + +#ifdef P2P_SUPPORT + if (P2P_GO_ON(pAd) && (pWpsCtrl->bWscTrigger == FALSE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Ignore this EAPOL_Start!\n")); + return; + } +#endif /* P2P_SUPPORT */ + + + 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", + pEntry->Addr[0], + pEntry->Addr[1], + pEntry->Addr[2], + pEntry->Addr[3], + pEntry->Addr[4], + pEntry->Addr[5])); + + /* 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, + pEntry->Addr[0], + pEntry->Addr[1], + pEntry->Addr[2], + pEntry->Addr[3], + pEntry->Addr[4], + pEntry->Addr[5])); + + /* 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; +#ifdef P2P_SUPPORT + if (Elem->OpMode != OPMODE_STA) + CurOpMode = AP_MODE; +#endif /* P2P_SUPPORT */ +#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].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) + { +#ifdef DPA_S + if (pWscControl->EntryIfIdx >= MIN_NET_DEVICE_FOR_P2P_CLI) + RtmpOSWrielessEventSend(pAdapter->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_WPS_START, NULL, NULL, 0); +#endif /* DPA_S */ + /* 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) + { +#ifdef DPA_S + if (pWscControl->EntryIfIdx >= MIN_NET_DEVICE_FOR_P2P_CLI) + RtmpOSWrielessEventSend(pAdapter->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_WPS_START, NULL, NULL, 0); +#endif /* DPA_S */ + /* 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) +#ifdef P2P_SUPPORT + /* + P2P doesn't need to check PBC overlapping. + */ + && (pWscControl->EntryIfIdx < MIN_NET_DEVICE_FOR_P2P_GO) +#endif /* P2P_SUPPORT */ + ) + { + /* + 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); + 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; +#ifdef DPA_S +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx >= MIN_NET_DEVICE_FOR_P2P_CLI) + RtmpOSWrielessEventSend(pAdapter->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_WPS_SESSION_OVERLAP, NULL, NULL, 0); + else +#endif /* P2P_SUPPORT */ +#endif /* DPA_S */ + RTMPSendWirelessEvent(pAdapter, IW_WSC_PBC_SESSION_OVERLAP, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + DBGPRINT(RT_DEBUG_TRACE, ("WscEAPAction: PBC Session Overlap!\n")); + WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_CTRL, WSC_UPNP_DATA_SUB_PBC_OVERLAP, + &pAdapter->ApCfg.MBSSID[pWscControl->EntryIfIdx].Bssid[0], MAC_ADDR_LEN, 0, 0, &pAdapter->CurrentAddress[0], AP_MODE); + + } + 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 (pWscControl->WscState >= WSC_STATE_WAIT_EAPFAIL) + { + pWscControl->WscState = WSC_STATE_OFF; +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (CurOpMode == AP_MODE) + { + pWscControl->WscConfMode = WSC_DISABLE; + +#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 */ +#ifdef P2P_SUPPORT + if (pWscControl->WscStatus == STATUS_WSC_CONFIGURED) + pAdapter->P2pCfg.WscState = WSC_STATE_CONFIGURED; +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT + P2pSendWirelessEvent(pAdapter, RT_P2P_WPS_COMPLETED, NULL, NULL); +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ +#endif /* P2P_SUPPORT */ + /* Bring apcli interface down first */ + if(pEntry && IS_ENTRY_APCLI(pEntry) && pAdapter->ApCfg.ApCliTab[BSS0].Enable == TRUE ) + { +#ifdef P2P_SUPPORT + UCHAR P2pIdx = P2pGroupTabSearch(pAdapter, pEntry->Addr); +#endif /* P2P_SUPPORT */ + pAdapter->ApCfg.ApCliTab[pEntry->apidx].Enable = FALSE; + ApCliIfDown(pAdapter); +#ifdef P2P_SUPPORT + if ((P2pIdx != P2P_NOT_FOUND) + && P2P_CLI_ON(pAdapter) + && ((pWscControl->WscStatus == STATUS_WSC_ERROR_DEV_PWD_AUTH_FAIL) || (pWscControl->WscStatus == STATUS_WSC_FAIL))) + { + pAdapter->P2pTable.Client[P2pIdx].P2pClientState = P2PSTATE_DISCOVERY; + P2pLinkDown(pAdapter, P2P_CONNECT_FAIL); + } +#endif /* P2P_SUPPORT */ + 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) + { + UINT32 rv = 0; + /* + 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); + rv = 1; + } +#ifdef CONFIG_AP_SUPPORT + if (((pWscControl->WscConfMode & WSC_PROXY) != 0) && (!bUPnPMsg) && (CurOpMode == AP_MODE)) + { + if ((pWscControl->bWscTrigger +#ifdef EASY_CONFIG_SETUP + || (pEntry && pEntry->bRaAutoWpsCapable) +#endif /* EASY_CONFIG_SETUP */ + ) + && (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 +#ifdef EASY_CONFIG_SETUP + || (pEntry && pEntry->bRaAutoWpsCapable) +#endif /* EASY_CONFIG_SETUP */ + ) && + 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 +#ifdef EASY_CONFIG_SETUP + || pAdapter->StaCfg.EasyConfigInfo.bDoAutoWps +#endif /* EASY_CONFIG_SETUP */ +#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 P2P_SUPPORT + if (P2P_CLI_ON(pAdapter) && (pWscControl->EntryIfIdx != BSS0)) + { + UCHAR P2pIdx = P2P_NOT_FOUND; + P2pIdx = P2pGroupTabSearch(pAdapter, MacAddr); + if (P2pIdx != P2P_NOT_FOUND) + { + PRT_P2P_CLIENT_ENTRY pP2pEntry = &pAdapter->P2pTable.Client[P2pIdx]; + + if (pP2pEntry && (pAdapter->P2pCfg.ConfigMethod == WSC_CONFMET_KEYPAD)) + { + /* + I am KeyPad. We cannot use ConfigMethod or DPID to check peer's capability. + Some P2P device is display but the value of ConfigMethod will be 0x0188 and (ex. Samsung GALAXYSII). + */ + bReadOwnPIN = FALSE; + } + } + } +#endif /* P2P_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 P2P_SUPPORT + /*RTMPCancelTimer(&pAdapter->P2pCfg.P2pWscTimer, &Cancelled);*/ + if (P2P_GO_ON(pAdapter) && pWscControl->EntryIfIdx != BSS0) + { + UCHAR P2pIdx = P2P_NOT_FOUND; + P2pIdx = P2pGroupTabSearch(pAdapter, MacAddr); + if (P2pIdx != P2P_NOT_FOUND) + { + PRT_P2P_CLIENT_ENTRY pP2pEntry = &pAdapter->P2pTable.Client[P2pIdx]; + // Update p2p Entry's state. + pP2pEntry->P2pClientState = P2PSTATE_CLIENT_WPS_DONE; + } + } + + // default set extended listening to zero for each connection. If this is persistent, will set it. + pAdapter->P2pCfg.ExtListenInterval = 0; + pAdapter->P2pCfg.ExtListenPeriod = 0; + if (IS_PERSISTENT_ON(pAdapter) && (pEntry->bP2pClient == TRUE)) + { + UCHAR P2pIdx = P2P_NOT_FOUND; + P2pIdx = P2pGroupTabSearch(pAdapter, pEntry->Addr); + + if (IS_P2P_GO_ENTRY(pEntry)) + DBGPRINT(RT_DEBUG_ERROR, ("pEntry is P2P GO.\n")); + else if (IS_P2P_CLI_ENTRY(pEntry)) + DBGPRINT(RT_DEBUG_ERROR, ("pEntry is P2P CLIENT.\n")); + else + DBGPRINT(RT_DEBUG_ERROR, ("pEntry is P2P NONE.\n")); + + if ((P2pIdx != P2P_NOT_FOUND) && (IS_P2P_GO_ENTRY(pEntry) || IS_P2P_CLI_ENTRY(pEntry))) + { + DBGPRINT(RT_DEBUG_ERROR, ("P2pWPSDone- Save to persistent entry. GrpCap= %x \n", pAdapter->P2pTable.Client[P2pIdx].GroupCapability)); + DBGPRINT(RT_DEBUG_ERROR, ("3. P2pWPSDone- Set Extended timing !!!!!!!\n")); + DBGPRINT(RT_DEBUG_ERROR, (" ======== Profile :: Cnt = %d ========\n", pWscControl->WscProfile.ProfileCnt)); + DBGPRINT(RT_DEBUG_ERROR, (" SSID[%d] = %s.\n", pWscControl->WscProfile.Profile[0].SSID.SsidLength, pWscControl->WscProfile.Profile[0].SSID.Ssid)); + DBGPRINT(RT_DEBUG_ERROR, (" AuthType = %d. EncrType = %d.\n", pWscControl->WscProfile.Profile[0].AuthType, pWscControl->WscProfile.Profile[0].EncrType)); + DBGPRINT(RT_DEBUG_ERROR, (" MAC = %02x:%02x:%02x:%02x:%02x:%02x.\n", PRINT_MAC(pWscControl->WscProfile.Profile[0].MacAddr))); + DBGPRINT(RT_DEBUG_ERROR, (" KeyLen = %d. KeyIdx = %d.\n", pWscControl->WscProfile.Profile[0].KeyLength, pWscControl->WscProfile.Profile[0].KeyIndex)); + DBGPRINT(RT_DEBUG_ERROR, (" Key :: %02x %02x %02x %02x %02x %02x %02x %02x\n", pWscControl->WscProfile.Profile[0].Key[0], pWscControl->WscProfile.Profile[0].Key[1], pWscControl->WscProfile.Profile[0].Key[2], + pWscControl->WscProfile.Profile[0].Key[3], pWscControl->WscProfile.Profile[0].Key[4], pWscControl->WscProfile.Profile[0].Key[5], pWscControl->WscProfile.Profile[0].Key[6], pWscControl->WscProfile.Profile[0].Key[7])); + DBGPRINT(RT_DEBUG_ERROR, (" %02x %02x %02x %02x %02x %02x %02x %02x\n", pWscControl->WscProfile.Profile[0].Key[8], pWscControl->WscProfile.Profile[0].Key[9], pWscControl->WscProfile.Profile[0].Key[10], + pWscControl->WscProfile.Profile[0].Key[11], pWscControl->WscProfile.Profile[0].Key[12], pWscControl->WscProfile.Profile[0].Key[13], pWscControl->WscProfile.Profile[0].Key[14], pWscControl->WscProfile.Profile[0].Key[15])); + + P2pPerstTabInsert(pAdapter, pEntry->Addr, &pWscControl->WscProfile.Profile[0]); + // this is a persistent connection. + pAdapter->P2pCfg.ExtListenInterval = P2P_EXT_LISTEN_INTERVAL; + pAdapter->P2pCfg.ExtListenPeriod = P2P_EXT_LISTEN_PERIOD; + } + } +#endif //P2P_SUPPORT // + } +#ifdef CONFIG_AP_SUPPORT + else if ((CurOpMode == AP_MODE) && + (pWscControl->WscState == WSC_STATE_WAIT_DONE) && + (pWscControl->WscConfStatus == WSC_SCSTATE_CONFIGURED) && + (pAdapter->ApCfg.MBSSID[apidx].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; + 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; + bssIdx = 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; +#ifdef P2P_SUPPORT + if (Elem->OpMode != OPMODE_STA) + CurOpMode = AP_MODE; +#endif /* P2P_SUPPORT */ +#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)); + +#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); + 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); + 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); + 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); + + 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 +#ifdef WSC_V2_SUPPORT + if ((CurOpMode == AP_MODE) && pWscControl->bSetupLock) + { + rv = WSC_ERROR_SETUP_LOCKED; + goto Fail; + } +#endif /* WSC_V2_SUPPORT */ +#endif /* CONFIG_AP_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 == AP_MODE) + { + bReplyNack = TRUE; +#ifdef APCLI_SUPPORT + if (pEntry && !IS_ENTRY_APCLI(pEntry)) + bReplyNack = TRUE; + else + bReplyNack = FALSE; +#endif +#ifdef P2P_SUPPORT + if (P2P_INF_ON(pAdapter)) + { + if (P2P_GO_ON(pAdapter)) + bReplyNack = TRUE; + else + bReplyNack = FALSE; + } +#endif + } + + if (bReplyNack) + { + /* For VISTA SP1 internal registrar test */ + OpCode |= WSC_OPCODE_NACK; + 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 +#ifdef WSC_V2_SUPPORT + if (CurOpMode == AP_MODE) + WscCheckPinAttackCount(pAdapter, pWscControl); +#endif /* WSC_V2_SUPPORT */ +#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 +#ifdef WSC_V2_SUPPORT + if (CurOpMode == AP_MODE) + WscCheckPinAttackCount(pAdapter, pWscControl); +#endif /* WSC_V2_SUPPORT */ +#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; + } +#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 */ + WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_CTRL, WSC_UPNP_DATA_SUB_M8, + &pAdapter->ApCfg.MBSSID[pWscControl->EntryIfIdx].Bssid[0], MAC_ADDR_LEN, 0, 0, &pAdapter->CurrentAddress[0], AP_MODE); + 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; +#ifdef P2P_SUPPORT + pAdapter->P2pCfg.WscState = WSC_STATE_CONFIGURED; +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT + P2pSendWirelessEvent(pAdapter, RT_P2P_WPS_COMPLETED, NULL, NULL); +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ +#endif /* P2P_SUPPORT */ + } + 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; +#ifdef P2P_SUPPORT + pAdapter->P2pCfg.WscState = WSC_STATE_CONFIGURED; +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT + P2pSendWirelessEvent(pAdapter, RT_P2P_WPS_COMPLETED, NULL, NULL); +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ +#endif /* P2P_SUPPORT */ + 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 +#ifdef WSC_V2_SUPPORT + if ((CurOpMode == AP_MODE) && pWscControl->bSetupLock) + rv = WSC_ERROR_SETUP_LOCKED; +#endif /* WSC_V2_SUPPORT */ +#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; +#ifdef DPA_S +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx >= MIN_NET_DEVICE_FOR_P2P_CLI) + RtmpOSWrielessEventSend(pAdapter->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_WPS_WRONG_PIN, NULL, NULL, 0); +#endif /* P2P_SUPPORT */ +#endif /* DPA_S */ + break; + default: + pWscControl->WscStatus = STATUS_WSC_FAIL; + break; + } +#ifdef DPA_S +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx >= MIN_NET_DEVICE_FOR_P2P_CLI) + RtmpOSWrielessEventSend(pAdapter->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_WPS_FAIL, NULL, NULL, 0); + else +#endif /* P2P_SUPPORT */ +#endif /* DPA_S */ + 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) + { +#ifdef P2P_SUPPORT + if (P2P_CLI_ON(pAdapter)) + pWscControl->WscState = WSC_STATE_WAIT_DISCONN; + else +#endif /* P2P_SUPPORT */ + 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; */ + + bUPnPStatus = FALSE; + } + +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 */ + + 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) +#ifdef WSC_V2_SUPPORT + || (pWscControl->WscV2Info.bEnableWpsV2 && ((CurOpMode == AP_MODE) && !pWscControl->bSetupLock)) +#endif /* WSC_V2_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + ) + { + 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 P2P_SUPPORT +#ifdef DPA_S + if (pWscControl->EntryIfIdx >= MIN_NET_DEVICE_FOR_P2P_CLI) + RtmpOSWrielessEventSend(pAdapter->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_WPS_COMPLETE, NULL, NULL, 0); +#endif /* DPA_S */ + /*RTMPCancelTimer(&pAdapter->P2pCfg.P2pWscTimer, &Cancelled);*/ + if (P2P_GO_ON(pAdapter) && (pWscControl->EntryIfIdx != BSS0) && pEntry) + { + UCHAR P2pIdx = P2P_NOT_FOUND; + P2pIdx = P2pGroupTabSearch(pAdapter, pEntry->Addr); + if (P2pIdx != P2P_NOT_FOUND) + { + PRT_P2P_CLIENT_ENTRY pP2pEntry = &pAdapter->P2pTable.Client[P2pIdx]; + // Update p2p Entry's state. + pP2pEntry->P2pClientState = P2PSTATE_CLIENT_WPS_DONE; + } + } + + // default set extended listening to zero for each connection. If this is persistent, will set it. + pAdapter->P2pCfg.ExtListenInterval = 0; + pAdapter->P2pCfg.ExtListenPeriod = 0; + if (IS_PERSISTENT_ON(pAdapter) && pEntry && (pEntry->bP2pClient == TRUE)) + { + UCHAR P2pIdx = P2P_NOT_FOUND; + P2pIdx = P2pGroupTabSearch(pAdapter, pEntry->Addr); + + if (IS_P2P_GO_ENTRY(pEntry)) + DBGPRINT(RT_DEBUG_ERROR, ("pEntry is P2P GO.\n")); + else if (IS_P2P_CLI_ENTRY(pEntry)) + DBGPRINT(RT_DEBUG_ERROR, ("pEntry is P2P CLIENT.\n")); + else + DBGPRINT(RT_DEBUG_ERROR, ("pEntry is P2P NONE.\n")); + + if ((P2pIdx != P2P_NOT_FOUND) && (IS_P2P_GO_ENTRY(pEntry) || IS_P2P_CLI_ENTRY(pEntry))) + { + DBGPRINT(RT_DEBUG_ERROR, ("P2pWPSDone- Save to persistent entry. GrpCap= %x \n", pAdapter->P2pTable.Client[P2pIdx].GroupCapability)); + DBGPRINT(RT_DEBUG_ERROR, ("2. P2pWPSDone- Set Extended timing !!!!!!!\n")); + DBGPRINT(RT_DEBUG_ERROR, (" ======== Profile :: Cnt = %d ========\n", pWscControl->WscProfile.ProfileCnt)); + DBGPRINT(RT_DEBUG_ERROR, (" SSID[%d] = %s.\n", pWscControl->WscProfile.Profile[0].SSID.SsidLength, pWscControl->WscProfile.Profile[0].SSID.Ssid)); + DBGPRINT(RT_DEBUG_ERROR, (" AuthType = %d. EncrType = %d.\n", pWscControl->WscProfile.Profile[0].AuthType, pWscControl->WscProfile.Profile[0].EncrType)); + DBGPRINT(RT_DEBUG_ERROR, (" MAC = %02x:%02x:%02x:%02x:%02x:%02x.\n", PRINT_MAC(pWscControl->WscProfile.Profile[0].MacAddr))); + DBGPRINT(RT_DEBUG_ERROR, (" KeyLen = %d. KeyIdx = %d.\n", pWscControl->WscProfile.Profile[0].KeyLength, pWscControl->WscProfile.Profile[0].KeyIndex)); + DBGPRINT(RT_DEBUG_ERROR, (" Key :: %02x %02x %02x %02x %02x %02x %02x %02x\n", pWscControl->WscProfile.Profile[0].Key[0], pWscControl->WscProfile.Profile[0].Key[1], pWscControl->WscProfile.Profile[0].Key[2], + pWscControl->WscProfile.Profile[0].Key[3], pWscControl->WscProfile.Profile[0].Key[4], pWscControl->WscProfile.Profile[0].Key[5], pWscControl->WscProfile.Profile[0].Key[6], pWscControl->WscProfile.Profile[0].Key[7])); + DBGPRINT(RT_DEBUG_ERROR, (" %02x %02x %02x %02x %02x %02x %02x %02x\n", pWscControl->WscProfile.Profile[0].Key[8], pWscControl->WscProfile.Profile[0].Key[9], pWscControl->WscProfile.Profile[0].Key[10], + pWscControl->WscProfile.Profile[0].Key[11], pWscControl->WscProfile.Profile[0].Key[12], pWscControl->WscProfile.Profile[0].Key[13], pWscControl->WscProfile.Profile[0].Key[14], pWscControl->WscProfile.Profile[0].Key[15])); + + P2pPerstTabInsert(pAdapter, pEntry->Addr, &pWscControl->WscProfile.Profile[0]); + // this is a persistent connection. + pAdapter->P2pCfg.ExtListenInterval = P2P_EXT_LISTEN_INTERVAL; + pAdapter->P2pCfg.ExtListenPeriod = P2P_EXT_LISTEN_PERIOD; + } + } +#endif //P2P_SUPPORT // + +#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) + { +#ifdef WAC_SUPPORT + if (pAdapter->StaCfg.EasyConfigInfo.bEnableWAC) + { + pAdapter->StaCfg.EasyConfigInfo.CurrentStatus = OFC_SUCCESS; + if (pAdapter->StaCfg.EasyConfigInfo.DoAutoWAC == 0x01) + pAdapter->StaCfg.EasyConfigInfo.DoAutoWAC = 0xFF; + } +#endif /* WAC_SUPPORT */ + 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); + /*#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)&& + (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 = kmalloc(WSC_MAX_DATA_LEN, GFP_ATOMIC)) == NULL) */ + 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; + WSC_UPNP_NODE_INFO *pWscUPnPInfo = &pWscControl->WscUPnPNodeInfo; + UINT MaxWscDataLen = WSC_MAX_DATA_LEN; + UCHAR CurOpMode = 0xFF; +#ifdef P2P_SUPPORT + BOOLEAN bReadOwnPIN = FALSE; +#endif /* P2P_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction Enter!\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; +#ifdef P2P_SUPPORT + if (Elem->OpMode != OPMODE_STA) + CurOpMode = AP_MODE; +#endif /* P2P_SUPPORT */ +#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 = kmalloc(WSC_MAX_DATA_LEN, GFP_ATOMIC)) == NULL) */ + 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; +#ifdef P2P_SUPPORT + /* + If own UI is limited UI, we need to use own PIN not PIN of Enrollee. + */ + if (P2P_GO_ON(pAdapter) && (pWscControl->EntryIfIdx != BSS0)) + { + if ((pAdapter->P2pCfg.ConfigMethod & WSC_CONFMET_KEYPAD) == 0) + bReadOwnPIN = TRUE; + } + if (bReadOwnPIN) + { + pWscControl->WscPinCodeLen = pWscControl->WscEnrolleePinCodeLen; + WscGetRegDataPIN(pAdapter, pWscControl->WscEnrolleePinCode, pWscControl); + } +#endif /* P2P_SUPPORT */ + +#ifdef EASY_CONFIG_SETUP + if (pEntry && pEntry->bRaAutoWpsCapable) + bSendM2D = FALSE; +#endif /* EASY_CONFIG_SETUP */ + + 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; + } + + 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 */ + 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 + (CurOpMode == AP_MODE) || +#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, WscData); + pWscControl->WscStatus = STATUS_WSC_EAP_M8_SENT; + /* Change the state to next one */ + pWscControl->WscState = WSC_STATE_WAIT_DONE; + /* + If APUT is Registra , + 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].Bssid[0], MAC_ADDR_LEN, 0, 0, &pAdapter->ApCfg.MBSSID[pWscControl->EntryIfIdx & 0x0F].Bssid[0], AP_MODE); + 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)) + 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)) + { + RTMP_SEM_LOCK(&pWscControl->WscPeerListSemLock); + WscDelListEntryByMAC(&pWscControl->WscPeerList, pEntry->Addr); + RTMP_SEM_UNLOCK(&pWscControl->WscPeerListSemLock); + } +#endif /* CONFIG_AP_SUPPORT */ + + } +#ifdef CONFIG_STA_SUPPORT + else if ((CurOpMode == STA_MODE) && + (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); + } +#endif /* CONFIG_STA_SUPPORT */ + } + } + 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) + { +#ifdef WAC_SUPPORT + if (pEntry && pAdapter->ApCfg.MBSSID[pWscControl->EntryIfIdx & 0x0F].EasyConfigInfo.bEnableWAC) + { + RTMP_SEM_LOCK(&pAdapter->ApCfg.MBSSID[pWscControl->EntryIfIdx & 0x0F].EasyConfigInfo.WAC_PeerListSemLock); + WscDelListEntryByMAC(&pAdapter->ApCfg.MBSSID[pWscControl->EntryIfIdx & 0x0F].EasyConfigInfo.WAC_PeerList, + pEntry->Addr); + RTMP_SEM_UNLOCK(&pAdapter->ApCfg.MBSSID[pWscControl->EntryIfIdx & 0x0F].EasyConfigInfo.WAC_PeerListSemLock); + } +#endif // WAC_SUPPORT // + pWscControl->WscStatus = STATUS_WSC_EAP_RAP_RSP_DONE_SENT; + /* Send EAP-Fail */ + WscSendEapFail(pAdapter, pWscControl, FALSE); + pWscControl->WscStatus = STATUS_WSC_CONFIGURED; +#ifdef P2P_SUPPORT + if (P2P_GO_ON(pAdapter) && + (pWscControl->WscConfStatus == WSC_SCSTATE_UNCONFIGURED) && + (pWscControl == &pAdapter->ApCfg.MBSSID[MAIN_MBSSID].WscControl)) + pAdapter->P2pCfg.bStopAuthRsp = TRUE; +#endif /* P2P_SUPPORT */ + } +#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); +#ifdef P2P_SUPPORT +#ifdef DPA_S + if (pWscControl->EntryIfIdx >= MIN_NET_DEVICE_FOR_P2P_CLI) + RtmpOSWrielessEventSend(pAdapter->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_WPS_COMPLETE, NULL, NULL, 0); +#endif /* DPA_S */ + /*RTMPCancelTimer(&pAdapter->P2pCfg.P2pWscTimer, &Cancelled);*/ + if (P2P_GO_ON(pAdapter) && pEntry && pWscControl->EntryIfIdx != BSS0) + { + UCHAR P2pIdx = P2P_NOT_FOUND; + P2pIdx = P2pGroupTabSearch(pAdapter, pEntry->Addr); + if (P2pIdx != P2P_NOT_FOUND) + { + PRT_P2P_CLIENT_ENTRY pP2pEntry = &pAdapter->P2pTable.Client[P2pIdx]; + // Update p2p Entry's state. + pP2pEntry->P2pClientState = P2PSTATE_CLIENT_WPS_DONE; + } + } + + // default set extended listening to zero for each connection. If this is persistent, will set it. + pAdapter->P2pCfg.ExtListenInterval = 0; + pAdapter->P2pCfg.ExtListenPeriod = 0; + pAdapter->P2pCfg.WscState = WSC_STATE_CONFIGURED; +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT + P2pSendWirelessEvent(pAdapter, RT_P2P_WPS_COMPLETED, NULL, NULL); +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ + if (IS_PERSISTENT_ON(pAdapter) && pEntry && (pEntry->bP2pClient == TRUE)) + { + UCHAR P2pIdx = P2P_NOT_FOUND; + P2pIdx = P2pGroupTabSearch(pAdapter, pEntry->Addr); + + if (IS_P2P_GO_ENTRY(pEntry)) + DBGPRINT(RT_DEBUG_ERROR, ("pEntry is P2P GO.\n")); + else if (IS_P2P_CLI_ENTRY(pEntry)) + DBGPRINT(RT_DEBUG_ERROR, ("pEntry is P2P CLIENT.\n")); + else + DBGPRINT(RT_DEBUG_ERROR, ("pEntry is P2P NONE[%d].\n", pEntry->EntryType)); + + if ((P2pIdx != P2P_NOT_FOUND) && (IS_P2P_GO_ENTRY(pEntry) || IS_P2P_CLI_ENTRY(pEntry))) + { + DBGPRINT(RT_DEBUG_ERROR, ("P2pWPSDone- Save to persistent entry. GrpCap= %x \n", pAdapter->P2pTable.Client[P2pIdx].GroupCapability)); + DBGPRINT(RT_DEBUG_ERROR, ("1. P2pWPSDone- Set Extended timing !!!!!!!\n")); + DBGPRINT(RT_DEBUG_ERROR, (" ======== Profile :: Cnt = %d ========\n", pWscControl->WscProfile.ProfileCnt)); + DBGPRINT(RT_DEBUG_ERROR, (" SSID[%d] = %s.\n", pWscControl->WscProfile.Profile[0].SSID.SsidLength, pWscControl->WscProfile.Profile[0].SSID.Ssid)); + DBGPRINT(RT_DEBUG_ERROR, (" AuthType = %x. EncrType = %x.\n", pWscControl->WscProfile.Profile[0].AuthType, pWscControl->WscProfile.Profile[0].EncrType)); + DBGPRINT(RT_DEBUG_ERROR, (" MAC = %02x:%02x:%02x:%02x:%02x:%02x.\n", PRINT_MAC(pWscControl->WscProfile.Profile[0].MacAddr))); + DBGPRINT(RT_DEBUG_ERROR, (" KeyLen = %d. KeyIdx = %d.\n", pWscControl->WscProfile.Profile[0].KeyLength, pWscControl->WscProfile.Profile[0].KeyIndex)); + DBGPRINT(RT_DEBUG_ERROR, (" Key :: %02x %02x %02x %02x %02x %02x %02x %02x\n", pWscControl->WscProfile.Profile[0].Key[0], pWscControl->WscProfile.Profile[0].Key[1], pWscControl->WscProfile.Profile[0].Key[2], + pWscControl->WscProfile.Profile[0].Key[3], pWscControl->WscProfile.Profile[0].Key[4], pWscControl->WscProfile.Profile[0].Key[5], pWscControl->WscProfile.Profile[0].Key[6], pWscControl->WscProfile.Profile[0].Key[7])); + DBGPRINT(RT_DEBUG_ERROR, (" %02x %02x %02x %02x %02x %02x %02x %02x\n", pWscControl->WscProfile.Profile[0].Key[8], pWscControl->WscProfile.Profile[0].Key[9], pWscControl->WscProfile.Profile[0].Key[10], + pWscControl->WscProfile.Profile[0].Key[11], pWscControl->WscProfile.Profile[0].Key[12], pWscControl->WscProfile.Profile[0].Key[13], pWscControl->WscProfile.Profile[0].Key[14], pWscControl->WscProfile.Profile[0].Key[15])); + + P2pPerstTabInsert(pAdapter, pEntry->Addr, &pWscControl->WscProfile.Profile[0]); + // this is a persistent connection. + pAdapter->P2pCfg.ExtListenInterval = P2P_EXT_LISTEN_INTERVAL; + pAdapter->P2pCfg.ExtListenPeriod = P2P_EXT_LISTEN_PERIOD; + } + } +#endif //P2P_SUPPORT // + 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) + WscSendMessage(pAdapter, OpCode, WscData, DataLen, pWscControl, AP_MODE, EAP_CODE_REQ); + } +#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; +#ifdef DPA_S +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx >= MIN_NET_DEVICE_FOR_P2P_CLI) + RtmpOSWrielessEventSend(pAdapter->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_WPS_WRONG_PIN, NULL, NULL, 0); +#endif /* P2P_SUPPORT */ +#endif /* DPA_S */ + } + 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; + } +#ifdef DPA_S +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx >= MIN_NET_DEVICE_FOR_P2P_CLI) + RtmpOSWrielessEventSend(pAdapter->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_WPS_FAIL, NULL, NULL, 0); + else +#endif /* P2P_SUPPORT */ +#endif /* DPA_S */ + 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; */ + bUPnPStatus = FALSE; + } + + 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 */ + + 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 + { + if (CurOpMode == AP_MODE) + { + 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 WAC_SUPPORT + if (pAdapter->ApCfg.MBSSID[pWscControl->EntryIfIdx & 0x0F].EasyConfigInfo.bEnableWAC) + { + pAdapter->ApCfg.MBSSID[pWscControl->EntryIfIdx & 0x0F].EasyConfigInfo.CurrentStatus = OFC_SUCCESS; + } +#endif /* WAC_SUPPORT */ + + } + } + 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) + { + { + /* + 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->Aid, 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; +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx != BSS0) + CurOpMode = AP_MODE; +#endif /* P2P_SUPPORT */ +#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); +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx & MIN_NET_DEVICE_FOR_P2P_GO) + { +#ifdef RTMP_MAC_PCI + OS_WAIT(1000); +#endif /* RTMP_MAC_PCI */ + P2P_GoStop(pAd); + P2P_GoStartUp(pAd, MAIN_MBSSID); + } + else +#endif /* P2P_SUPPORT */ + { + 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; + + 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 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; +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx != BSS0) + CurOpMode = AP_MODE; +#endif /* P2P_SUPPORT */ +#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 = kmalloc(WSC_MAX_DATA_LEN, GFP_ATOMIC))!= NULL) */ + 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 >= 2) +#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 >= 2) + 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 >= 2) + 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 >= 2) + 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 >= 2) + WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_M3, pWscControl); + else + { + if (pWscControl->WscActionMode == WSC_REGISTRAR) + { + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_MODE, EAP_CODE_REQ); +#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 >= 2) + 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 >= 2) + WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_M5, pWscControl); + else + { + if (pWscControl->WscActionMode == WSC_REGISTRAR) + { + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_MODE, EAP_CODE_REQ); +#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 >= 2) + 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 >= 2) + WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_M7, pWscControl); + else + { + if (pWscControl->WscActionMode == WSC_REGISTRAR) + { + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_MODE, EAP_CODE_REQ); +#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 >= 2) + 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) + WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_MODE, EAP_CODE_REQ); +#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; +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx != BSS0) + CurOpMode = AP_MODE; +#endif /* P2P_SUPPORT */ +#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) + { + 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 */ + + 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); + + WscSendUPnPMessage(pAd, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_CTRL, WSC_UPNP_DATA_SUB_WSC_TIMEOUT, + &pAd->ApCfg.MBSSID[pWscControl->EntryIfIdx].Bssid[0], MAC_ADDR_LEN, 0, 0, &pAd->CurrentAddress[0], AP_MODE); + 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->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; +#ifdef WAC_SUPPORT + pAd->StaCfg.EasyConfigInfo.bWACAP = FALSE; +#endif /* WAC_SUPPORT */ + } +#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. */ +#ifdef CONFIG_WIFI_LED_SHARE + || (LED_MODE(pAd) == WPS_LED_MODE_SHARE) +#endif /* CONFIG_WIFI_LED_SHARE */ + ) + { + 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); +#ifdef CONFIG_WIFI_LED_SHARE + if(LED_MODE(pAd) == WPS_LED_MODE_SHARE) + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_WPS_FAIL_WIFI_LED_TIMEOUT); + else +#endif /* CONFIG_WIFI_LED_SHARE */ + /* 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); +#ifdef CONFIG_WIFI_LED_SHARE + if(LED_MODE(pAd) == WPS_LED_MODE_SHARE) + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_WPS_FAIL_WIFI_LED_TIMEOUT); + else +#endif /* CONFIG_WIFI_LED_SHARE */ + + /* 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 */ + } + +#ifdef DPA_S +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx >= MIN_NET_DEVICE_FOR_P2P_CLI) + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_WPS_TIMEOUT, NULL, NULL, 0); +#endif /* P2P_SUPPORT */ +#endif /* DPA_S */ + + 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; +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx != BSS0) + { + CurOpMode = AP_MODE; + apidx = MAIN_MBSSID; + } +#endif /* P2P_SUPPORT */ +#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].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 */ + 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 ((pAdapter->CommonCfg.PhyMode == PHY_11A) + || (pAdapter->CommonCfg.PhyMode == PHY_11ABG_MIXED) +#ifdef DOT11_N_SUPPORT + || (pAdapter->CommonCfg.PhyMode == PHY_11AN_MIXED) + || (pAdapter->CommonCfg.PhyMode == PHY_11ABGN_MIXED) + || (pAdapter->CommonCfg.PhyMode == PHY_11AGN_MIXED) +#endif /* DOT11_N_SUPPORT */ + ) + pWscControl->RegData.SelfInfo.RfBand |= WSC_RFBAND_50GHZ; /* 5.0G */ + + if ((pAdapter->CommonCfg.PhyMode != PHY_11A) +#ifdef DOT11_N_SUPPORT + && (pAdapter->CommonCfg.PhyMode != PHY_11AN_MIXED) +#endif /* DOT11_N_SUPPORT */ + ) + 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) + { +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx >= MIN_NET_DEVICE_FOR_P2P_CLI) + { + NdisMoveMemory(&pWscControl->RegData.SelfInfo.PriDeviceType, pAdapter->P2pCfg.DevInfo.PriDeviceType, 8); + } + else +#endif /* P2P_SUPPORT */ + 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].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) */ +/* pOutBuffer = kmalloc(MAX_LEN_OF_MLME_BUFFER, MEM_ALLOC_FLAG); */ + 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) +/* kfree(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].CurrentAddress[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; +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx != BSS0) + CurOpMode = AP_MODE; +#endif /* P2P_SUPPORT */ +#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].CurrentAddress[0], + EAPOL); + Length = sizeof(EAP_FRAME) + sizeof(enrIdentity) - 1; + pWscControl->WscConfMode = WSC_ENROLLEE; /* Ap Client only support Enrollee now. 20070518 */ + } +#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) */ +/* pOutBuffer = kmalloc(MAX_LEN_OF_MLME_BUFFER, MEM_ALLOC_FLAG); */ + os_alloc_mem(NULL, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER); + if(pOutBuffer == NULL) + return; + + FrameLen = 0; + + if (pWscControl->WscConfMode == WSC_REGISTRAR) + { + /* Make Transmitting 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) +/* kfree(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 P2P_SUPPORT + return; +#endif /* P2P_SUPPORT */ + +#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; +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx != BSS0) + CurOpMode = AP_MODE; +#endif /* P2P_SUPPORT */ +#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}; + +#ifdef P2P_SUPPORT + if (apIdx >= MIN_NET_DEVICE_FOR_P2P_CLI) + return 0; +#endif /* P2P_SUPPORT */ + + 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 totalLen, leftLen, copyLen; + PUCHAR pBuf = NULL, pBufPtr = NULL, pPos = NULL; + PUCHAR pDevAddr = NULL; +#ifdef CONFIG_AP_SUPPORT + UCHAR bssIdx = devIfIdx; +#endif /* CONFIG_AP_SUPPORT */ + ULONG Now; + +#ifdef P2P_SUPPORT + if (devIfIdx >= MIN_NET_DEVICE_FOR_P2P_CLI) + return 0; +#endif /* P2P_SUPPORT */ + + 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].CurrentAddress[0]; + } + else +#endif /* APCLI_SUPPORT */ + pDevAddr = &pAd->ApCfg.MBSSID[bssIdx].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. */ + totalLen = leftLen = pNLMsgHdr->msgLen; + pPos = pData; + os_alloc_mem(NULL, (UCHAR **)&pBuf, IWEVCUSTOM_MSG_MAX_LEN); +/* if((pBuf = kmalloc(IWEVCUSTOM_MSG_MAX_LEN, GFP_ATOMIC)) != NULL) */ + 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)); + } + +/* kfree(pBuf); */ + 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; +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx != BSS0) + CurOpMode = AP_MODE; +#endif /* P2P_SUPPORT */ +#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].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].CurrentAddress[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) + 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; +#ifdef EASY_CONFIG_SETUP + UCHAR VendorExt[32] = {0}, MIC[16] = {0}; +#endif /* EASY_CONFIG_SETUP */ + + + /* 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 +#ifdef WSC_V2_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 /* WSC_V2_SUPPORT */ +#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 ((pAd->CommonCfg.PhyMode == PHY_11A) +#ifdef DOT11_N_SUPPORT + || (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) +#endif /* DOT11_N_SUPPORT */ + ) + 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 */ + +#ifdef EASY_CONFIG_SETUP + /* + Only main bssid supports auto provision. + */ + +#ifdef CONFIG_AP_SUPPORT + if ((pAd->ApCfg.MBSSID[MAIN_MBSSID].EasyConfigInfo.bEnable == TRUE) && + (apidx == MAIN_MBSSID)) +#endif /* CONFIG_AP_SUPPORT */ + { + /* + WPS Vendor Extension Value: Ralink OUI + MIC + */ + NdisMoveMemory(VendorExt, RALINK_OUI, 3); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + WpsCalculateMIC(pAd, &Data[0], Len, &pAd->ApCfg.MBSSID[apidx].EasyConfigInfo, pAd->ApCfg.MBSSID[apidx].Bssid, MIC); +#endif /* CONFIG_AP_SUPPORT */ + NdisMoveMemory(VendorExt + 3, MIC, LEN_KEY_DESC_MIC); + /* + WPS Vendor Extension + */ + templen = AppendWSCTLV(WSC_ID_VENDOR_EXT, pData, (UINT8 *)VendorExt, 3 + LEN_KEY_DESC_MIC); + pData += templen; + Len += templen; + } +#endif /* EASY_CONFIG_SETUP */ + +#ifdef P2P_SUPPORT + // 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, &pAd->P2pCfg.DeviceName, pAd->P2pCfg.DeviceNameLen); + pData += templen; + Len += templen; +#endif /* P2P_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; +#ifdef EASY_CONFIG_SETUP + UCHAR VendorExt[32] = {0}, MIC[16] = {0}; +#endif /* EASY_CONFIG_SETUP */ + + + /* 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 +#ifdef WSC_V2_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 /* WSC_V2_SUPPORT */ +#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); */ +#ifdef P2P_SUPPORT + /* + Some P2P Device will check this config method for PBC. (ex. Samsung GALAXYSII) + If this config method doesn't include PBC, some P2P Device doesn't send provision request if we are P2P GO. + */ + if (apidx >= MIN_NET_DEVICE_FOR_P2P_GO) + if (pAd->P2pCfg.bSigmaEnabled) + tempVal = pWpsCtrl->WscConfigMethods & 0xff7f; + else + tempVal = pWpsCtrl->WscConfigMethods; + else +#endif /* P2P_SUPPORT */ + { + /* + 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 ((pAd->CommonCfg.PhyMode == PHY_11A) +#ifdef DOT11_N_SUPPORT + || (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) +#endif /* DOT11_N_SUPPORT */ + ) + 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 */ + +#ifdef EASY_CONFIG_SETUP +#ifdef CONFIG_AP_SUPPORT + /* + Only main bssid supports auto provision. + */ + if ((pAd->ApCfg.MBSSID[apidx & 0x0F].EasyConfigInfo.bEnable == TRUE) && ((apidx & 0xF) == MAIN_MBSSID)) +#endif /* CONFIG_AP_SUPPORT */ + { + /* + WPS Vendor Extension Value: Ralink OUI + MIC + */ + NdisMoveMemory(VendorExt, RALINK_OUI, 3); + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + WpsCalculateMIC(pAd, &Data[0], Len, &pAd->ApCfg.MBSSID[apidx & 0xF].EasyConfigInfo, pAd->ApCfg.MBSSID[apidx & 0xF].Bssid, MIC); +#endif /* CONFIG_AP_SUPPORT */ + + NdisMoveMemory(VendorExt + 3, MIC, LEN_KEY_DESC_MIC); + /* + WPS Vendor Extension + */ + templen = AppendWSCTLV(WSC_ID_VENDOR_EXT, pData, (UINT8 *)VendorExt, 3 + LEN_KEY_DESC_MIC); + pData += templen; + Len += templen; + } +#endif /* EASY_CONFIG_SETUP */ + + 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; +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx != BSS0) + CurOpMode = AP_MODE; +#endif /* P2P_SUPPORT */ +#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].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) */ +/* pOutBuffer = kmalloc(MAX_LEN_OF_MLME_BUFFER, MEM_ALLOC_FLAG); */ + 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) +/* kfree(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; +#ifdef EASY_CONFIG_SETUP + UCHAR ExtData[4] = {0}; +#endif /* EASY_CONFIG_SETUP */ + + 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 */ + +#ifdef EASY_CONFIG_SETUP + /* + Only main bssid supports auto provision. + */ + if ((pAd->ApCfg.MBSSID[MAIN_MBSSID].EasyConfigInfo.bEnable == TRUE) && (ApIdx == MAIN_MBSSID)) + { + /* WPS Vendor Extension */ + NdisMoveMemory(ExtData, RALINK_OUI, 3); + ExtData[3] = Reason; + templen = AppendWSCTLV(WSC_ID_VENDOR_EXT, pData, &ExtData[0], 4); + pData += templen; + Len += templen; + } +#endif /* EASY_CONFIG_SETUP */ + + 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 */ + +//#ifdef CONFIG_STA_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 PWSC_CTRL pWscControl, + IN UCHAR CurOpMode, + OUT PUCHAR pOutBuf, + OUT PUCHAR pIeLen) +{ + WSC_IE_HEADER ieHdr; + UCHAR *OutMsgBuf = NULL; /* buffer to create message contents */ + INT Len =0, templen = 0; + PUCHAR pData; + USHORT tempVal = 0; + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData; +#ifdef IWSC_SUPPORT + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pWscControl->pAd; +#endif // IWSC_SUPPORT // + + if (pWscControl == NULL) + { + DBGPRINT(RT_DEBUG_INFO, ("%s: -----> pWscControl == NULL\n", __FUNCTION__)); + return; + } + + 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 */ + if (pWscControl->WscConfMode == WSC_REGISTRAR) + tempVal = WSC_MSGTYPE_REGISTRAR; + else if (pWscControl->WscConfMode == WSC_ENROLLEE) + tempVal = WSC_MSGTYPE_ENROLLEE_OPEN_8021X; + else + tempVal = WSC_MSGTYPE_ENROLLEE_INFO_ONLY; + + templen = AppendWSCTLV(WSC_ID_REQ_TYPE, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + + /* 3. Config method */ +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + if (pWscControl->bWscTrigger) + { + if (pWscControl->WscMode == WSC_PIN_MODE) + { + tempVal = (pWscControl->WscConfigMethods & 0x200F); + } + else + { + tempVal = (pWscControl->WscConfigMethods & 0x02F0); + } + } + else + { + tempVal = pWscControl->WscConfigMethods; + } + } + else +#endif /* WSC_V2_SUPPORT */ + { + tempVal = (pWscControl->WscConfigMethods & 0x00FF); + } + +#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 + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* 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 */ + 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), 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; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pWscControl->pAd; + 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; +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx != BSS0) + CurOpMode = AP_MODE; +#endif /* P2P_SUPPORT */ +#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; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + CurOpMode = STA_MODE; +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx != BSS0) + CurOpMode = AP_MODE; +#endif /* P2P_SUPPORT */ +#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); + } + + if (pWscControl->WscUpdatePortCfgTimerRunning) + { + pWscControl->WscUpdatePortCfgTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->WscUpdatePortCfgTimer, &Cancelled); + } + + RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); + pWscControl->EapolTimerRunning = FALSE; +#ifdef CONFIG_AP_SUPPORT +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscSetupLockTimerRunning) + { + pWscControl->WscSetupLockTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->WscSetupLockTimer, &Cancelled); + } +#endif /* WSC_V2_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); + } +#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 CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { +#ifdef APCLI_SUPPORT + if (!bFromApCli) +#endif /* APCLI_SUPPORT */ + { + pAd->ApCfg.MBSSID[apidx].WscIEBeacon.ValueLen = 0; + pAd->ApCfg.MBSSID[apidx].WscIEProbeResp.ValueLen = 0; + } + } +#endif /* CONFIG_AP_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; + INT band = 0; + + if (RFIC_IS_5G_BAND(pAd)) + band = 0; + else + band = 1; + + pOpposAd = (PRTMP_ADAPTER) pAdGlobalList[band]; + + if (bFromApCli) + { + pWpsCtrl = &pOpposAd->ApCfg.ApCliTab[BSS0].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("CON_WPS: Stop the Band[%d] ApCli WPS, state [%d]\n", + band, 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", band)); + 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; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef P2P_SUPPORT + if (BssIndex >= MIN_NET_DEVICE_FOR_P2P_GO) + { + pWscControl = &pAd->ApCfg.MBSSID[MAIN_MBSSID].WscControl; + } + else if (bFromApCli) + { + pWscControl = &pAd->ApCfg.ApCliTab[MAIN_MBSSID].WscControl; + } + else +#endif /* P2P_SUPPORT */ + { + 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 */ + { +#ifdef P2P_SUPPORT + if (pWscControl->WscConfMode == WSC_DISABLE) + { + if (BssIndex >= MIN_NET_DEVICE_FOR_P2P_GO) + { + pAd->ApCfg.MBSSID[MAIN_MBSSID].WscIEBeacon.ValueLen = 0; + pAd->ApCfg.MBSSID[MAIN_MBSSID].WscIEProbeResp.ValueLen = 0; + } + return; + } +#endif /* P2P_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 */ + } +} + +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_11Encryption2Enabled: + return WSC_ENCRTYPE_TKIP; + case Ndis802_11Encryption4Enabled: + return (WSC_ENCRTYPE_AES | WSC_ENCRTYPE_TKIP); + default: + case Ndis802_11Encryption3Enabled: + 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_11Encryption2Enabled; + default: + case (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES): + return Ndis802_11Encryption4Enabled; + case WSC_ENCRTYPE_AES: + return Ndis802_11Encryption3Enabled; + } +} + +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; +#ifdef P2P_SUPPORT + if (P2P_GO_ON(pAd)) + { + NdisZeroMemory(pAd->P2pCfg.SSID, MAX_LEN_OF_SSID); + pAd->P2pCfg.SSIDLen = pCredential->SSID.SsidLength; + NdisMoveMemory(pAd->P2pCfg.SSID, pCredential->SSID.Ssid, pAd->P2pCfg.SSIDLen); + } +#endif /* P2P_SUPPORT */ + } +#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].DefaultKeyId = 1; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + pAd->StaCfg.DefaultKeyId = 0; +#endif /* CONFIG_STA_SUPPORT */ + + if (pCredential->KeyLength >= 8 && pCredential->KeyLength <= 64) + { + UCHAR *pPMKBuf = NULL, *pSSIDStr = NULL; + INT ssidLen = 0; + + pWscControl->WpaPskLen = pCredential->KeyLength; + RTMPZeroMemory(pWscControl->WpaPsk, 64); + RTMPMoveMemory(pWscControl->WpaPsk, 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; + } +#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].DefaultKeyId = WepKeyId; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + pAd->StaCfg.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].DefaultKeyId = 0; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + pAd->StaCfg.DefaultKeyId = 0; +#endif /* CONFIG_STA_SUPPORT */ + + } + } + } +#ifdef CONFIG_AP_SUPPORT + } + else + { + if (CurOpMode == AP_MODE) + { + pAd->ApCfg.MBSSID[CurApIdx].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 PRTMP_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; + + if ((strcmp(arg, "WEPAUTO") == 0) || (strcmp(arg, "wepauto") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeAutoSwitch; + else if ((strcmp(arg, "OPEN") == 0) || (strcmp(arg, "open") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeOpen; + else if ((strcmp(arg, "SHARED") == 0) || (strcmp(arg, "shared") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeShared; + else if ((strcmp(arg, "WPAPSK") == 0) || (strcmp(arg, "wpapsk") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPAPSK; + else if ((strcmp(arg, "WPA") == 0) || (strcmp(arg, "wpa") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPA; + else if ((strcmp(arg, "WPA2PSK") == 0) || (strcmp(arg, "wpa2psk") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPA2PSK; + else if ((strcmp(arg, "WPA2") == 0) || (strcmp(arg, "wpa2") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPA2; + else if ((strcmp(arg, "WPA1WPA2") == 0) || (strcmp(arg, "wpa1wpa2") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPA1WPA2; + else if ((strcmp(arg, "WPAPSKWPA2PSK") == 0) || (strcmp(arg, "wpapskwpa2psk") == 0)) + pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPA1PSKWPA2PSK; + else + { + pAd->ApCfg.MBSSID[apidx].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].PortSecured = WPA_802_1X_PORT_NOT_SECURED; + /*RTMPMakeRSNIE(pAd, pAd->ApCfg.MBSSID[apidx].AuthMode, pAd->ApCfg.MBSSID[apidx].WepStatus, apidx); */ + + pAd->ApCfg.MBSSID[apidx].DefaultKeyId = 0; + + if(pAd->ApCfg.MBSSID[apidx].AuthMode >= Ndis802_11AuthModeWPA) + pAd->ApCfg.MBSSID[apidx].DefaultKeyId = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) %s::(AuthMode=%d)\n", apidx, __FUNCTION__, pAd->ApCfg.MBSSID[apidx].AuthMode)); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + if (strcmp(arg, "WEPAUTO") == 0) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeAutoSwitch; + else if (strcmp(arg, "OPEN") == 0) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + else if (strcmp(arg, "SHARED") == 0) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeShared; + else if (strcmp(arg, "WPAPSK") == 0) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK; + else if (strcmp(arg, "WPANONE") == 0) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPANone; + else if ((strcmp(arg, "WPA2PSK") == 0) || (strcmp(arg, "WPAPSKWPA2PSK") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK; +#ifdef WPA_SUPPLICANT_SUPPORT + else if (strcmp(arg, "WPA") == 0) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA; + else if ((strcmp(arg, "WPA2") == 0) || (strcmp(arg, "WPA1WPA2") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA2; +#endif /* WPA_SUPPLICANT_SUPPORT */ + else + return FALSE; + + if ((pAd->StaCfg.BssType == BSS_ADHOC) && (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) + { + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPANone; + } + + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + DBGPRINT(RT_DEBUG_TRACE, ("WscSetAuthMode::(AuthMode=%d)\n", pAd->StaCfg.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) + { + + if ((strcmp(arg, "NONE") == 0) || (strcmp(arg, "none") == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11WEPDisabled; + else if ((strcmp(arg, "WEP") == 0) || (strcmp(arg, "wep") == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11WEPEnabled; + else if ((strcmp(arg, "TKIP") == 0) || (strcmp(arg, "tkip") == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11Encryption2Enabled; + else if ((strcmp(arg, "AES") == 0) || (strcmp(arg, "aes") == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11Encryption3Enabled; + else if ((strcmp(arg, "TKIPAES") == 0) || (strcmp(arg, "tkipaes") == 0)) + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11Encryption4Enabled; + else + { + pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11WEPDisabled; + DBGPRINT(RT_DEBUG_TRACE, ("%s: Unknow EncrypType (%s), set EncrypType to NONE\n", __FUNCTION__, arg)); + } + + if (pAd->ApCfg.MBSSID[apidx].WepStatus >= Ndis802_11Encryption2Enabled) + pAd->ApCfg.MBSSID[apidx].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__, pAd->ApCfg.MBSSID[apidx].WepStatus)); + + return TRUE; +} +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + if (strcmp(arg, "NONE") == 0) + { + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; /* do nothing */ + + pAd->StaCfg.WepStatus = Ndis802_11WEPDisabled; + pAd->StaCfg.PairCipher = Ndis802_11WEPDisabled; + pAd->StaCfg.GroupCipher = Ndis802_11WEPDisabled; + } + else if (strcmp(arg, "WEP") == 0) + { + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; /* do nothing */ + + pAd->StaCfg.WepStatus = Ndis802_11WEPEnabled; + pAd->StaCfg.PairCipher = Ndis802_11WEPEnabled; + pAd->StaCfg.GroupCipher = Ndis802_11WEPEnabled; + } + else if (strcmp(arg, "TKIP") == 0) + { + if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA) + return TRUE; /* do nothing */ + + pAd->StaCfg.WepStatus = Ndis802_11Encryption2Enabled; + pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; + pAd->StaCfg.GroupCipher = Ndis802_11Encryption2Enabled; + } + else if ((strcmp(arg, "AES") == 0) || (strcmp(arg, "TKIPAES") == 0)) + { + if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA) + return TRUE; /* do nothing */ + + pAd->StaCfg.WepStatus = Ndis802_11Encryption3Enabled; + pAd->StaCfg.PairCipher = Ndis802_11Encryption3Enabled; + pAd->StaCfg.GroupCipher = Ndis802_11Encryption3Enabled; + } + else + return FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("WscSetEncrypType::(EncrypType=%d)\n", pAd->StaCfg.WepStatus)); + } +#endif /* CONFIG_STA_SUPPORT */ + + return TRUE; +} + +#ifdef CONFIG_STA_SUPPORT +USHORT WscGetAuthTypeFromStr( + IN PSTRING arg) +{ + if ((strcmp(arg, "OPEN") == 0) || (strcmp(arg, "open") == 0)) + return WSC_AUTHTYPE_OPEN; + else if ((strcmp(arg, "SHARED") == 0) || (strcmp(arg, "shared") == 0)) + return WSC_AUTHTYPE_SHARED; + else if ((strcmp(arg, "WPAPSK") == 0) || (strcmp(arg, "wpapsk") == 0)) + return WSC_AUTHTYPE_WPAPSK; + else if ((strcmp(arg, "WPA2PSK") == 0) || (strcmp(arg, "wpa2psk") == 0)) + return WSC_AUTHTYPE_WPA2PSK; +#ifdef WPA_SUPPLICANT_SUPPORT + else if ((strcmp(arg, "WPA") == 0) || (strcmp(arg, "wpa") == 0)) + return WSC_AUTHTYPE_WPA; + else if ((strcmp(arg, "WPA2") == 0) || (strcmp(arg, "wpa2") == 0)) + return WSC_AUTHTYPE_WPA2; +#endif /* WPA_SUPPLICANT_SUPPORT */ + else + return 0; +} + +USHORT WscGetEncrypTypeFromStr( + IN PSTRING arg) +{ + if ((strcmp(arg, "NONE") == 0) || (strcmp(arg, "none") == 0)) + return WSC_ENCRTYPE_NONE; + else if ((strcmp(arg, "WEP") == 0) || (strcmp(arg, "wep") == 0)) + return WSC_ENCRTYPE_WEP; + else if ((strcmp(arg, "TKIP") == 0) || (strcmp(arg, "tkip") == 0)) + return WSC_ENCRTYPE_TKIP; + else if ((strcmp(arg, "AES") == 0) || (strcmp(arg, "aes") == 0)) + 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 */ + +#ifdef DPA_S +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx >= MIN_NET_DEVICE_FOR_P2P_CLI) + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_WPS_STATUS_SCANNING, NULL, NULL, 0); +#endif /* P2P_SUPPORT */ +#endif /* DPA_S */ +} + +/* + ======================================================================== + + 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; +#ifdef DPA_S +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx >= MIN_NET_DEVICE_FOR_P2P_CLI) + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_WPS_SESSION_OVERLAP, NULL, NULL, 0); + else +#endif /* P2P_SUPPORT */ +#endif /* DPA_S */ + 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); +#ifdef CONFIG_WIFI_LED_SHARE + if (LED_MODE(pAd) == WPS_LED_MODE_SHARE) + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_WPS_OVERLAP_WIFI_LED_TIMEOUT); +#endif /* CONFIG_WIFI_LED_SHARE */ + + + } +#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 + FALSE, +#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].CurrentAddress, + MAC_ADDR_LEN); + + snprintf(ChStr, sizeof(ChStr), "%d", pAd->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( + PRTMP_ADAPTER pAd, + PWSC_CTRL pWscControl, + PBSS_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 PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl) +{ + INT i; + PBSS_ENTRY pInBss; +/* UUID_BSSID_CH_INFO ApUuidBssid[8]; */ + UUID_BSSID_CH_INFO *ApUuidBssid = NULL; + BOOLEAN rv = FALSE; + 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 APCLI_SUPPORT +if (CurOpMode == AP_MODE) + pWscControl = &pAd->ApCfg.ApCliTab[BSS0].WscControl; +#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)); + pWscControl->WscPBCBssCount = 0; + for (i = 0; i < pAd->ScanTab.BssNr; i++) + { + /* BSS entry for VarIE processing */ + pInBss = (PBSS_ENTRY) &pAd->ScanTab.BssEntry[i]; + + /* 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); + } + } + + 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); +#endif /* CONFIG_STA_SUPPORT */ + pAd->MlmeAux.Channel = ApUuidBssid[0].Channel; + +#ifdef APCLI_SUPPORT + if (CurOpMode == AP_MODE) + { + NdisZeroMemory(pAd->ApCfg.ApCliTab[BSS0].CfgSsid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->ApCfg.ApCliTab[BSS0].CfgSsid, ApUuidBssid[0].Ssid, ApUuidBssid[0].SsidLen); + pAd->ApCfg.ApCliTab[BSS0].CfgSsidLen = (UCHAR)ApUuidBssid[0].SsidLen; + } +#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].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; + 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].WepStatus == Ndis802_11Encryption2Enabled) + encyType = WSC_ENCRTYPE_TKIP; + if (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11Encryption3Enabled) + encyType = WSC_ENCRTYPE_AES; + } + } + else + { + authType = WscGetAuthType(pAd->ApCfg.MBSSID[apidx].AuthMode); + encyType = WscGetEncryType(pAd->ApCfg.MBSSID[apidx].WepStatus); + } + WepKeyId = pAd->ApCfg.MBSSID[apidx].DefaultKeyId; + } +#ifdef APCLI_SUPPORT + else if (OpMode == AP_CLIENT_MODE) + { + apidx = apidx & 0x0F; + authType = WscGetAuthType(pAd->ApCfg.ApCliTab[apidx].AuthMode); + encyType = WscGetEncryType(pAd->ApCfg.ApCliTab[apidx].WepStatus); + WepKeyId = pAd->ApCfg.ApCliTab[apidx].DefaultKeyId; + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + authType = WscGetAuthType(pAd->StaCfg.AuthMode); + encyType = WscGetEncryType(pAd->StaCfg.WepStatus); + WepKeyId = pAd->StaCfg.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 == 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].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 == 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].Ssid, pAd->ApCfg.ApCliTab[apidx].SsidLen); + pCredential->SSID.SsidLength = pAd->ApCfg.ApCliTab[apidx].SsidLen; + } +#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, ("AuthType: %d, EncrType: %d\n", 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->DefaultKeyId = 0; + + if (pCredential->KeyLength >= 8 && pCredential->KeyLength <= 64) + { + pWscControl->WpaPskLen = (INT) pCredential->KeyLength; + NdisZeroMemory(pWscControl->WpaPsk, 64); + NdisMoveMemory(pWscControl->WpaPsk, pCredential->Key, pWscControl->WpaPskLen); + RT_CfgSetWPAPSKKey(pAd, (PSTRING) pCredential->Key, 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->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->DefaultKeyId = WepKeyId = 0; + } + } + } + } + + if (pWscControl->WscProfile.ProfileCnt > 1) + { + pWscControl->WscProfileRetryTimerRunning = TRUE; + RTMPSetTimer(&pWscControl->WscProfileRetryTimer, WSC_PROFILE_RETRY_TIME_OUT); + } + +#ifdef P2P_SUPPORT + if (P2P_CLI_ON(pAd)) + { + NdisZeroMemory(pAd->P2pCfg.SSID, MAX_LEN_OF_SSID); + pAd->P2pCfg.SSIDLen = pCredential->SSID.SsidLength; + NdisMoveMemory(pAd->P2pCfg.SSID, pCredential->SSID.Ssid, pAd->P2pCfg.SSIDLen); + } +#endif /* P2P_SUPPORT */ + + 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].CurrentAddress, + 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].CurrentAddress, 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; + } +#ifdef P2P_SUPPORT + if (Elem->OpMode == OPMODE_AP) + CurOpMode = AP_MODE; +#endif /* P2P_SUPPORT */ +#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 +INT WscGetConfWithoutTrigger( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl, + IN BOOLEAN bFromUPnP) +{ + INT WscMode; + INT IsAPConfigured; + PWSC_UPNP_NODE_INFO pWscUPnPNodeInfo; + UCHAR apIdx; + +#ifdef LINUX +#ifdef RTMP_RBUS_SUPPORT +/* +++ added by YYHuang@Ralink, 08/03/12 */ +/* + Notify user space application that WPS procedure will begin. +*/ + { +#define WSC_SINGLE_TRIGGER_APPNAME "goahead" + + struct task_struct *p; + read_lock(&tasklist_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)) + send_sig(SIGXFSZ, p, 0); + } + read_unlock(&tasklist_lock); + } +/* --- 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; + pWscUPnPNodeInfo = &pWscControl->WscUPnPNodeInfo; + + 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; + + 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].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) +#ifdef P2P_SUPPORT + || (P2P_CLI_ON(pAdapter)) +#endif /* P2P_SUPPORT */ + ) + ) + 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; +} + +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) +{ + 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] && + 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 (NdisEqualMemory(pMacAddr, pWscStaPbcProbeInfo->StaMacAddr[tab_idx], MAC_ADDR_LEN)) + { + 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) || + NdisEqualMemory(pWscStaPbcProbeInfo->StaMacAddr[tab_idx], &ZERO_MAC_ADDR[0], MAC_ADDR_LEN)) + { + if (pWscStaPbcProbeInfo->Valid[tab_idx] == FALSE) + { + Index = tab_idx; + bAddEntry = TRUE; + break; + } + else + { + pWscStaPbcProbeInfo->ReciveTime[tab_idx] = now; + NdisMoveMemory(pWscStaPbcProbeInfo->StaMacAddr[tab_idx], pMacAddr, MAC_ADDR_LEN); + return; + } + } + } + } + + if (bAddEntry) + { + pWscStaPbcProbeInfo->WscPBCStaProbeCount++; + pWscStaPbcProbeInfo->ReciveTime[Index] = now; + pWscStaPbcProbeInfo->Valid[Index] = TRUE; + NdisMoveMemory(pWscStaPbcProbeInfo->StaMacAddr[Index], pMacAddr, MAC_ADDR_LEN); + } +} + +void WscWriteConfToDatFile( + IN PRTMP_ADAPTER pAd, + IN 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].DefaultKeyId+1, apidx+1); + snprintf((PSTRING) WepKeyFormatName, sizeof(WepKeyFormatName), "Key%dType=", pAd->ApCfg.MBSSID[apidx].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.DefaultKeyId+1); + snprintf(WepKeyFormatName, sizeof(WepKeyFormatName), "Key%dType=", pAd->StaCfg.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 kmalloc 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 kmalloc 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 kmalloc fail. (512)\n")); + RtmpOSFileClose(file_w); + goto WriteErr; + } + + for (;;) + { + int i = 0; + PSTRING ptr; + BOOLEAN bNewFormat = TRUE; + + 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) || + 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, 512); + if (pAd->StaCfg.BssType == BSS_ADHOC) + snprintf(pTempStr, 512, "NetworkType=Adhoc"); + else + snprintf(pTempStr, 512, "NetworkType=Infra"); + } +#endif /* CONFIG_STA_SUPPORT */ + else if (strncmp(pTempStr, "AuthMode=", strlen("AuthMode=")) == 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].AuthMode)); + else + snprintf(pTempStr, 512, "%s;%s", pTempStr, RTMPGetRalinkAuthModeStr(pAd->ApCfg.MBSSID[index].AuthMode)); + } + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + USHORT auth_flag = WscGetAuthType(pAd->StaCfg.AuthMode); + snprintf(pTempStr, 512, "%s%s", pTempStr, WscGetAuthTypeStr(auth_flag)); + } +#endif /* CONFIG_STA_SUPPORT */ + } + else if (strncmp(pTempStr, "EncrypType=", strlen("EncrypType=")) == 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].WepStatus)); + else + snprintf(pTempStr, 512, "%s;%s", pTempStr, RTMPGetRalinkEncryModeStr(pAd->ApCfg.MBSSID[index].WepStatus)); + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + USHORT encrypt_flag = WscGetEncryType(pAd->StaCfg.WepStatus); + snprintf(pTempStr, 512, "%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, 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); + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + snprintf(pTempStr, 512, "%s%d", pTempStr, pWscControl->WscConfMode); +#endif /* CONFIG_STA_SUPPORT */ + } + else if (strncmp(pTempStr, "WscConfStatus=", strlen("WscConfStatus=")) == 0) + { + 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); + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + snprintf(pTempStr, 512, "%s%d", pTempStr, pWscControl->WscConfStatus); +#endif /* CONFIG_STA_SUPPORT */ + } + else if (strncmp(pTempStr, "DefaultKeyID=", strlen("DefaultKeyID=")) == 0) + { + NdisZeroMemory(pTempStr, 512); + snprintf(pTempStr, 512, "DefaultKeyID="); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { + if (index == 0) + snprintf(pTempStr, 512, "%s%d", pTempStr, pAd->ApCfg.MBSSID[index].DefaultKeyId+1); + else + snprintf(pTempStr, 512, "%s;%d", pTempStr, pAd->ApCfg.MBSSID[index].DefaultKeyId+1); + } + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + snprintf(pTempStr, 512, "%s%d", pTempStr, pAd->StaCfg.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].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, 512); + NdisMoveMemory(pTempStr, WepKeyFormatName, strlen(WepKeyFormatName)); + for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++) + { + if (idx == apidx) + snprintf(pTempStr, 512, "%s0", pTempStr); + else + snprintf(pTempStr, 512, "%s%d", pTempStr, KeyType[idx]); + + if (apidx < (pAd->ApCfg.BssidNum - 1)) + snprintf(pTempStr, 512, "%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].WepStatus == Ndis802_11WEPEnabled) + { + NdisZeroMemory(pTempStr, 512); + 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, 512, "%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.WepStatus == Ndis802_11WEPEnabled) + { + NdisZeroMemory(pTempStr, 512); + snprintf(pTempStr, 512, "%s0", WepKeyFormatName); /* Hex */ + } + } + else if (rtstrstr(pTempStr, (PSTRING) WepKeyName) && (CurOpMode == STA_MODE)) + { + pCredentail = &pWscControl->WscProfile.Profile[pWscControl->WscProfile.ApplyProfileIdx]; + if (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) + { + NdisZeroMemory(pTempStr, 512); + 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, 512, "%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) +/* kfree(pTempStr); */ + os_free_mem(NULL, pTempStr); +ReadErr: +WriteFileOpenErr: + if (cfgData) +/* kfree(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].DefaultKeyId+1); + snprintf((PSTRING) WepKeyFormatName, sizeof(WepKeyFormatName), "Key%dType=", pAd->ApCfg.MBSSID[MAIN_MBSSID].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 kmalloc fail. (512)\n")); + RtmpOSFileClose(file_w); + goto WriteErr; + } + os_alloc_mem(NULL, (UCHAR **)&pDatStr, 4096); + if (!pDatStr) + { + DBGPRINT(RT_DEBUG_TRACE, ("pDatStr kmalloc 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].AuthMode)); + else + snprintf(pTempStr, 512, "%s;%s", pTempStr, RTMPGetRalinkAuthModeStr(pAd->ApCfg.MBSSID[index].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].WepStatus)); + else + snprintf(pTempStr, 512, "%s;%s", pTempStr, RTMPGetRalinkEncryModeStr(pAd->ApCfg.MBSSID[index].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].DefaultKeyId+1); + else + snprintf(pTempStr, 512, "%s;%d", pTempStr, pAd->ApCfg.MBSSID[apidx].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].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].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) +/* kfree(pTempStr); */ + os_free_mem(NULL, pTempStr); + if (pDatStr) +/* kfree(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) +#ifdef P2P_SUPPORT + /* P2P will use ApCfg.MBSSID and ApCfg.ApCliTab also. */ + || TRUE +#endif /* P2P_SUPPORT */ + ) + { + 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->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 WAC_SUPPORT + WscClearPeerList(&pAd->ApCfg.MBSSID[ap_idx].EasyConfigInfo.WAC_PeerList); + NdisFreeSpinLock(&pAd->ApCfg.MBSSID[ap_idx].EasyConfigInfo.WAC_PeerListSemLock); +#ifdef WAC_QOS_PRIORITY + WscClearPeerList(&pAd->ApCfg.MBSSID[ap_idx].EasyConfigInfo.WAC_ForcePriorityList); + NdisFreeSpinLock(&pAd->ApCfg.MBSSID[ap_idx].EasyConfigInfo.WAC_ForcePriorityListSemLock); +#endif /* WAC_QOS_PRIORITY */ +#endif /* WAC_SUPPORT */ + } +#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. */ + { + +#ifdef CONFIG_WIFI_LED_SHARE + case LED_WPS_PRE_STAGE: + WPSLEDStatus = LED_WPS_IN_PROCESS; + break; + case LED_WPS_POST_STAGE: + WPSLEDStatus = LED_WPS_TURN_LED_OFF; + break; +#endif /* CONFIG_WIFI_LED_SHARE */ + + /* Turn off the blue LED after 300 seconds. */ + case LED_WPS_SUCCESS: +#ifdef CONFIG_WIFI_LED_SHARE + if (LED_MODE(pAd) == WPS_LED_MODE_SHARE) + { + WPSLEDStatus = LED_WPS_POST_STAGE; + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_WPS_PREPOST_WIFI_LED_TIMEOUT); + } + else +#endif /* CONFIG_WIFI_LED_SHARE */ + 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: +#ifdef CONFIG_WIFI_LED_SHARE + if (LED_MODE(pAd) == WPS_LED_MODE_SHARE) + { + WPSLEDStatus = LED_WPS_POST_STAGE; + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_WPS_PREPOST_WIFI_LED_TIMEOUT); + } + else +#endif /* CONFIG_WIFI_LED_SHARE */ + 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: +#ifdef CONFIG_WIFI_LED_SHARE + if (LED_MODE(pAd) == WPS_LED_MODE_SHARE) + { + WPSLEDStatus = LED_WPS_POST_STAGE; + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_WPS_PREPOST_WIFI_LED_TIMEOUT); + }else +#endif /* CONFIG_WIFI_LED_SHARE */ + 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->AuthMode && + WscGetWepStatus(pCredential->EncrType) == pMbss->WepStatus && + NdisEqualMemory(pMbss->Ssid, pCredential->SSID.Ssid, pMbss->SsidLen) && + 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; +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx & MIN_NET_DEVICE_FOR_P2P_GO) + { +#ifdef RTMP_MAC_PCI + OS_WAIT(1000); +#endif /* RTMP_MAC_PCI */ + P2P_GoStop(pAd); + P2P_GoStartUp(pAd, MAIN_MBSSID); + } + else +#endif /* P2P_SUPPORT */ + { + 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); + DBGPRINT(RT_DEBUG_TRACE, ("%s : DevicePasswordID = 0x%04x\n", __FUNCTION__, 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) +#ifdef P2P_SUPPORT + || P2P_GO_ON(pAd) +#endif /* P2P_SUPPORT */ + ) + { + 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].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 */ + + 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, ("PeerProbeReqSanity : Add this peer: %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(Fr->Hdr.Addr2))); + } + RTMP_SEM_UNLOCK(&pWscCtrl->WscConfiguredPeerListSemLock); + DBGPRINT(RT_DEBUG_TRACE, ("PeerProbeReqSanity : PeerConfigMethod = 0x%04x\n", 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; +} +#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/mt7620/src/common/wsc_tlv.c b/mt7620/src/common/wsc_tlv.c new file mode 100644 index 0000000..a070bea --- /dev/null +++ b/mt7620/src/common/wsc_tlv.c @@ -0,0 +1,4352 @@ +/* + *************************************************************************** + * 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) +{ +#ifdef CONFIG_STA_SUPPORT + /* Point to M7 Profile */ + PWSC_PROFILE pProfile = (PWSC_PROFILE) &pAdapter->StaCfg.WscControl.WscM7Profile; + UCHAR *pTmp; + USHORT Idx = 0, tmpVal = 0; +#endif /* CONFIG_STA_SUPPORT */ + USHORT WscType, WscLen, HmacLen; + PUCHAR pData; + UCHAR Hmac[8], Temp[32]; + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData; + + 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 */ + NdisMoveMemory(pReg->Es1, pData, WscLen); + break; + + case WSC_ID_E_SNONCE2: + /* for verification with our enrollee nonce */ + NdisMoveMemory(pReg->Es2, pData, WscLen); + break; + + case WSC_ID_R_SNONCE1: + /* for verification with our enrollee nonce */ + NdisMoveMemory(pReg->Rs1, pData, WscLen); + break; + + case WSC_ID_R_SNONCE2: + /* for verification with our enrollee nonce */ + NdisMoveMemory(pReg->Rs2, pData, WscLen); + break; + + case WSC_ID_KEY_WRAP_AUTH: + NdisMoveMemory(Hmac, pData, WscLen); + break; + +#ifdef CONFIG_STA_SUPPORT + /* */ + /* 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; + } + 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 (!MAC_ADDR_EQUAL(pData, pAdapter->StaCfg.WscControl.RegData.SelfInfo.MacAddr)) + DBGPRINT(RT_DEBUG_TRACE, ("WscParseEncrSettings --> Enrollee macAddr not match\n")); + RTMPMoveMemory(pProfile->Profile[0].MacAddr, pData, 6); + break; + + case WSC_ID_AUTH_TYPE: + tmpVal = get_unaligned((PUSHORT) pData); + pProfile->Profile[0].AuthType = cpu2be16(tmpVal);/*cpu2be16(*((PUSHORT) pData)); */ + break; + + case WSC_ID_ENCR_TYPE: + tmpVal = get_unaligned((PUSHORT) pData); + pProfile->Profile[0].EncrType = cpu2be16(tmpVal);/*cpu2be16(*((PUSHORT) pData)); */ + break; + + case WSC_ID_NW_KEY_INDEX: + /* Netork Key Index: 1 ~ 4 */ + pProfile->Profile[0].KeyIndex = (*pData); + break; + + case WSC_ID_NW_KEY: + if (WscLen == 0) + break; + pProfile->Profile[0].KeyLength = WscLen; + RTMPMoveMemory(pProfile->Profile[0].Key, pData, pProfile->Profile[0].KeyLength); + break; +#endif /* CONFIG_STA_SUPPORT */ + + 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 */ + 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 + + ======================================================================== +*/ +static BOOLEAN WscProcessCredential( + 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, 64); + 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 */ + +} + +/* + ======================================================================== + + 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; +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx != BSS0) + CurOpMode = AP_MODE; +#endif /* P2P_SUPPORT */ +#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) + { + /* + AP MUST NOT support using PBC to add an external Registrar + */ + if (CurOpMode == AP_MODE) + { + ConfigMethods = (pWscControl->WscConfigMethods & 0x200F); + } +#ifdef IWSC_SUPPORT + if ((CurOpMode == STA_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 */ + 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) +{ + UCHAR TB[1]; + 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); + 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); + 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 */ + 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); + + /* 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 */ + if (pReg->PinCodeLen == 4) + RT_HMAC_SHA256(pReg->AuthKey, 32, pReg->PIN, 2, TB, SHA256_DIGEST_SIZE); + else + RT_HMAC_SHA256(pReg->AuthKey, 32, pReg->PIN, 4, TB, SHA256_DIGEST_SIZE); + + /* 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 */ + if (pReg->PinCodeLen == 4) + RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[2], 2, TB, SHA256_DIGEST_SIZE); + else + RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[4], 4, TB, SHA256_DIGEST_SIZE); + + /* 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 */ + if (pReg->PinCodeLen == 4) + RT_HMAC_SHA256(pReg->AuthKey, 32, pReg->PIN, 2, TB, SHA256_DIGEST_SIZE); + else + RT_HMAC_SHA256(pReg->AuthKey, 32, pReg->PIN, 4, TB, SHA256_DIGEST_SIZE); + + /* 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 */ + if (pReg->PinCodeLen == 4) + RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[2], 2, TB, SHA256_DIGEST_SIZE); + else + RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[4], 4, TB, SHA256_DIGEST_SIZE); + + /* 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; +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx != BSS0) + CurOpMode = AP_MODE; +#endif /* P2P_SUPPORT */ +#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, + 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; +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx != BSS0) + CurOpMode = AP_MODE; +#endif /* P2P_SUPPORT */ +#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) + { + WscCreateProfileFromCfg(pAdapter, REGISTRAR_ACTION | AP_MODE, pWscControl, &pWscControl->WscProfile); + pCredential = &pAdapter->ApCfg.MBSSID[apidx].WscControl.WscProfile.Profile[0]; + } +#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 (pWscControl->RegData.PeerInfo.Version2 == 0) + { + 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; +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx != BSS0) + CurOpMode = AP_MODE; +#endif /* P2P_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + pReg->PeerInfo.Version2 = 0; + + DH_Len = 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); + + 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)); + 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); */ +#ifdef CONFIG_STA_SUPPORT + if (CurOpMode == STA_MODE) + { + /* 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; + } +#endif /* CONFIG_STA_SUPPORT */ + 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 EASY_CONFIG_SETUP + AutoProvisionDecodeExtData(pAdapter, (pWscControl->EntryIfIdx & 0x0F), &pWscControl->EntryAddr[0], pData); +#endif /* EASY_CONFIG_SETUP */ +#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}; + MAC_TABLE_ENTRY *pEntry = NULL; + 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; +#ifdef P2P_SUPPORT + if (pWscControl->EntryIfIdx != BSS0) + CurOpMode = AP_MODE; +#endif /* P2P_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + + 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; + + pEntry = MacTableLookup(pAdapter, pReg->PeerInfo.MacAddr); + + 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 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)); + 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; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2 --> Unknown IE 0x%04x\n", WscType)); + break; + } + + NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerMAC, &pWscControl->RegData.PeerInfo.MacAddr, 6); + + /* Offset to net WSC Ie */ + pData += WscLen; + Length -= WscLen; + } + + + DH_Len = 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); + + /* 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); + + /* 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/mt7620/src/common/wsc_ufd.c b/mt7620/src/common/wsc_ufd.c new file mode 100644 index 0000000..e59f5ed --- /dev/null +++ b/mt7620/src/common/wsc_ufd.c @@ -0,0 +1,593 @@ +/* + *************************************************************************** + * 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 PRTMP_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/mt7620/src/common/wsc_v2.c b/mt7620/src/common/wsc_v2.c new file mode 100644 index 0000000..227af17 --- /dev/null +++ b/mt7620/src/common/wsc_v2.c @@ -0,0 +1,414 @@ +/* + *************************************************************************** + * 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++; + } +} + +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) +#ifdef P2P_SUPPORT + || (pWscControl->EntryIfIdx & MIN_NET_DEVICE_FOR_P2P_CLI) +#endif /* P2P_SUPPORT */ + ) + { + /* + 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 */ + +/* + 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/mt7620/src/cp_module.sh b/mt7620/src/cp_module.sh new file mode 100755 index 0000000..8010db5 --- /dev/null +++ b/mt7620/src/cp_module.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +logfile="UTIL/os/linux/Module.symvers" + +if [ -e $logfile ]; then + cp -f MODULE/os/linux/Module.symvers NETIF/os/linux/. +fi +echo + +exit 0 \ No newline at end of file diff --git a/mt7620/src/cp_util.sh b/mt7620/src/cp_util.sh new file mode 100755 index 0000000..9f1fc20 --- /dev/null +++ b/mt7620/src/cp_util.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +logfile="UTIL/os/linux/Module.symvers" + +if [ -e $logfile ]; then + cp -f UTIL/os/linux/Module.symvers MODULE/os/linux/. +fi +echo + +exit 0 \ No newline at end of file diff --git a/mt7620/src/include/action.h b/mt7620/src/include/action.h new file mode 100644 index 0000000..4922e74 --- /dev/null +++ b/mt7620/src/include/action.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-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 + Paul Lin 04-06-15 Initial +*/ + +#ifndef __ACTION_H__ +#define __ACTION_H__ + +typedef struct GNU_PACKED __HT_INFO_OCTET { +#ifdef RT_BIG_ENDIAN + UCHAR Reserved:5; + UCHAR STA_Channel_Width:1; + UCHAR Forty_MHz_Intolerant:1; + UCHAR Request:1; +#else + UCHAR Request:1; + UCHAR Forty_MHz_Intolerant:1; + UCHAR STA_Channel_Width:1; + UCHAR Reserved:5; +#endif +} HT_INFORMATION_OCTET; + +typedef struct GNU_PACKED __FRAME_HT_INFO { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + HT_INFORMATION_OCTET HT_Info; +} FRAME_HT_INFO, *PFRAME_HT_INFO; + +#endif /* __ACTION_H__ */ diff --git a/mt7620/src/include/ags.h b/mt7620/src/include/ags.h new file mode 100644 index 0000000..1b1e2b6 --- /dev/null +++ b/mt7620/src/include/ags.h @@ -0,0 +1,96 @@ +/**************************************************************************** + * 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[]; + + +#define AGS_TX_QUALITY_WORST_BOUND 8 + +/* The size, in bytes, of an AGS entry in the rate switch table */ +#define SIZE_OF_AGS_RATE_TABLE_ENTRY 9 + + +typedef struct _RTMP_TX_RATE_SWITCH_AGS { + UCHAR ItemNo; + +#ifdef RT_BIG_ENDIAN + UCHAR Rsv2:2; + UCHAR Mode:2; + UCHAR Rsv1:1; + UCHAR BW:1; + UCHAR ShortGI:1; + UCHAR STBC:1; +#else + UCHAR STBC:1; + UCHAR ShortGI:1; + UCHAR BW:1; + UCHAR Rsv1:1; + UCHAR Mode:2; + UCHAR Rsv2:2; +#endif /* RT_BIG_ENDIAN */ + + UCHAR CurrMCS; + UCHAR TrainUp; + UCHAR TrainDown; + UCHAR downMcs; + UCHAR upMcs3; + UCHAR upMcs2; + UCHAR upMcs1; +} RTMP_TX_RATE_SWITCH_AGS, *PRTMP_TX_RATE_SWITCH_AGS; + + +/* 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) (IS_RT3593(__pAd)) +#define AGS_IS_USING(__pAd, __pRateTable) \ + (SUPPORT_AGS(__pAd) && \ + ((__pRateTable == AGS1x1HTRateTable) || \ + (__pRateTable == AGS2x2HTRateTable) || \ + (__pRateTable == AGS3x3HTRateTable))) + +#endif /* __AGS_H__ */ + +/* End of ags.h */ diff --git a/mt7620/src/include/ap.h b/mt7620/src/include/ap.h new file mode 100644 index 0000000..b0f29b0 --- /dev/null +++ b/mt7620/src/include/ap.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: + ap.h + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Lin 08-01-2002 created + James Tan 09-06-2002 modified (Revise NTCRegTable) + John Chang 12-22-2004 modified for RT2561/2661. merge with STA driver +*/ +#ifndef __AP_H__ +#define __AP_H__ + + +/* ============================================================= */ +/* 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].VLAN_VID != 0)) \ + { \ + __VLAN_VID = __pAd->ApCfg.MBSSID[__FromWhichBSSID].VLAN_VID; \ + __VLAN_Priority = __pAd->ApCfg.MBSSID[__FromWhichBSSID].VLAN_Priority; \ + } \ +} + +/* ============================================================= */ +/* Function Prototypes */ +/* ============================================================= */ + +/* ap_data.c */ + +BOOLEAN APBridgeToWirelessSta( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHeader, + IN UINT HdrLen, + IN PUCHAR pData, + IN UINT DataLen, + IN ULONG fromwdsidx); + +VOID RTMP_BASetup( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pMacEntry, + IN UINT8 UserPriority); + +VOID APSendPackets( + IN NDIS_HANDLE MiniportAdapterContext, + IN PPNDIS_PACKET ppPacketArray, + IN UINT NumberOfPackets); + +NDIS_STATUS APSendPacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket); + +NDIS_STATUS APInsertPsQueue( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN MAC_TABLE_ENTRY *pMacEntry, + IN UCHAR QueIdx); + +NDIS_STATUS APHardTransmit( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR QueIdx); + +VOID APRxEAPOLFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +NDIS_STATUS APCheckRxError( + IN PRTMP_ADAPTER pAd, + IN PRT28XX_RXD_STRUC pRxD, + IN UCHAR Wcid); + +BOOLEAN APCheckClass2Class3Error( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN PHEADER_802_11 pHeader); + +VOID APHandleRxPsPoll( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN USHORT Aid, + IN BOOLEAN isActive); + +VOID RTMPDescriptorEndianChange( + IN PUCHAR pData, + IN ULONG DescriptorType); + +VOID RTMPFrameEndianChange( + IN PRTMP_ADAPTER pAd, + IN PUCHAR 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 APPeerAssocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerReassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerDisassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MbssKickOutStas( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN USHORT Reason); + +VOID APMlmeKickOutSta( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pStaAddr, + IN UCHAR Wcid, + IN USHORT Reason); + + +VOID APMlmeDisassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APCls3errAction( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN PHEADER_802_11 pHeader); + + +USHORT APBuildAssociation( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN USHORT CapabilityInfo, + IN UCHAR MaxSupportedRateIn500Kbps, + IN UCHAR *RSN, + IN UCHAR *pRSNLen, + IN BOOLEAN bWmmCapable, + IN ULONG RalinkIe, + IN EXT_CAP_INFO_ELEMENT ExtCapInfo, + IN HT_CAPABILITY_IE *pHtCapability, + OUT UCHAR *pHtCapabilityLen, + OUT USHORT *pAid); + +/* +VOID RTMPAddClientSec( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIdx, + IN UCHAR KeyIdx, + IN UCHAR CipherAlg, + IN PUCHAR pKey, + IN PUCHAR pTxMic, + IN PUCHAR pRxMic, + IN MAC_TABLE_ENTRY *pEntry); +*/ + +/* ap_auth.c */ + +void APAuthStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID APCls2errAction( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN PHEADER_802_11 pHeader); + +/* ap_connect.c */ + +#ifdef CONFIG_AP_SUPPORT +BOOLEAN BeaconTransmitRequired( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN MULTISSID_STRUCT *pMbss); +#endif /* CONFIG_AP_SUPPORT */ + +VOID APMakeBssBeacon( + IN PRTMP_ADAPTER pAd, + IN INT apidx); + +VOID APUpdateBeaconFrame( + IN PRTMP_ADAPTER pAd, + IN INT apidx); + +VOID APMakeAllBssBeacon( + IN PRTMP_ADAPTER pAd); + +VOID APUpdateAllBeaconFrame( + IN PRTMP_ADAPTER pAd); + + +/* 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 APInvalidStateWhenScan( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APScanTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerProbeReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerBeaconAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APMlmeScanReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef CON_WPS +VOID APMlmeScanCompleteAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif /* CON_WPS */ + +VOID APPeerBeaconAtScanAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APScanCnclAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ApSiteSurvey( + IN PRTMP_ADAPTER pAd, + IN PNDIS_802_11_SSID pSsid, + IN UCHAR ScanType, + IN BOOLEAN ChannelSel); + +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( + IN PRTMP_ADAPTER pAd); + +#ifdef DOT11N_DRAFT3 +VOID APOverlappingBSSScan( + IN RTMP_ADAPTER *pAd); + +INT GetBssCoexEffectedChRange( + IN RTMP_ADAPTER *pAd, + IN BSS_COEX_CH_RANGE *pCoexChRange); + +#endif /* DOT11N_DRAFT3 */ + +/* ap_wpa.c */ +VOID WpaStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +/* ap_mlme.c */ +VOID APMlmePeriodicExec( + IN PRTMP_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 RTMPSetPiggyBack( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bPiggyBack); + +VOID APAsicEvaluateRxAnt( + IN PRTMP_ADAPTER pAd); + +VOID APAsicRxAntEvalTimeout( + IN PRTMP_ADAPTER pAd); + +/* ap.c */ +NDIS_STATUS APInitialize( + IN PRTMP_ADAPTER pAd); + +VOID APShutdown( + IN PRTMP_ADAPTER pAd); + +VOID APStartUp( + IN PRTMP_ADAPTER pAd); + +VOID APStop( + IN PRTMP_ADAPTER pAd); + +VOID APCleanupPsQueue( + IN PRTMP_ADAPTER pAd, + IN PQUEUE_HEADER pQueue); + +VOID MacTableReset( + IN PRTMP_ADAPTER pAd); + +MAC_TABLE_ENTRY *MacTableInsertEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR apidx, + IN UCHAR OpMode, + IN BOOLEAN CleanAll); + +BOOLEAN MacTableDeleteEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT wcid, + IN PUCHAR pAddr); + +MAC_TABLE_ENTRY *MacTableLookup( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +VOID MacTableMaintenance( + IN PRTMP_ADAPTER pAd); + +UINT32 MacTableAssocStaNumGet( + IN PRTMP_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); + +BOOLEAN APPsIndicate( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN ULONG Wcid, + IN UCHAR Psm); + +#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 */ + +#ifdef DOT11_N_SUPPORT +VOID APUpdateOperationMode( + IN PRTMP_ADAPTER pAd); +#endif /* DOT11_N_SUPPORT */ + +VOID APUpdateCapabilityAndErpIe( + IN PRTMP_ADAPTER pAd); + +BOOLEAN ApCheckAccessControlList( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR Apidx); + +VOID ApUpdateAccessControlList( + IN PRTMP_ADAPTER pAd, + IN UCHAR Apidx); + +VOID ApEnqueueNullFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR TxRate, + IN UCHAR PID, + IN UCHAR apidx, + IN BOOLEAN bQosNull, + IN BOOLEAN bEOSP, + IN UCHAR OldUP); + +/* ap_sanity.c */ + + +BOOLEAN PeerAssocReqCmmSanity( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN isRessoc, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pListenInterval, + OUT PUCHAR pApAddr, + OUT UCHAR *pSsidLen, + OUT char *Ssid, + OUT UCHAR *pRatesLen, + OUT UCHAR Rates[], + OUT UCHAR *RSN, + OUT UCHAR *pRSNLen, + OUT BOOLEAN *pbWmmCapable, +#ifdef WSC_AP_SUPPORT + OUT BOOLEAN *pWscCapable, +#endif /* WSC_AP_SUPPORT */ + OUT ULONG *pRalinkIe, + OUT EXT_CAP_INFO_ELEMENT *pExtCapInfo, +#ifdef P2P_SUPPORT + OUT ULONG *P2PSubelementLen, + OUT PUCHAR pP2pSubelement, +#endif /* P2P_SUPPORT */ + OUT UCHAR *pHtCapabilityLen, + OUT HT_CAPABILITY_IE *pHtCapability); + + +BOOLEAN PeerDisassocReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + 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 DOT1X_SUPPORT +/* ap_cfg.h */ +INT Set_OwnIPAddr_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_EAPIfName_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_PreAuthIfName_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +/* Define in ap.c */ +BOOLEAN DOT1X_InternalCmdAction( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UINT8 cmd); + +BOOLEAN DOT1X_EapTriggerAction( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); +#endif /* DOT1X_SUPPORT */ +#endif /* __AP_H__ */ + +VOID AP_E2PROM_IOCTL_PostCtrl( + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN PSTRING msg); + +VOID IAPP_L2_UpdatePostCtrl( + IN PRTMP_ADAPTER pAd, + IN UINT8 *mac_p, + IN INT bssid); diff --git a/mt7620/src/include/ap_apcli.h b/mt7620/src/include/ap_apcli.h new file mode 100644 index 0000000..938f23d --- /dev/null +++ b/mt7620/src/include/ap_apcli.h @@ -0,0 +1,314 @@ +/* + *************************************************************************** + * 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 */ + +#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); + +/* */ +/* Private routines in apcli_ctrl.c */ +/* */ +VOID ApCliCtrlStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +/* */ +/* Private routines in apcli_sync.c */ +/* */ +VOID ApCliSyncStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +/* */ +/* Private routines in apcli_auth.c */ +/* */ +VOID ApCliAuthStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +/* */ +/* Private routines in apcli_assoc.c */ +/* */ +VOID ApCliAssocStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +MAC_TABLE_ENTRY *ApCliTableLookUpByWcid( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid, + IN PUCHAR pAddrs); + + +BOOLEAN ApCliAllowToSendPacket( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + OUT UCHAR *pWcid); + +BOOLEAN ApCliValidateRSNIE( + IN PRTMP_ADAPTER pAd, + IN PEID_STRUCT pEid_ptr, + IN USHORT eid_len, + IN USHORT idx); + +BOOLEAN ApCliValidateAuthEncryp( + IN PAPCLI_STRUCT pApCliEntry, + IN NDIS_802_11_AUTHENTICATION_MODE WPA_AuthMode, + IN NDIS_802_11_AUTHENTICATION_MODE WPA_AuthModeAux, + IN CIPHER_SUITE WPA); + + +VOID ApCli_Remove( + IN PRTMP_ADAPTER pAd); + +VOID RT28xx_ApCli_Close( + IN PRTMP_ADAPTER pAd); + + + +INT ApCliIfLookUp( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + + +INT ApCli_VirtualIF_PacketSend( + IN PNDIS_PACKET skb_p, + IN PNET_DEV dev_p); + +INT ApCli_VirtualIF_Ioctl( + IN PNET_DEV dev_p, + IN OUT VOID *rq_p, + IN INT cmd); + + +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 */ + +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, +#ifdef P2P_SUPPORT + OUT ULONG *P2PSubelementLen, + OUT PUCHAR pP2pSubelement, +#endif /* P2P_SUPPORT */ + 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); + +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 ApCliUpdateMlmeRate( + IN PRTMP_ADAPTER pAd, + IN USHORT ifIndex); + +VOID APCli_Init( + IN PRTMP_ADAPTER pAd, + IN RTMP_OS_NETDEV_OP_HOOK *pNetDevOps); + +BOOLEAN ApCli_Open( + IN PRTMP_ADAPTER pAd, + IN PNET_DEV dev_p); + +BOOLEAN ApCli_Close( + IN PRTMP_ADAPTER pAd, + IN PNET_DEV dev_p); + +BOOLEAN ApCliWaitProbRsp( + IN PRTMP_ADAPTER pAd, + IN USHORT ifIndex); + +#ifdef APCLI_AUTO_CONNECT_SUPPORT +extern INT Set_ApCli_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +extern INT Set_ApCli_Bssid_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +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); +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + +#endif /* APCLI_SUPPORT */ + +#endif /* _AP_APCLI_H_ */ + diff --git a/mt7620/src/include/ap_autoChSel.h b/mt7620/src/include/ap_autoChSel.h new file mode 100644 index 0000000..729da5f --- /dev/null +++ b/mt7620/src/include/ap_autoChSel.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. + **************************************************************************** + + 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); + +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/mt7620/src/include/ap_autoChSel_cmm.h b/mt7620/src/include/ap_autoChSel_cmm.h new file mode 100644 index 0000000..21a822a --- /dev/null +++ b/mt7620/src/include/ap_autoChSel_cmm.h @@ -0,0 +1,61 @@ +/**************************************************************************** + * 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__ + +#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 AP_QLOAD_SUPPORT + UINT32 chanbusytime[MAX_NUM_OF_CHANNELS+1]; /* QLOAD ALARM */ +#endif /* AP_QLOAD_SUPPORT */ + 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/mt7620/src/include/ap_cfg.h b/mt7620/src/include/ap_cfg.h new file mode 100644 index 0000000..a7878e6 --- /dev/null +++ b/mt7620/src/include/ap_cfg.h @@ -0,0 +1,183 @@ +#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); + +#ifdef INF_AR9 +#ifdef AR9_MAPI_SUPPORT +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); + +#ifdef RTMP_RBUS_SUPPORT +/* +++ added by Red@Ralink, 2009/09/30 */ +VOID RTMPIoctlGetMacTableStaInfo( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +/* ++ end of addition */ +#endif /* RTMP_RBUS_SUPPORT */ + +VOID RTMPIoctlGetMacTable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + + +VOID RTMPAPIoctlE2PROM( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +#ifdef DBG +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 RtmpDrvMaxRateGet( + IN VOID *pReserved, +/* IN PHTTRANSMIT_SETTING pHtPhyMode, */ + IN UINT8 MODE, + IN UINT8 ShortGI, + IN UINT8 BW, + IN UINT8 MCS, + 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 */ +#ifdef INF_AR9 +#ifdef AR9_MAPI_SUPPORT +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); +#endif /* DOT1X_SUPPORT */ + +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/mt7620/src/include/ap_diversity.h b/mt7620/src/include/ap_diversity.h new file mode 100644 index 0000000..4d9d832 --- /dev/null +++ b/mt7620/src/include/ap_diversity.h @@ -0,0 +1,149 @@ +/*************************************************************************** + * 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" + +/* + * TAB width:8 + */ + +/* + * For shorter udelay(). + * (ripped from rtmp.h) + */ +/*#define RTMP_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) {} */ +/* 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 PRTMP_ADAPTER pAd +); + +VOID RT3XXX_AntDiversity_Fini( + IN PRTMP_ADAPTER pAd +); + +VOID AntDiversity_Update_Rssi_Sample( + IN PRTMP_ADAPTER pAd, + IN RSSI_SAMPLE *pRssi, + IN PRXWI_STRUC pRxWI +); + + +#endif diff --git a/mt7620/src/include/ap_ids.h b/mt7620/src/include/ap_ids.h new file mode 100644 index 0000000..76a15d3 --- /dev/null +++ b/mt7620/src/include/ap_ids.h @@ -0,0 +1,72 @@ +/**************************************************************************** + * 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 PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHeader, + IN CHAR Rssi0, + IN CHAR Rssi1, + IN CHAR Rssi2); + +VOID RTMPConflictSsidDetection( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN CHAR Rssi0, + IN CHAR Rssi1, + IN CHAR Rssi2); + +BOOLEAN RTMPReplayAttackDetection( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr2, + IN CHAR Rssi0, + IN CHAR Rssi1, + IN CHAR Rssi2); + +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/mt7620/src/include/ap_mbss.h b/mt7620/src/include/ap_mbss.h new file mode 100644 index 0000000..a226de7 --- /dev/null +++ b/mt7620/src/include/ap_mbss.h @@ -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, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering 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 +*/ + +#ifndef MODULE_MBSS + +#define MBSS_EXTERN extern + +#else + +#define MBSS_EXTERN + +#endif /* MODULE_MBSS */ + + +/* + 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].PhyMode; \ + if ((__PhyMode == PHY_11B) && \ + (__HtPhyMode.field.MODE != MODE_CCK)) \ + { \ + __HtPhyMode.field.MODE = MODE_CCK; \ + __HtPhyMode.field.MCS = 3; \ + } \ + else if ((__PhyMode <= PHY_11G) && \ + (__PhyMode != PHY_11B) && \ + (__HtPhyMode.field.MODE != MODE_OFDM)) \ + { \ + __HtPhyMode.field.MODE = MODE_OFDM; \ + __HtPhyMode.field.MCS = 7; \ + } \ + } + + +/* Public function list */ +INT Show_MbssInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +VOID MBSS_Init( + IN PRTMP_ADAPTER pAd, + IN RTMP_OS_NETDEV_OP_HOOK *pNetDevOps); + +VOID MBSS_Remove( + IN PRTMP_ADAPTER pAd); + +INT MBSS_Open( + IN PNET_DEV pDev); + +INT MBSS_Close( + IN PNET_DEV pDev); + +INT32 RT28xx_MBSS_IdxGet( + IN PRTMP_ADAPTER pAd, + IN PNET_DEV pDev); + +/* End of ap_mbss.h */ diff --git a/mt7620/src/include/ap_wds.h b/mt7620/src/include/ap_wds.h new file mode 100644 index 0000000..016ea9e --- /dev/null +++ b/mt7620/src/include/ap_wds.h @@ -0,0 +1,220 @@ +/* + *************************************************************************** + * 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].VLAN_VID != 0)) \ + { \ + __VLAN_VID = __pAd->WdsTab.WdsEntry[ \ + __FromWhichBSSID - MIN_NET_DEVICE_FOR_WDS].VLAN_VID; \ + __VLAN_Priority = __pAd->WdsTab.WdsEntry[ \ + __FromWhichBSSID - MIN_NET_DEVICE_FOR_WDS].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].dev != NULL) && (RTMP_OS_NETDEV_STATE_RUNNING(pAd->WdsTab.WdsEntry[ifidx].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); + + +BOOLEAN ApWdsAllowToSendPacket( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + OUT UCHAR *pWcid); + +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 RT28xx_WDS_Close( + 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, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen); + +VOID APWdsInitialize( + IN PRTMP_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( + IN PRTMP_ADAPTER pAd); + + +VOID WDS_Init( + IN PRTMP_ADAPTER pAd, + IN RTMP_OS_NETDEV_OP_HOOK *pNetDevOps); + +VOID WDS_Remove( + IN PRTMP_ADAPTER pAd); + +BOOLEAN WDS_StatsGet( + IN PRTMP_ADAPTER pAd, + IN RT_CMD_STATS *pStats); + +VOID AP_WDS_KeyNameMakeUp( + IN STRING *pKey, + IN UINT32 KeyMaxSize, + IN INT KeyId); + +/* + ========================================================================== + Description: + Check the WDS Entry is valid or not. + ========================================================================== + */ +static inline BOOLEAN ValidWdsEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR WdsIndex) +{ + BOOLEAN result; + PMAC_TABLE_ENTRY pMacEntry; + + do + { + if (WdsIndex >= MAX_WDS_ENTRY) + { + result = FALSE; + break; + } + + if (pAd->WdsTab.WdsEntry[WdsIndex].Valid != TRUE) + { + result = FALSE; + break; + } + + if ((pAd->WdsTab.WdsEntry[WdsIndex].MacTabMatchWCID==0) + || (pAd->WdsTab.WdsEntry[WdsIndex].MacTabMatchWCID >= MAX_LEN_OF_MAC_TABLE)) + { + result = FALSE; + break; + } + + pMacEntry = &pAd->MacTab.Content[pAd->WdsTab.WdsEntry[WdsIndex].MacTabMatchWCID]; + if (!IS_ENTRY_WDS(pMacEntry)) + { + result = FALSE; + break; + } + + result = TRUE; + } while(FALSE); + + return result; +} +#endif /* _AP_WDS_H_ */ + diff --git a/mt7620/src/include/band_steering.h b/mt7620/src/include/band_steering.h new file mode 100644 index 0000000..dc42605 --- /dev/null +++ b/mt7620/src/include/band_steering.h @@ -0,0 +1,99 @@ +/* + *************************************************************************** + * 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_RssiCheck( 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); +#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); + +INT BndStrg_CheckConnectionReq( + PRTMP_ADAPTER pAd, + PUCHAR pSrcAddr, + UINT8 FrameType, + PCHAR Rssi, + BOOLEAN *bAuthCheck); + +INT BndStrg_Enable(PBND_STRG_CLI_TABLE table, BOOLEAN enable); +INT BndStrg_SetInfFlags(PRTMP_ADAPTER pAd, PBND_STRG_CLI_TABLE table, BOOLEAN bInfReady); +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, _bAuthCheck) \ +{ \ + 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; \ +\ + BndStrg_CheckConnectionReq( _pAd, \ + _SrcAddr, \ + _FrameType, \ + Rssi, \ + _bAuthCheck); \ +} + +#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/mt7620/src/include/band_steering_def.h b/mt7620/src/include/band_steering_def.h new file mode 100644 index 0000000..8115cef --- /dev/null +++ b/mt7620/src/include/band_steering_def.h @@ -0,0 +1,208 @@ +/* + *************************************************************************** + * 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_CHECK 30 +#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; + +typedef struct _BND_STRG_CLI_TABLE{ + BOOLEAN bInitialized; + BOOLEAN bEnabled; + UINT32 Size; + 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 RssiCheck; /* if Rssi2.4G > Rssi5G by RssiCheck, then allow client to connect 2.4G */ + 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_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_NOT_SUPPORT_HT = (1 << 3), + fBND_STRG_CLIENT_IS_2G_ONLY = (1 << 4), +}; + +#define OID_BNDSTRG_MSG 0x0950 +/* Use for I/O between driver and daemon */ +typedef struct _BNDSTRG_MSG{ + UINT8 Action; + BOOLEAN OnOff; + UINT8 Band; + BOOLEAN b2GInfReady; + BOOLEAN b5GInfReady; + CHAR Rssi[3]; + CHAR RssiCheck; + UINT8 FrameType; + BOOLEAN bAuthCheck; + UINT32 Time; + 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, + INF_STATUS_QUERY, + INF_STATUS_RSP_2G, + INF_STATUS_RSP_5G, + TABLE_INFO, + ENTRY_LIST, + BNDSTRG_ONOFF, + SET_RSSI_CHECK, + SET_AGE_TIME, + SET_HOLD_TIME, + SET_CHECK_TIME, + SET_MNT_ADDR, +}; + + + +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); + + INT (*CheckConnectionReq)( + struct _RTMP_ADAPTER *pAd, + PUCHAR pSrcAddr, + UINT8 FrameType, + PCHAR Rssi, + BOOLEAN *bAuthCheck); + + INT (*SetEnable)( + PBND_STRG_CLI_TABLE table, + BOOLEAN enable); + + INT (*SetRssiCheck)( + PBND_STRG_CLI_TABLE table, + CHAR RssiCheck); + + 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); + +#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/mt7620/src/include/br_ftph.h b/mt7620/src/include/br_ftph.h new file mode 100644 index 0000000..7810cf1 --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/cfg80211.h b/mt7620/src/include/cfg80211.h new file mode 100644 index 0000000..36139d1 --- /dev/null +++ b/mt7620/src/include/cfg80211.h @@ -0,0 +1,78 @@ +/**************************************************************************** + * 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. + +***************************************************************************/ + +#ifdef RT_CFG80211_SUPPORT + +#include + +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]; +} 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 */ + +/* End of cfg80211.h */ diff --git a/mt7620/src/include/cfg80211extr.h b/mt7620/src/include/cfg80211extr.h new file mode 100644 index 0000000..32caaa6 --- /dev/null +++ b/mt7620/src/include/cfg80211extr.h @@ -0,0 +1,201 @@ +/**************************************************************************** + * 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 Function Prototype. + +***************************************************************************/ + +#ifdef RT_CFG80211_SUPPORT + +#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_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_Alpha2); + +#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); + +#define RT_CFG80211_REINIT(__pAd) \ + CFG80211_SupBandReInit((VOID *)__pAd); \ + +#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_RFKILL_STATUS_UPDATE(_pAd, _active) \ + CFG80211_RFKillStatusUpdate(_pAd, _active); + +#ifdef SINGLE_SKU +#define CFG80211_BANDINFO_FILL(__pAd, __pBandInfo) \ +{ \ + (__pBandInfo)->RFICType = __pAd->RFICType; \ + (__pBandInfo)->MpduDensity = __pAd->CommonCfg.BACapability.field.MpduDensity;\ + (__pBandInfo)->TxStream = __pAd->CommonCfg.TxStream; \ + (__pBandInfo)->RxStream = __pAd->CommonCfg.RxStream; \ + (__pBandInfo)->MaxTxPwr = __pAd->CommonCfg.DefineMaxTxPwr; \ + if (__pAd->CommonCfg.PhyMode == PHY_11B) \ + (__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->RFICType; \ + (__pBandInfo)->MpduDensity = __pAd->CommonCfg.BACapability.field.MpduDensity;\ + (__pBandInfo)->TxStream = __pAd->CommonCfg.TxStream; \ + (__pBandInfo)->RxStream = __pAd->CommonCfg.RxStream; \ + (__pBandInfo)->MaxTxPwr = 0; \ + if (__pAd->CommonCfg.PhyMode == PHY_11B) \ + (__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 */ + + +/* utilities used in DRV module */ +INT CFG80211DRV_IoctlHandle( + IN VOID *pAdSrc, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN INT cmd, + IN USHORT subcmd, + IN VOID *pData, + IN ULONG Data); + +BOOLEAN CFG80211DRV_OpsSetChannel( + VOID *pAdOrg, + VOID *pData); + +BOOLEAN CFG80211DRV_OpsChgVirtualInf( + VOID *pAdOrg, + VOID *pFlgFilter, + UINT8 IfType); + +BOOLEAN CFG80211DRV_OpsScan( + VOID *pAdOrg); + +BOOLEAN CFG80211DRV_OpsJoinIbss( + VOID *pAdOrg, + VOID *pData); + +BOOLEAN CFG80211DRV_OpsLeave( + VOID *pAdOrg); + +BOOLEAN CFG80211DRV_StaGet( + VOID *pAdOrg, + VOID *pData); + +BOOLEAN CFG80211DRV_Connect( + VOID *pAdOrg, + VOID *pData); + +BOOLEAN CFG80211DRV_KeyAdd( + VOID *pAdOrg, + VOID *pData); + +VOID CFG80211DRV_RegNotify( + VOID *pAdOrg, + VOID *pData); + +VOID CFG80211DRV_SurveyGet( + VOID *pAdOrg, + VOID *pData); + +VOID CFG80211DRV_PmkidConfig( + VOID *pAdOrg, + VOID *pData); + +VOID CFG80211_RegHint( + IN VOID *pAdCB, + IN UCHAR *pCountryIe, + IN ULONG CountryIeLen); + +VOID CFG80211_RegHint11D( + IN VOID *pAdCB, + IN UCHAR *pCountryIe, + IN ULONG CountryIeLen); + +VOID CFG80211_ScanEnd( + IN VOID *pAdCB, + IN BOOLEAN FlgIsAborted); + +VOID CFG80211_ConnectResultInform( + IN VOID *pAdCB, + IN UCHAR *pBSSID, + IN UCHAR *pReqIe, + IN UINT32 ReqIeLen, + IN UCHAR *pRspIe, + IN UINT32 RspIeLen, + IN UCHAR FlgIsSuccess); + +BOOLEAN CFG80211_SupBandReInit( + IN VOID *pAdCB); + +VOID CFG80211_RegRuleApply( + IN VOID *pAdCB, + IN VOID *pWiphy, + IN UCHAR *pAlpha2); + +VOID CFG80211_Scaning( + IN VOID *pAdCB, + IN UINT32 BssIdx, + IN UINT32 ChanId, + IN UCHAR *pFrame, + IN UINT32 FrameLen, + IN INT32 RSSI); + +#ifdef RFKILL_HW_SUPPORT +VOID CFG80211_RFKillStatusUpdate( + IN PVOID pAd, + IN BOOLEAN active); +#endif /* RFKILL_HW_SUPPORT */ + +VOID CFG80211_UnRegister( + IN VOID *pAdOrg, + IN VOID *pNetDev); + +#endif /* RT_CFG80211_SUPPORT */ + +/* End of cfg80211extr.h */ diff --git a/mt7620/src/include/chip/chip_id.h b/mt7620/src/include/chip/chip_id.h new file mode 100644 index 0000000..6748e30 --- /dev/null +++ b/mt7620/src/include/chip/chip_id.h @@ -0,0 +1,67 @@ +/**************************************************************************** + * 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 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 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 DLINK_PCI_VENDOR_ID 0x1186 + +#endif /* __CHIP_ID_H__ */ diff --git a/mt7620/src/include/chip/mac_pci.h b/mt7620/src/include/chip/mac_pci.h new file mode 100644 index 0000000..85a0ffd --- /dev/null +++ b/mt7620/src/include/chip/mac_pci.h @@ -0,0 +1,489 @@ +/**************************************************************************** + * 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" +#include "chip/rtmp_mac.h" +#include "chip/rtmp_phy.h" +#include "rtmp_iface.h" +#include "rtmp_dot11.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 TXINFO_SIZE 0 +/*#define RTMP_PKT_TAIL_PADDING 0 // os abl move */ +#define fRTMP_ADAPTER_NEED_STOP_TX 0 + +#define AUX_CTRL 0x10c + +/* */ +/* TX descriptor format, Tx ring, Mgmt Ring */ +/* */ +#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; + /* Word 3 */ + UINT32 ICO:1; + UINT32 UCO:1; + UINT32 TCO:1; + UINT32 rsv:2; + UINT32 QSEL:2; /* select on-chip FIFO ID for 2nd-stage output scheduler.0:MGMT, 1:HCCA 2:EDCA */ + UINT32 WIV:1; /* Wireless Info Valid. 1 if Driver already fill WI, o if DMA needs to copy WI to correctposition */ + UINT32 rsv2:24; +#ifdef DESC_32B_SUPPORT + /* Word 4 */ + UINT32 rsv3; + /* Word 5 */ + UINT32 rsv4; + /* Word 6 */ + UINT32 rsv5; + /* Word 7 */ + UINT32 rsv6; +#endif /* DESC_32B_SUPPORT */ +} 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; + /*Word3 */ + UINT32 rsv2:24; + UINT32 WIV:1; /* Wireless Info Valid. 1 if Driver already fill WI, o if DMA needs to copy WI to correctposition */ + UINT32 QSEL:2; /* select on-chip FIFO ID for 2nd-stage output scheduler.0:MGMT, 1:HCCA 2:EDCA */ + UINT32 rsv:2; + UINT32 TCO:1; /* */ + UINT32 UCO:1; /* */ + UINT32 ICO:1; /* */ +#ifdef DESC_32B_SUPPORT + /* Word 4 */ + UINT32 rsv3; + /* Word 5 */ + UINT32 rsv4; + /* Word 6 */ + UINT32 rsv5; + /* Word 7 */ + UINT32 rsv6; +#endif /* DESC_32B_SUPPORT */ +} 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 Rsv:2; + UINT32 SDL1:14; + /* Word 2 */ + UINT32 SDP1; + /* Word 3 */ + UINT32 Rsv1:13; + UINT32 PlcpRssil:1;/* To be moved */ + UINT32 PlcpSignal:1; /* To be moved */ + UINT32 Decrypted:1; /* this frame is being decrypted. */ + 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; +#ifdef DESC_32B_SUPPORT + /* Word 4 */ + UINT32 rsv3; + /* Word 5 */ + UINT32 rsv4; + /* Word 6 */ + UINT32 rsv5; + /* Word 7 */ + UINT32 rsv6; +#endif /* DESC_32B_SUPPORT */ +} RXD_STRUC, *PRXD_STRUC, RT28XX_RXD_STRUC, *PRT28XX_RXD_STRUC; +#else +typedef struct GNU_PACKED _RXD_STRUC{ + /* Word 0 */ + UINT32 SDP0; + /* Word 1 */ + UINT32 SDL1:14; + UINT32 Rsv:2; + UINT32 SDL0:14; + UINT32 LS0:1; + UINT32 DDONE:1; + /* Word 2 */ + UINT32 SDP1; + /* Word 3 */ + UINT32 BA:1; + UINT32 DATA:1; + UINT32 NULLDATA:1; + UINT32 FRAG:1; + UINT32 U2M:1; /* 1: this RX frame is unicast to me */ + UINT32 Mcast:1; /* 1: this is a multicast frame */ + UINT32 Bcast:1; /* 1: this is a broadcast frame */ + UINT32 MyBss:1; /* 1: this frame belongs to the same BSSID */ + UINT32 Crc:1; /* 1: CRC error */ + UINT32 CipherErr:2; /* 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid */ + UINT32 AMSDU:1; /* rx with 802.3 header, not 802.11 header. */ + UINT32 HTC:1; + UINT32 RSSI:1; + UINT32 L2PAD:1; + UINT32 AMPDU:1; + UINT32 Decrypted:1; /* this frame is being decrypted. */ + UINT32 PlcpSignal:1; /* To be moved */ + UINT32 PlcpRssil:1;/* To be moved */ + UINT32 Rsv1:13; +#ifdef DESC_32B_SUPPORT + /* Word 4 */ + UINT32 rsv3; + /* Word 5 */ + UINT32 rsv4; + /* Word 6 */ + UINT32 rsv5; + /* Word 7 */ + UINT32 rsv6; +#endif /* DESC_32B_SUPPORT */ +} RXD_STRUC, *PRXD_STRUC, RT28XX_RXD_STRUC, *PRT28XX_RXD_STRUC; +#endif + +/* ----------------- 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) + +#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)) */ + + +#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) \ + /*RtmpPCIDataLastTxIdx(_pAd, _QueIdx,_LastTxIdx)*/ + +#define HAL_KickOutTx(_pAd, _pTxBlk, _QueIdx) \ + RTMP_IO_WRITE32((_pAd), TX_CTX_IDX0+((_QueIdx)*0x10), (_pAd)->TxRing[(_QueIdx)].TxCpuIdx) +/* RtmpPCIDataKickOut(_pAd, _pTxBlk, _QueIdx)*/ + +#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); + + +/* ----------------- 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->Aid, 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 ----------------- */ + +/* */ +/* 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 /*DELAYINTMASK*/); /* 1:enable */ \ + RTMP_SET_FLAG((_pAd), fRTMP_ADAPTER_INTERRUPT_ACTIVE); \ + }while(0) + + +#define RTMP_IRQ_INIT(pAd) \ + { unsigned long _irqFlags;\ + RTMP_INT_LOCK(&pAd->irq_lock, _irqFlags);\ + pAd->int_enable_reg = ((DELAYINTMASK) | \ + (RxINT|TxDataInt|TxMgmtInt)) & ~(0x03); \ + pAd->int_disable_mask = 0; \ + pAd->int_pending = 0; \ + RTMP_INT_UNLOCK(&pAd->irq_lock, _irqFlags);\ + } + +#define RTMP_IRQ_ENABLE(pAd) \ + { /* clear garbage ints */ \ + unsigned long _irqFlags;\ + RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, 0xffffffff);\ + RTMP_INT_LOCK(&pAd->irq_lock, _irqFlags);\ + RTMP_ASIC_INTERRUPT_ENABLE(pAd); \ + RTMP_INT_UNLOCK(&pAd->irq_lock, _irqFlags);\ +} + + + +/* ----------------- MLME Related MACRO ----------------- */ +#define RTMP_MLME_HANDLER(pAd) MlmeHandler(pAd) + +#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 */ + +#endif /*__MAC_PCI_H__ */ + diff --git a/mt7620/src/include/chip/rt2860.h b/mt7620/src/include/chip/rt2860.h new file mode 100644 index 0000000..2e8cc54 --- /dev/null +++ b/mt7620/src/include/chip/rt2860.h @@ -0,0 +1,45 @@ +/**************************************************************************** + * 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: + rt2860.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RT2860_H__ +#define __RT2860_H__ + +#ifdef RT2860 + +#ifndef RTMP_PCI_SUPPORT +#error "For RT2860, you should define the compile flag -DRTMP_PCI_SUPPORT" +#endif + +#ifndef RTMP_MAC_PCI +#error "For RT2880, you should define the compile flag -DRTMP_MAC_PCI" +#endif + +/* + Device ID & Vendor ID, these values should match EEPROM value +*/ + +#endif /* RT2860 */ + +#endif /*__RT2860_H__ */ diff --git a/mt7620/src/include/chip/rt2880.h b/mt7620/src/include/chip/rt2880.h new file mode 100644 index 0000000..ff33a97 --- /dev/null +++ b/mt7620/src/include/chip/rt2880.h @@ -0,0 +1,90 @@ +/**************************************************************************** + * 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: + rt2880.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RT2880_H__ +#define __RT2880_H__ + + +#ifndef RTMP_RBUS_SUPPORT +#error "For RT2880, you should define the compile flag -DRTMP_RBUS_SUPPORT" +#endif + +#ifndef RTMP_MAC_PCI +#error "For RT2880, you should define the compile flag -DRTMP_MAC_PCI" +#endif + +#ifdef LINUX +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) +#include +#define RTMP_MAC_CSR_ADDR RALINK_11N_MAC_BASE +#else + +#ifdef CONFIG_RALINK_RT2880_SHUTTLE +#undef RTMP_MAC_CSR_ADDR +#define RTMP_MAC_CSR_ADDR 0xA0600000 +#endif /* CONFIG_RALINK_RT2880_SHUTTLE */ + +#ifdef CONFIG_RALINK_RT2880_MP +#undef RTMP_MAC_CSR_ADDR +#define RTMP_MAC_CSR_ADDR 0xA0480000 +#endif /* CONFIG_RALINK_RT2880_MP */ + +#ifndef RTMP_MAC_CSR_ADDR +#error "Please Choice Chip Version (Shuttle/MP)" +#endif + +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) */ + +#else + +#ifdef CONFIG_RALINK_RT2880_SHUTTLE +#undef RTMP_MAC_CSR_ADDR +#define RTMP_MAC_CSR_ADDR 0xA0600000 +#endif /* CONFIG_RALINK_RT2880_SHUTTLE */ + +#ifdef CONFIG_RALINK_RT2880_MP +#undef RTMP_MAC_CSR_ADDR +#define RTMP_MAC_CSR_ADDR 0xA0480000 +#endif /* CONFIG_RALINK_RT2880_MP */ + +#ifndef RTMP_MAC_CSR_ADDR +#error "Please Choice Chip Version (Shuttle/MP)" +#endif +#endif /* LINUX */ + +#define RT2860_CSR_ADDR_PCI 0xC0000000 /* RT2880 PCI */ + +#define RTMP_FLASH_BASE_ADDR 0xbfc00000 + +struct _RTMP_ADAPTER; +VOID RT2880_Init(IN struct _RTMP_ADAPTER *pAd); + +/* */ +/* Device ID & Vendor ID, these values should match EEPROM value */ +/* */ + + +#endif /*__RT2880_H__ */ + diff --git a/mt7620/src/include/chip/rt2883.h b/mt7620/src/include/chip/rt2883.h new file mode 100644 index 0000000..30a00ef --- /dev/null +++ b/mt7620/src/include/chip/rt2883.h @@ -0,0 +1,67 @@ +/**************************************************************************** + * 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: + rt2883.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RT2883_H__ +#define __RT2883_H__ + +#ifndef RTMP_RBUS_SUPPORT +#error "For RT2880, you should define the compile flag -DRTMP_RBUS_SUPPORT" +#endif + +#ifndef RTMP_MAC_PCI +#error "For RT2880, you should define the compile flag -DRTMP_MAC_PCI" +#endif + +struct _RTMP_ADAPTER; + +#define RTMP_MAC_CSR_ADDR 0xB0180000 +#define RTMP_FLASH_BASE_ADDR 0xbfc00000 + +#define BBP_REG_BF BBP_R105 +#define BBP_REG_SNR0 BBP_R189 +#define BBP_REG_SNR1 BBP_R190 +#define BBP_REG_SNR2 BBP_R191 + + +extern REG_PAIR RT2883_BBPRegTable[]; +extern UCHAR RT2883_NUM_BBP_REG_PARMS; + + +/* */ +/* Device ID & Vendor ID, these values should match EEPROM value */ +/* */ + + +/* ========================= + Function definition + ========================= */ +VOID NICInitRT2883MacRegisters( + IN struct _RTMP_ADAPTER *pAd); + +VOID NICInitRT2883BbpRegisters( + IN struct _RTMP_ADAPTER *pAd); + +#endif /*__RT2880_H__ */ + diff --git a/mt7620/src/include/chip/rt28xx.h b/mt7620/src/include/chip/rt28xx.h new file mode 100644 index 0000000..3eacae6 --- /dev/null +++ b/mt7620/src/include/chip/rt28xx.h @@ -0,0 +1,39 @@ +/**************************************************************************** + * 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: + rt28xx.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RT28XX_H__ +#define __RT28XX_H__ + +#ifdef RT28xx + +VOID RT28xx_ChipSwitchChannel( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR Channel, + IN BOOLEAN bScan); + +#endif /* RT28xx */ + +#endif /*__RT28XX_H__ */ + diff --git a/mt7620/src/include/chip/rt305x.h b/mt7620/src/include/chip/rt305x.h new file mode 100644 index 0000000..91c11ff --- /dev/null +++ b/mt7620/src/include/chip/rt305x.h @@ -0,0 +1,104 @@ +/**************************************************************************** + * 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: + rt305x.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RT305x_H__ +#define __RT305x_H__ + +#ifdef RT305x + +struct _RTMP_ADAPTER; + +#ifndef RTMP_RBUS_SUPPORT +#error "For RT305x, you should define the compile flag -DRTMP_RBUS_SUPPORT" +#endif + +#ifndef RTMP_MAC_PCI +#error "For RT305x, you should define the compile flag -DRTMP_MAC_PCI" +#endif + +#ifndef RTMP_RF_RW_SUPPORT +#error "For RT305x, you should define the compile flag -DRTMP_RF_RW_SUPPORT" +#endif + +#define RTMP_SYS_CTL_ADDR 0xB0000000 +#define RTMP_INT_CTL_ADDR 0xB0000200 +#define RTMP_PIO_CTL_ADDR 0xB0000600 +#define RTMP_MAC_CSR_ADDR 0xB0180000 +#define RTMP_FLASH_BASE_ADDR 0xbfc00000 + +/* System Control */ +#define RTMP_SYS_GPIOMODE_OFFSET 0x0060 + +/* Programmable I/O */ +#define RTMP_PIO2100_DATA_OFFSET 0x0020 +#define RTMP_PIO2100_DIR_OFFSET 0x0024 +#define RTMP_PIO2100_POL_OFFSET 0x0028 + +extern REG_PAIR RT305x_RFRegTable[]; + +extern REG_PAIR RT305x_BBPRegTable[]; +extern UCHAR RT305x_NUM_BBP_REG_PARMS; + +// +// Device ID & Vendor ID, these values should match EEPROM value +// + + +VOID RT305x_Init( + IN struct _RTMP_ADAPTER *pAd); + +VOID NICInitRT305xMacRegisters( + IN struct _RTMP_ADAPTER *pAd); + +VOID NICInitRT305xBbpRegisters( + IN struct _RTMP_ADAPTER *pAd); + +VOID RT305x_ChipSwitchChannel( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR Channel, + IN BOOLEAN bScan); + +#ifdef RTMP_INTERNAL_TX_ALC +VOID RT3350_InitDesiredTSSITable( + IN struct _RTMP_ADAPTER *pAd); + +UCHAR RT3350_GetDesiredTSSI( + IN struct _RTMP_ADAPTER *pAd); + +VOID RT3350_AsicTxAlcGetAutoAgcOffset( + IN struct _RTMP_ADAPTER *pAd, + IN PCHAR pDeltaPwr, + IN PCHAR pTotalDeltaPwr, + IN PCHAR pAgcCompensate, + IN PCHAR pDeltaPowerByBbpR1); +#endif /* RTMP_INTERNAL_TX_ALC */ + +VOID RT305x_ChipSpecInit( + IN struct _RTMP_ADAPTER *pAd); + +#endif // RT305x // + +#endif //__RT305x_H__ // + diff --git a/mt7620/src/include/chip/rt3352.h b/mt7620/src/include/chip/rt3352.h new file mode 100644 index 0000000..fe89229 --- /dev/null +++ b/mt7620/src/include/chip/rt3352.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: + rt3352.h + + Abstract: + 2*2 Wireless Chip SoC + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + SampleLin 20100625 Initial version + */ + +#ifndef __RT3352_H__ +#define __RT3352_H__ + +#ifdef RT3352 + +struct _RTMP_ADAPTER; + +/* */ +/* Device ID & Vendor ID, these values should match EEPROM value */ +/* */ + +extern REG_PAIR RT3352_RFRegTable[]; +extern UCHAR RT3352_NUM_RF_REG_PARMS; +extern REG_PAIR RT3352_BBPRegTable[]; +extern UCHAR RT3352_NUM_BBP_REG_PARMS; +extern RTMP_REG_PAIR RT3352_MACRegTable[]; +extern UCHAR RT3352_NUM_MAC_REG_PARMS; + +#ifdef CONFIG_RALINK_RT3352 +#define PROCREG_DIR "rt3352" +#endif /* CONFIG_RALINK_RT3352 */ + +VOID RT3352_Init( + IN struct _RTMP_ADAPTER *pAd); + +VOID NICInitRT3352MacRegisters( + IN struct _RTMP_ADAPTER *pAd); + +VOID NICInitRT3352BbpRegisters( + IN struct _RTMP_ADAPTER *pAd); + +VOID NICInitRT3352RFRegisters( + IN struct _RTMP_ADAPTER *pAd); + +VOID RT3352_EnableAPMIMOPS( + IN struct _RTMP_ADAPTER *pAd, + IN BOOLEAN ReduceCorePower); + +VOID RT3352_DisableAPMIMOPS( + IN struct _RTMP_ADAPTER *pAd); + +VOID RT3352_RxSensitivityTuning( + IN struct _RTMP_ADAPTER *pAd); + +UCHAR RT3352_ChipAGCAdjust( + IN struct _RTMP_ADAPTER *pAd, + IN CHAR Rssi, + IN UCHAR OrigR66Value); + +VOID RT3352_ChipBBPAdjust( + IN struct _RTMP_ADAPTER *pAd); + +VOID RT3352_ChipSwitchChannel( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR Channel, + IN BOOLEAN bScan); + +VOID *RT3352_AsicTxAlcTxPwrAdjOverRF( + IN struct _RTMP_ADAPTER *pAd, + IN VOID *pTxPowerTuningEntrySrc); + +VOID RT3352_RTMPSetAGCInitValue( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR BandWidth); + +#ifdef RTMP_INTERNAL_TX_ALC +VOID RT3352_InitDesiredTSSITable( + IN struct _RTMP_ADAPTER *pAd); + +UCHAR RT3352_GetDesiredTSSI( + IN struct _RTMP_ADAPTER *pAd); + +VOID RT3352_AsicTxAlcGetAutoAgcOffset( + IN struct _RTMP_ADAPTER *pAd, + IN PCHAR pDeltaPwr, + IN PCHAR pTotalDeltaPwr, + IN PCHAR pAgcCompensate, + IN PCHAR pDeltaPowerByBbpR1); +#endif /* RTMP_INTERNAL_TX_ALC */ +#endif /* RT3352 */ +#endif /*__RT3352_H__ */ + +/* End of rt3352.h */ diff --git a/mt7620/src/include/chip/rt3883.h b/mt7620/src/include/chip/rt3883.h new file mode 100644 index 0000000..373fdfa --- /dev/null +++ b/mt7620/src/include/chip/rt3883.h @@ -0,0 +1,95 @@ +/**************************************************************************** + * 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: + rt3883.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RT3883_H__ +#define __RT3883_H__ + +#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; + +#define RTMP_MAC_CSR_ADDR 0xB0180000 +#define RTMP_FLASH_BASE_ADDR 0xbc000000 + + +#define BBP_REG_BF BBP_R163 +#define BBP_REG_SNR0 BBP_R160 +#define BBP_REG_SNR1 BBP_R161 +#define BBP_REG_SNR2 BBP_R162 + + +#define MAX_RF_TX_POWER 31 // Maximum Tx Power value in RF Register + +// Macro to convert Tx Power setting to RF Reg for A Band +#define TX_PWR_TO_RF_REG(p) (CHAR)(0x48 | (((p) & 0x18) << 1) | ((p) & 0x7)) + +extern UCHAR NUM_OF_3883_CHNL; +extern FREQUENCY_ITEM FreqItems3883[]; + +VOID RTMPRT3883ABandSel( + IN UCHAR Channel); + +VOID RTMPRT3883ReadChannelPwr( + IN struct _RTMP_ADAPTER *pAd); + +VOID RTMPRT3883ReadTxPwrPerRate( + IN struct _RTMP_ADAPTER *pAd); + +VOID RT3883_Init( + IN struct _RTMP_ADAPTER *pAd); + +VOID RT3883_AsicGetTxPowerOffset( + IN struct _RTMP_ADAPTER *pAd, + INOUT PULONG pTxPwr); + +#ifdef CONFIG_AP_SUPPORT +int RT3883_ext_pkt_len( + IN UCHAR *pOutBuffer, + IN ULONG FrameLen, + IN UCHAR *RalinkSpecificIe, + IN UCHAR IeLen); +#endif /* CONFIG_AP_SUPPORT */ + +VOID RT3883_CWC_ProtectAdjust( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR *pSetMask, + IN USHORT *pOperationMode); + +VOID RT3883_CWC_AsicSet( + IN struct _RTMP_ADAPTER *pAd, + IN BOOLEAN bCwc); + +void RT3883_AsicSetFreqOffset( + IN struct _RTMP_ADAPTER *pAd, + IN ULONG freqOffset); + +#endif /*__RT3883_H__ */ + diff --git a/mt7620/src/include/chip/rt5350.h b/mt7620/src/include/chip/rt5350.h new file mode 100644 index 0000000..a01f830 --- /dev/null +++ b/mt7620/src/include/chip/rt5350.h @@ -0,0 +1,124 @@ +/**************************************************************************** + * 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: + rt5350.h + + Abstract: + 2*2 Wireless Chip SoC + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + SampleLin 20100908 Initial version + */ + +#ifndef __RT5350_H__ +#define __RT5350_H__ + +#ifdef RT5350 + +struct _RTMP_ADAPTER; + +#undef EEPROM_TSSI_REF_OFFSET + +#define EEPROM_TSSI_REF_OFFSET 0x6E +#define EEPROM_TSSI_DELTA_CH1_CH2 0x6F +#define EEPROM_TSSI_DELTA_CH3_CH4 0x70 +#define EEPROM_TSSI_DELTA_CH5_CH6 0x71 +#define EEPROM_TSSI_DELTA_CH7_CH8 0x72 +#define EEPROM_TSSI_DELTA_CH9_CH10 0x73 +#define EEPROM_TSSI_DELTA_CH11_CH12 0x74 +#define EEPROM_TSSI_DELTA_CH13_CH14 0x75 + +#define EEPROM_TSSI_GAIN_ATTENUATION 0x76 + +#define EEPROM_RSSI_GAIN 0x120 + +#ifdef RTMP_INTERNAL_TX_ALC +//TSSI delta info is signed number with 4bits +typedef struct +{ + char delta:4; +} TssiDeltaInfo; +#endif /* RTMP_INTERNAL_TX_ALC */ + +extern REG_PAIR RT5350_RFRegTable[]; +extern UCHAR RT5350_NUM_RF_REG_PARMS; +extern REG_PAIR RT5350_BBPRegTable[]; +extern UCHAR RT5350_NUM_BBP_REG_PARMS; +extern RTMP_REG_PAIR RT5350_MACRegTable[]; +extern UCHAR RT5350_NUM_MAC_REG_PARMS; + +#ifdef CONFIG_RALINK_RT5350 +#define PROCREG_DIR "rt5350" +#endif // CONFIG_RALINK_RT5350 // + +VOID RT5350_Init( + IN struct _RTMP_ADAPTER *pAd); + +VOID NICInitRT5350MacRegisters( + IN struct _RTMP_ADAPTER *pAd); + +VOID NICInitRT5350BbpRegisters( + IN struct _RTMP_ADAPTER *pAd); + +VOID NICInitRT5350RFRegisters( + IN struct _RTMP_ADAPTER *pAd); + +VOID RT5350_RxSensitivityTuning( + IN struct _RTMP_ADAPTER *pAd); + +UCHAR RT5350_ChipAGCAdjust( + IN struct _RTMP_ADAPTER *pAd, + IN CHAR Rssi, + IN UCHAR OrigR66Value); + +VOID RT5350_ChipBBPAdjust( + IN struct _RTMP_ADAPTER *pAd); + +VOID RT5350_ChipSwitchChannel( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR Channel, + IN BOOLEAN bScan); + +VOID RT5350_AsicInitDesiredTSSITable( + IN struct _RTMP_ADAPTER *pAd); + +VOID *RT5350_AsicTxAlcTxPwrAdjOverRF( + IN struct _RTMP_ADAPTER *pAd, + IN VOID *pTxPowerTuningEntrySrc); + +VOID RT5350_RTMPSetAGCInitValue( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR BandWidth); + +VOID RT5350_AsicTxAlcGetAutoAgcOffset( + IN struct _RTMP_ADAPTER *pAd, + IN PCHAR pDeltaPwr, + IN PCHAR pTotalDeltaPwr, + IN PCHAR pAgcCompensate, + IN PCHAR pDeltaPowerByBbpR1); + +VOID RT5350_InitDesiredTSSITable( + IN struct _RTMP_ADAPTER *pAd); + +VOID RT5350_AsicExtraPowerOverMAC( + IN struct _RTMP_ADAPTER *pAd); + +#endif // RT5350 // +#endif //__RT5350_H__ // + +/* End of rt5350.h */ diff --git a/mt7620/src/include/chip/rt6352.h b/mt7620/src/include/chip/rt6352.h new file mode 100644 index 0000000..5b6df13 --- /dev/null +++ b/mt7620/src/include/chip/rt6352.h @@ -0,0 +1,229 @@ +/**************************************************************************** + * 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 + + +enum CURRENT_TEMPERATURE_MODE { + TEMPERATURE_MODE_NORMAL, + TEMPERATURE_MODE_LOW_LEVEL_1, + TEMPERATURE_MODE_LOW_LEVEL_2, +}; + +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) */ + +#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; \ +} + +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 +UCHAR GetSkuMinPwr( + IN struct _RTMP_ADAPTER *pAd); + +UCHAR GetSkuRatePwr( + IN struct _RTMP_ADAPTER *pAd, + IN CHAR phymode, + 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); +#endif /* SINGLE_SKU_V2 */ + +#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 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 */ +#endif /* RT6352 */ +#endif /*__RT6352_H__ */ +/* End of rt6352.h */ + diff --git a/mt7620/src/include/chip/rtmp_mac.h b/mt7620/src/include/chip/rtmp_mac.h new file mode 100644 index 0000000..18461b6 --- /dev/null +++ b/mt7620/src/include/chip/rtmp_mac.h @@ -0,0 +1,3325 @@ +/* + *************************************************************************** + * 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__ + + + +/* ================================================================================= */ +/* TX / RX ring descriptor format */ +/* ================================================================================= */ + +/* 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 + + +/* */ +/* TXD Wireless Information format for Tx ring and Mgmt Ring */ +/* */ +/*txop : for txop mode */ +/* 0:txop for the MPDU frame will be handles by ASIC by register */ +/* 1/2/3:the MPDU frame is send after PIFS/backoff/SIFS */ +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _TXWI_STRUC { + /* 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; +#ifdef RT6352 + UINT32 TXLUT:1; +#else + UINT32 rsv:1; +#endif /* RT6352 */ + 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; /*tx back off mode 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs only when previous frame exchange is successful. */ + 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 MPDUtotalByteCount:12; + UINT32 WirelessCliID: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 */ + UINT32 rsv3:12; + UINT32 TxPwrAdj:4; + UINT32 rsv2:16; +#endif /* defined(RT5592) || defined(RT6352) */ +} TXWI_STRUC, *PTXWI_STRUC; +#else +typedef struct GNU_PACKED _TXWI_STRUC { + /* 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; +#ifdef RT6352 + UINT32 TXLUT:1; +#else + UINT32 rsv:1; +#endif /* RT6352 */ + 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, MPDUtotalByteCount = 0x38 */ + UINT32 ACK:1; + UINT32 NSEQ:1; + UINT32 BAWinSize:6; + UINT32 WirelessCliID:8; + UINT32 MPDUtotalByteCount:12; + UINT32 PacketId:4; + /*Word2 */ + UINT32 IV; + /*Word3 */ + UINT32 EIV; + +#if defined(RT5592) || defined(RT6352) + /* Word 4 */ + UINT32 rsv2:16; + UINT32 TxPwrAdj:4; + UINT32 rsv3:12; +#endif /* defined(RT5592) || defined(RT6352) */ +} TXWI_STRUC, *PTXWI_STRUC; +#endif + +#ifdef RTMP_RBUS_SUPPORT +#if defined(RT2883) || defined(RT3883) +#define BF_SNR_OFFSET 88 /* Offset added to RXWI BF_SNR to remove 22.0dB offset */ +#endif /* defined(RT2883) || defined(RT3883) */ +#endif /* RTMP_RBUS_SUPPORT */ + +/* */ +/* RXWI wireless information format, in PBF. invisible in driver. */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXWI_STRUC { + /* Word 0 */ + UINT32 TID:4; + UINT32 MPDUtotalByteCount:12; + UINT32 UDF:3; + UINT32 BSSID:3; + UINT32 KeyIndex:2; + UINT32 WirelessCliID:8; + + /* Word 1 */ + UINT32 PHYMODE: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 ShortGI: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) + /* Word 4 */ + INT32 BF_SNR2:8; + INT32 BF_SNR1:8; + INT32 BF_SNR0:8; + INT32 RSSIANT0:8; +#elif defined(RT5592) + /* For Expert Antenna */ + UINT32 STS1_SNR:8; + UINT32 STS0_SNR:8; + UINT32 RX1_RSSI:8; + UINT32 RX0_RSSI:8; +#else + UINT32 rsv3; +#endif /* defined(RT2883) || defined(RT3883) || defined(RT3593) */ + +#if defined(RT5592) || defined(RT6352) + /* Word 5 */ + UINT32 rsv4; +#endif /* defined(RT5592) || defined(RT6352) */ +} RXWI_STRUC, *PRXWI_STRUC; +#else +typedef struct GNU_PACKED _RXWI_STRUC { + /* Word 0 */ + UINT32 WirelessCliID:8; + UINT32 KeyIndex:2; + UINT32 BSSID:3; + UINT32 UDF:3; + UINT32 MPDUtotalByteCount:12; + UINT32 TID:4; + + /* Word 1 */ + UINT32 FRAG:4; + UINT32 SEQUENCE:12; + UINT32 MCS:7; + UINT32 BW:1; + UINT32 ShortGI:1; + UINT32 STBC:2; + UINT32 eTxBF:1; /* eTxBF enable */ + UINT32 Sounding:1; /* Sounding enable */ + UINT32 iTxBF:1; /* iTxBF enable */ + UINT32 PHYMODE: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) + /* Word 4 */ + INT32 RSSIANT0:8; + INT32 BF_SNR0:8; + INT32 BF_SNR1:8; + INT32 BF_SNR2:8; +#elif defined(RT5592) + /* For Expert Antenna */ + UINT32 RX0_RSSI:8; + UINT32 RX1_RSSI:8; + UINT32 STS0_SNR:8; + UINT32 STS1_SNR:8; +#else + UINT32 rsv3; +#endif /* defined(RT2883) || defined(RT3883) || defined(RT3593) */ + +#if defined(RT5592) || defined(RT6352) + /* Word 5 */ + UINT32 rsv4; +#endif /* defined(RT5592) || defined(RT6352) */ +} RXWI_STRUC, *PRXWI_STRUC; +#endif + + +/* ================================================================================= */ +/* Register format */ +/* ================================================================================= */ + + +#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 + +/* */ +/* SCH/DMA registers - base address 0x0200 */ +/* */ +/* INT_SOURCE_CSR: Interrupt source register. Write one to clear corresponding bit */ +/* */ +#define DMA_CSR0 0x200 +#define INT_SOURCE_CSR 0x200 +#ifdef RT_BIG_ENDIAN +typedef union _INT_SOURCE_CSR_STRUC { + struct { +#ifdef CARRIER_DETECTION_SUPPORT + UINT32 :11; + UINT32 RadarINT:1; + UINT32 rsv:2; +#else /* original source code */ + UINT32 :14; +#endif /* CARRIER_DETECTION_SUPPORT */ + 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; +} INT_SOURCE_CSR_STRUC, *PINT_SOURCE_CSR_STRUC; +#else +typedef union _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; +#ifdef CARRIER_DETECTION_SUPPORT + UINT32 rsv:2; + UINT32 RadarINT:1; + UINT32 :11; +#else + UINT32 :14; +#endif /* CARRIER_DETECTION_SUPPORT */ + } field; + UINT32 word; +} INT_SOURCE_CSR_STRUC, *PINT_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; +#ifdef CARRIER_DETECTION_SUPPORT + UINT32 :9; + UINT32 RadarINT:1; + UINT32 rsv:10; +#else + UINT32 :20; +#endif /* CARRIER_DETECTION_SUPPORT */ + 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, *PINT_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; +#ifdef CARRIER_DETECTION_SUPPORT + UINT32 rsv:10; + UINT32 RadarINT:1; + UINT32 :9; +#else + UINT32 :20; +#endif /* CARRIER_DETECTION_SUPPORT */ + UINT32 RxCoherent:1; + UINT32 TxCoherent:1; + } field; + UINT32 word; +} INT_MASK_CSR_STRUC, *PINT_MASK_CSR_STRUC; +#endif + +#define WPDMA_GLO_CFG 0x208 +#ifdef RT_BIG_ENDIAN +typedef union _WPDMA_GLO_CFG_STRUC { + struct { + UINT32 HDR_SEG_LEN:16; +#ifdef DESC_32B_SUPPORT + UINT32 RXHdrScater:7; + UINT32 Desc32BEn:1; +#else + UINT32 RXHdrScater: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 RXHdrScater:8; +#endif /* DESC_32B_SUPPORT */ + UINT32 HDR_SEG_LEN:16; + } field; + UINT32 word; +} WPDMA_GLO_CFG_STRUC, *PWPDMA_GLO_CFG_STRUC; +#endif + +#define WPDMA_RST_IDX 0x20c +#ifdef RT_BIG_ENDIAN +typedef union _WPDMA_RST_IDX_STRUC { + struct { + UINT32 :15; + UINT32 RST_DRX_IDX0:1; + UINT32 rsv:10; + 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 rsv:10; + UINT32 RST_DRX_IDX0:1; + UINT32 :15; + } 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 +#define WMM_AIFSN_CFG 0x0214 +#ifdef RT_BIG_ENDIAN +typedef union _AIFSN_CSR_STRUC { + struct { + UINT32 Rsv:16; + 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, *PAIFSN_CSR_STRUC; +#else +typedef union _AIFSN_CSR_STRUC { + struct { + UINT32 Aifsn0:4; /* for AC_BE */ + UINT32 Aifsn1:4; /* for AC_BK */ + UINT32 Aifsn2:4; /* for AC_VI */ + UINT32 Aifsn3:4; /* for AC_VO */ + UINT32 Rsv:16; + } field; + UINT32 word; +} AIFSN_CSR_STRUC, *PAIFSN_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 Rsv:16; + 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, *PCWMIN_CSR_STRUC; +#else +typedef union _CWMIN_CSR_STRUC { + struct { + UINT32 Cwmin0:4; /* for AC_BE */ + UINT32 Cwmin1:4; /* for AC_BK */ + UINT32 Cwmin2:4; /* for AC_VI */ + UINT32 Cwmin3:4; /* for AC_VO */ + UINT32 Rsv:16; + } field; + UINT32 word; +} CWMIN_CSR_STRUC, *PCWMIN_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 Rsv:16; + 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, *PCWMAX_CSR_STRUC; +#else +typedef union _CWMAX_CSR_STRUC { + struct { + UINT32 Cwmax0:4; /* for AC_BE */ + UINT32 Cwmax1:4; /* for AC_BK */ + UINT32 Cwmax2:4; /* for AC_VI */ + UINT32 Cwmax3:4; /* for AC_VO */ + UINT32 Rsv:16; + } field; + UINT32 word; +} CWMAX_CSR_STRUC, *PCWMAX_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 { + USHORT Ac1Txop; /* for AC_BE, in unit of 32us */ + USHORT Ac0Txop; /* for AC_BK, in unit of 32us */ + } field; + UINT32 word; +} AC_TXOP_CSR0_STRUC, *PAC_TXOP_CSR0_STRUC; +#else +typedef union _AC_TXOP_CSR0_STRUC { + struct { + USHORT Ac0Txop; /* for AC_BK, in unit of 32us */ + USHORT Ac1Txop; /* for AC_BE, in unit of 32us */ + } field; + UINT32 word; +} AC_TXOP_CSR0_STRUC, *PAC_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 { + USHORT Ac3Txop; /* for AC_VO, in unit of 32us */ + USHORT Ac2Txop; /* for AC_VI, in unit of 32us */ + } field; + UINT32 word; +} AC_TXOP_CSR1_STRUC, *PAC_TXOP_CSR1_STRUC; +#else +typedef union _AC_TXOP_CSR1_STRUC { + struct { + USHORT Ac2Txop; /* for AC_VI, in unit of 32us */ + USHORT Ac3Txop; /* for AC_VO, in unit of 32us */ + } field; + UINT32 word; +} AC_TXOP_CSR1_STRUC, *PAC_TXOP_CSR1_STRUC; +#endif + + +#define RINGREG_DIFF 0x10 +#define GPIO_CTRL_CFG 0x0228 /*MAC_CSR13 */ +#define MCU_CMD_CFG 0x022c +#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 USB_DMA_CFG 0x02a0 +#ifdef RT_BIG_ENDIAN +typedef union _USB_DMA_CFG_STRUC { + struct { + UINT32 TxBusy:1; /*USB DMA TX FSM busy . debug only */ + UINT32 RxBusy:1; /*USB DMA RX FSM busy . debug only */ + UINT32 EpoutValid:6; /*OUT endpoint data valid. debug only */ + UINT32 TxBulkEn:1; /*Enable USB DMA Tx */ + UINT32 RxBulkEn:1; /*Enable USB DMA Rx */ + UINT32 RxBulkAggEn:1; /*Enable Rx Bulk Aggregation */ + UINT32 TxopHalt:1; /*Halt TXOP count down when TX buffer is full. */ + UINT32 TxClear:1; /*Clear USB DMA TX path */ + UINT32 rsv:2; + UINT32 phyclear:1; /*phy watch dog enable. write 1 */ + UINT32 RxBulkAggLmt:8; /*Rx Bulk Aggregation Limit in unit of 1024 bytes */ + UINT32 RxBulkAggTOut:8; /*Rx Bulk Aggregation TimeOut in unit of 33ns */ + } field; + UINT32 word; +} USB_DMA_CFG_STRUC, *PUSB_DMA_CFG_STRUC; +#else +typedef union _USB_DMA_CFG_STRUC { + struct { + UINT32 RxBulkAggTOut:8; /*Rx Bulk Aggregation TimeOut in unit of 33ns */ + UINT32 RxBulkAggLmt:8; /*Rx Bulk Aggregation Limit in unit of 256 bytes */ + UINT32 phyclear:1; /*phy watch dog enable. write 1 */ + UINT32 rsv:2; + UINT32 TxClear:1; /*Clear USB DMA TX path */ + UINT32 TxopHalt:1; /*Halt TXOP count down when TX buffer is full. */ + UINT32 RxBulkAggEn:1; /*Enable Rx Bulk Aggregation */ + UINT32 RxBulkEn:1; /*Enable USB DMA Rx */ + UINT32 TxBulkEn:1; /*Enable USB DMA Tx */ + UINT32 EpoutValid:6; /*OUT endpoint data valid */ + UINT32 RxBusy:1; /*USB DMA RX FSM busy */ + UINT32 TxBusy:1; /*USB DMA TX FSM busy */ + } field; + UINT32 word; +} USB_DMA_CFG_STRUC, *PUSB_DMA_CFG_STRUC; +#endif + +#define US_CYC_CNT 0x02a4 +#ifdef BIG_ENDIAN +typedef union _US_CYC_CNT_STRUC { + struct { + ULONG rsv2:7; + ULONG TestEn:1; + ULONG TestSel:8; + ULONG rsv1:7; + ULONG MiscModeEn:1; + ULONG UsCycCnt:8; + } field; + ULONG word; +} US_CYC_CNT_STRUC, *PUS_CYC_CNT_STRUC; +#else +typedef union _US_CYC_CNT_STRUC { + struct { + ULONG UsCycCnt:8; + ULONG MiscModeEn:1; + ULONG rsv1:7; + ULONG TestSel:8; + ULONG TestEn:1; + ULONG rsv2:7; + } field; + ULONG word; +} US_CYC_CNT_STRUC, *PUS_CYC_CNT_STRUC; +#endif + +/* */ +/* 3 PBF registers */ +/* */ +/* */ +/* Most are for debug. Driver doesn't touch PBF register. */ +#define PBF_SYS_CTRL 0x0400 + +#ifdef RT_BIG_ENDIAN +typedef union _PBF_SYS_CTRL_STRUC +{ + struct + { + ULONG Reserved5:12; /* Reserved */ + ULONG SHR_MSEL:1; /* Shared memory access selection */ + ULONG PBF_MSEL:2; /* Packet buffer memory access selection */ + ULONG HST_PM_SEL:1; /* The write selection of the host program RAM */ + ULONG Reserved4:1; /* Reserved */ + ULONG CAP_MODE:1; /* Packet buffer capture mode */ + ULONG Reserved3:1; /* Reserved */ + ULONG CLK_SEL:1; /* MAC/PBF clock source selection */ + ULONG PBF_CLK_EN:1; /* PBF clock enable */ + ULONG MAC_CLK_EN:1; /* MAC clock enable */ + ULONG DMA_CLK_EN:1; /* DMA clock enable */ + ULONG Reserved2:1; /* Reserved */ + ULONG MCU_READY:1; /* MCU ready */ + ULONG Reserved1:2; /* Reserved */ + ULONG ASY_RESET:1; /* ASYNC interface reset */ + ULONG PBF_RESET:1; /* PBF hardware reset */ + ULONG MAC_RESET:1; /* MAC hardware reset */ + ULONG DMA_RESET:1; /* DMA hardware reset */ + ULONG MCU_RESET:1; /* MCU hardware reset */ + } field; + + ULONG word; +} PBF_SYS_CTRL_STRUC, *PPBF_SYS_CTRL_STRUC; +#else +typedef union _PBF_SYS_CTRL_STRUC +{ + struct + { + ULONG MCU_RESET:1; /* MCU hardware reset */ + ULONG DMA_RESET:1; /* DMA hardware reset */ + ULONG MAC_RESET:1; /* MAC hardware reset */ + ULONG PBF_RESET:1; /* PBF hardware reset */ + ULONG ASY_RESET:1; /* ASYNC interface reset */ + ULONG Reserved1:2; /* Reserved */ + ULONG MCU_READY:1; /* MCU ready */ + ULONG Reserved2:1; /* Reserved */ + ULONG DMA_CLK_EN:1; /* DMA clock enable */ + ULONG MAC_CLK_EN:1; /* MAC clock enable */ + ULONG PBF_CLK_EN:1; /* PBF clock enable */ + ULONG CLK_SEL:1; /* MAC/PBF clock source selection */ + ULONG Reserved3:1; /* Reserved */ + ULONG CAP_MODE:1; /* Packet buffer capture mode */ + ULONG Reserved4:1; /* Reserved */ + ULONG HST_PM_SEL:1; /* The write selection of the host program RAM */ + ULONG PBF_MSEL:2; /* Packet buffer memory access selection */ + ULONG SHR_MSEL:1; /* Shared memory access selection */ + ULONG Reserved5:12; /* Reserved */ + } field; + + ULONG word; +} PBF_SYS_CTRL_STRUC, *PPBF_SYS_CTRL_STRUC; +#endif + +#define PBF_CFG 0x0408 +#define PBF_MAX_PCNT 0x040C +#define PBF_CTRL 0x0410 +#define PBF_INT_STA 0x0414 +#define PBF_INT_ENA 0x0418 +#define TXRXQ_STA 0x0434 +#define TXRXQ_PCNT 0x0438 +#define PBF_DBG 0x043c +#define PBF_CAP_CTRL 0x0440 +#define MCU_INT_STATUS 0x0414 + + +#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, *PINTERNAL_1_STRUCT; +#else +typedef union _TX_ATTENUATION_CTRL_STRUC { + 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, *PINTERNAL_1_STRUCT; +#endif + +#define RF_DBG1 0x050C +#define RF_CONTROL0 0x0518 +#define 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 + +/* */ +/* 4 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 { + USHORT ASICVer; /* version : 2860 */ + USHORT ASICRev; /* reversion : 0 */ + } field; + UINT32 word; +} ASIC_VER_ID_STRUC, *PASIC_VER_ID_STRUC; +#else +typedef union _ASIC_VER_ID_STRUC { + struct { + USHORT ASICRev; /* reversion : 0 */ + USHORT ASICVer; /* version : 2860 */ + } field; + UINT32 word; +} ASIC_VER_ID_STRUC, *PASIC_VER_ID_STRUC; +#endif +#define MAC_SYS_CTRL 0x1004 /*MAC_CSR1 */ +#define MAC_ADDR_DW0 0x1008 /* MAC ADDR DW0 */ +#define MAC_ADDR_DW1 0x100c /* MAC ADDR DW1 */ +/* */ +/* MAC_CSR2: STA MAC register 0 */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _MAC_DW0_STRUC { + struct { + UCHAR Byte3; /* MAC address byte 3 */ + UCHAR Byte2; /* MAC address byte 2 */ + UCHAR Byte1; /* MAC address byte 1 */ + UCHAR Byte0; /* MAC address byte 0 */ + } field; + UINT32 word; +} MAC_DW0_STRUC, *PMAC_DW0_STRUC; +#else +typedef union _MAC_DW0_STRUC { + struct { + UCHAR Byte0; /* MAC address byte 0 */ + UCHAR Byte1; /* MAC address byte 1 */ + UCHAR Byte2; /* MAC address byte 2 */ + UCHAR Byte3; /* MAC address byte 3 */ + } field; + UINT32 word; +} MAC_DW0_STRUC, *PMAC_DW0_STRUC; +#endif + +/* */ +/* MAC_CSR3: STA MAC register 1 */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _MAC_DW1_STRUC { + struct { + UCHAR Rsvd1; + UCHAR U2MeMask; + UCHAR Byte5; /* MAC address byte 5 */ + UCHAR Byte4; /* MAC address byte 4 */ + } field; + UINT32 word; +} MAC_DW1_STRUC, *PMAC_DW1_STRUC; +#else +typedef union _MAC_DW1_STRUC { + struct { + UCHAR Byte4; /* MAC address byte 4 */ + UCHAR Byte5; /* MAC address byte 5 */ + UCHAR U2MeMask; + UCHAR Rsvd1; + } field; + UINT32 word; +} MAC_DW1_STRUC, *PMAC_DW1_STRUC; +#endif + +#define MAC_BSSID_DW0 0x1010 /* MAC BSSID DW0 */ +#define MAC_BSSID_DW1 0x1014 /* MAC BSSID DW1 */ + +/* */ +/* MAC_CSR5: BSSID register 1 */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _MAC_CSR5_STRUC { + struct { + USHORT Rsvd:11; + USHORT MBssBcnNum:3; + USHORT BssIdMode:2; /* 0: one BSSID, 10: 4 BSSID, 01: 2 BSSID , 11: 8BSSID */ + UCHAR Byte5; /* BSSID byte 5 */ + UCHAR Byte4; /* BSSID byte 4 */ + } field; + UINT32 word; +} MAC_CSR5_STRUC, *PMAC_CSR5_STRUC; +#else +typedef union _MAC_CSR5_STRUC { + struct { + UCHAR Byte4; /* BSSID byte 4 */ + UCHAR Byte5; /* BSSID byte 5 */ + USHORT BssIdMask:2; /* 0: one BSSID, 10: 4 BSSID, 01: 2 BSSID , 11: 8BSSID */ + USHORT MBssBcnNum:3; + USHORT Rsvd:11; + } field; + UINT32 word; +} MAC_CSR5_STRUC, *PMAC_CSR5_STRUC; +#endif + +#define MAX_LEN_CFG 0x1018 /* rt2860b max 16k bytes. bit12:13 Maximum PSDU length (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16 */ +#define BBP_CSR_CFG 0x101c /* */ +/* */ +/* BBP_CSR_CFG: BBP serial control register */ +/* */ +#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, *PBBP_CSR_CFG_STRUC; +#else +typedef union _BBP_CSR_CFG_STRUC { + struct { + UINT32 Value:8; /* Register value to program into BBP */ + UINT32 RegNum:8; /* Selected BBP register */ + UINT32 fRead:1; /* 0: Write BBP, 1: Read BBP */ + UINT32 Busy:1; /* 1: ASIC is busy execute BBP programming. */ + UINT32 BBP_PAR_DUR:1; /* 0: 4 MAC clock cycles 1: 8 MAC clock cycles */ + UINT32 BBP_RW_MODE:1; /* 0: use serial mode 1:parallel */ + UINT32 :12; + } field; + UINT32 word; +} BBP_CSR_CFG_STRUC, *PBBP_CSR_CFG_STRUC; +#endif +#define RF_CSR_CFG0 0x1020 +/* */ +/* RF_CSR_CFG: RF control register */ +/* */ +#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, *PRF_CSR_CFG0_STRUC; +#else +typedef union _RF_CSR_CFG0_STRUC { + struct { + UINT32 RegIdAndContent:24; /* Register value to program into BBP */ + UINT32 bitwidth:5; /* Selected BBP register */ + UINT32 StandbyMode:1; /* 0: high when stand by 1: low when standby */ + UINT32 Sel:1; /* 0:RF_LE0 activate 1:RF_LE1 activate */ + UINT32 Busy:1; /* 0: idle 1: 8busy */ + } field; + UINT32 word; +} RF_CSR_CFG0_STRUC, *PRF_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, *PRF_CSR_CFG1_STRUC; +#else +typedef union _RF_CSR_CFG1_STRUC { + struct { + UINT32 RegIdAndContent:24; /* Register value to program into BBP */ + 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 rsv:7; /* 0: idle 1: 8busy */ + } field; + UINT32 word; +} RF_CSR_CFG1_STRUC, *PRF_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, *PRF_CSR_CFG2_STRUC; +#else +typedef union _RF_CSR_CFG2_STRUC { + struct { + UINT32 RegIdAndContent:24; /* Register value to program into BBP */ + UINT32 rsv:8; /* 0: idle 1: 8busy */ + } field; + UINT32 word; +} RF_CSR_CFG2_STRUC, *PRF_CSR_CFG2_STRUC; +#endif +#define LED_CFG 0x102c /* MAC_CSR14 */ +#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, *PLED_CFG_STRUC; +#else +typedef union _LED_CFG_STRUC { + struct { + UINT32 OnPeriod:8; /* blinking on period unit 1ms */ + UINT32 OffPeriod:8; /* blinking off period unit 1ms */ + UINT32 SlowBlinkPeriod:6; /* slow blinking period. unit:1ms */ + UINT32 rsv:2; + UINT32 RLedMode:2; /* red Led Mode 0: off1: blinking upon TX2: periodic slow blinking3: always on */ + UINT32 GLedMode:2; /* green Led Mode */ + UINT32 YLedMode:2; /* yellow Led Mode */ + UINT32 LedPolar:1; /* Led Polarity. 0: active low1: active high */ + UINT32 :1; + } field; + UINT32 word; +} LED_CFG_STRUC, *PLED_CFG_STRUC; +#endif + +/* */ +/* 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 + { + UCHAR TxChainAddr0L_Byte3; /* Destination MAC address of Tx chain0 (byte 3) */ + UCHAR TxChainAddr0L_Byte2; /* Destination MAC address of Tx chain0 (byte 2) */ + UCHAR TxChainAddr0L_Byte1; /* Destination MAC address of Tx chain0 (byte 1) */ + UCHAR TxChainAddr0L_Byte0; /* Destination MAC address of Tx chain0 (byte 0) */ + } field; + + UINT32 word; +} TX_CHAIN_ADDR0_L_STRUC, *PTX_CHAIN_ADDR0_L_STRUC; +#else +typedef union _TX_CHAIN_ADDR0_L_STRUC +{ + struct + { + UCHAR TxChainAddr0L_Byte0; /* Destination MAC address of Tx chain0 (byte 0) */ + UCHAR TxChainAddr0L_Byte1; /* Destination MAC address of Tx chain0 (byte 1) */ + UCHAR TxChainAddr0L_Byte2; /* Destination MAC address of Tx chain0 (byte 2) */ + UCHAR TxChainAddr0L_Byte3; /* Destination MAC address of Tx chain0 (byte 3) */ + } field; + + UINT32 word; +} TX_CHAIN_ADDR0_L_STRUC, *PTX_CHAIN_ADDR0_L_STRUC; +#endif + +#define TX_CHAIN_ADDR0_H 0x1048 + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR0_H_STRUC +{ + struct + { + USHORT Reserved:12; /* Reserved */ + USHORT TxChainSel0:4; /* Selection value of Tx chain0 */ + UCHAR TxChainAddr0H_Byte5; /* Destination MAC address of Tx chain0 (byte 5) */ + UCHAR TxChainAddr0H_Byte4; /* Destination MAC address of Tx chain0 (byte 4) */ + } field; + + UINT32 word; +} TX_CHAIN_ADDR0_H_STRUC, *PTX_CHAIN_ADDR0_H_STRUC; +#else +typedef union _TX_CHAIN_ADDR0_H_STRUC +{ + struct + { + UCHAR TxChainAddr0H_Byte4; /* Destination MAC address of Tx chain0 (byte 4) */ + UCHAR TxChainAddr0H_Byte5; /* Destination MAC address of Tx chain0 (byte 5) */ + USHORT TxChainSel0:4; /* Selection value of Tx chain0 */ + USHORT Reserved:12; /* Reserved */ + } field; + + UINT32 word; +} TX_CHAIN_ADDR0_H_STRUC, *PTX_CHAIN_ADDR0_HA_STRUC; +#endif + +#define TX_CHAIN_ADDR1_L 0x104C + +#ifdef BIG_ENDIAN +typedef union _TX_CHAIN_ADDR1_L_STRUC +{ + struct + { + UCHAR TxChainAddr1L_Byte3; /* Destination MAC address of Tx chain1 (byte 3) */ + UCHAR TxChainAddr1L_Byte2; /* Destination MAC address of Tx chain1 (byte 2) */ + UCHAR TxChainAddr1L_Byte1; /* Destination MAC address of Tx chain1 (byte 1) */ + UCHAR 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 + { + UCHAR TxChainAddr1L_Byte0; /* Destination MAC address of Tx chain1 (byte 0) */ + UCHAR TxChainAddr1L_Byte1; /* Destination MAC address of Tx chain1 (byte 1) */ + UCHAR TxChainAddr1L_Byte2; /* Destination MAC address of Tx chain1 (byte 2) */ + UCHAR TxChainAddr1L_Byte3; /* Destination MAC address of Tx chain1 (byte 3) */ + } field; + + UINT32 word; +} TX_CHAIN_ADDR1_L_STRUC, *PTX_CHAIN_ADDR1_L_STRUC; +#endif + +#define TX_CHAIN_ADDR1_H 0x1050 + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR1_H_STRUC +{ + struct + { + USHORT Reserved:12; /* Reserved */ + USHORT TxChainSel0:4; /* Selection value of Tx chain0 */ + UCHAR TxChainAddr1H_Byte5; /* Destination MAC address of Tx chain1 (byte 5) */ + UCHAR TxChainAddr1H_Byte4; /* Destination MAC address of Tx chain1 (byte 4) */ + } field; + + UINT32 word; +} TX_CHAIN_ADDR1_H_STRUC, *PTX_CHAIN_ADDR1_H_STRUC; +#else +typedef union _TX_CHAIN_ADDR1_H_STRUC +{ + struct + { + UCHAR TxChainAddr1H_Byte4; /* Destination MAC address of Tx chain1 (byte 4) */ + UCHAR TxChainAddr1H_Byte5; /* Destination MAC address of Tx chain1 (byte 5) */ + USHORT TxChainSel0:4; /* Selection value of Tx chain0 */ + USHORT Reserved:12; /* Reserved */ + } field; + + UINT32 word; +} TX_CHAIN_ADDR1_H_STRUC, *PTX_CHAIN_ADDR1_HA_STRUC; +#endif + +#define TX_CHAIN_ADDR2_L 0x1054 + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR2_L_STRUC +{ + struct + { + UCHAR TxChainAddr2L_Byte3; /* Destination MAC address of Tx chain2 (byte 3) */ + UCHAR TxChainAddr2L_Byte2; /* Destination MAC address of Tx chain2 (byte 2) */ + UCHAR TxChainAddr2L_Byte1; /* Destination MAC address of Tx chain2 (byte 1) */ + UCHAR TxChainAddr2L_Byte0; /* Destination MAC address of Tx chain2 (byte 0) */ + } field; + + UINT32 word; +} TX_CHAIN_ADDR2_L_STRUC, *PTX_CHAIN_ADDR2_L_STRUC; +#else +typedef union _TX_CHAIN_ADDR2_L_STRUC +{ + struct + { + UCHAR TxChainAddr2L_Byte0; /* Destination MAC address of Tx chain2 (byte 0) */ + UCHAR TxChainAddr2L_Byte1; /* Destination MAC address of Tx chain2 (byte 1) */ + UCHAR TxChainAddr2L_Byte2; /* Destination MAC address of Tx chain2 (byte 2) */ + UCHAR TxChainAddr2L_Byte3; /* Destination MAC address of Tx chain2 (byte 3) */ + } field; + + UINT32 word; +} TX_CHAIN_ADDR2_L_STRUC, *PTX_CHAIN_ADDR2_L_STRUC; +#endif + +#define TX_CHAIN_ADDR2_H 0x1058 + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR2_H_STRUC +{ + struct + { + USHORT Reserved:12; /* Reserved */ + USHORT TxChainSel0:4; /* Selection value of Tx chain0 */ + UCHAR TxChainAddr2H_Byte5; /* Destination MAC address of Tx chain2 (byte 5) */ + UCHAR TxChainAddr2H_Byte4; /* Destination MAC address of Tx chain2 (byte 4) */ + } field; + + UINT32 word; +} TX_CHAIN_ADDR2_H_STRUC, *PTX_CHAIN_ADDR2_H_STRUC; +#else +typedef union _TX_CHAIN_ADDR2_H_STRUC +{ + struct + { + UCHAR TxChainAddr2H_Byte4; /* Destination MAC address of Tx chain2 (byte 4) */ + UCHAR TxChainAddr2H_Byte5; /* Destination MAC address of Tx chain2 (byte 5) */ + USHORT TxChainSel0:4; /* Selection value of Tx chain0 */ + USHORT Reserved:12; /* Reserved */ + } field; + + UINT32 word; +} TX_CHAIN_ADDR2_H_STRUC, *PTX_CHAIN_ADDR2_HA_STRUC; +#endif + +#define TX_CHAIN_ADDR3_L 0x105C + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR3_L_STRUC +{ + struct + { + UCHAR TxChainAddr3L_Byte3; /* Destination MAC address of Tx chain3 (byte 3) */ + UCHAR TxChainAddr3L_Byte2; /* Destination MAC address of Tx chain3 (byte 2) */ + UCHAR TxChainAddr3L_Byte1; /* Destination MAC address of Tx chain3 (byte 1) */ + UCHAR 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 + { + UCHAR TxChainAddr3L_Byte0; /* Destination MAC address of Tx chain3 (byte 0) */ + UCHAR TxChainAddr3L_Byte1; /* Destination MAC address of Tx chain3 (byte 1) */ + UCHAR TxChainAddr3L_Byte2; /* Destination MAC address of Tx chain3 (byte 2) */ + UCHAR TxChainAddr3L_Byte3; /* Destination MAC address of Tx chain3 (byte 3) */ + } field; + + UINT32 word; +} TX_CHAIN_ADDR3_L_STRUC, *PTX_CHAIN_ADDR3_L_STRUC; +#endif + +#define TX_CHAIN_ADDR3_H 0x1060 + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR3_H_STRUC +{ + struct + { + USHORT Reserved:12; /* Reserved */ + USHORT TxChainSel0:4; /* Selection value of Tx chain0 */ + UCHAR TxChainAddr3H_Byte5; /* Destination MAC address of Tx chain3 (byte 5) */ + UCHAR 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 + { + UCHAR TxChainAddr3H_Byte4; /* Destination MAC address of Tx chain3 (byte 4) */ + UCHAR TxChainAddr3H_Byte5; /* Destination MAC address of Tx chain3 (byte 5) */ + USHORT TxChainSel0:4; /* Selection value of Tx chain0 */ + USHORT Reserved:12; /* Reserved */ + } field; + + UINT32 word; +} TX_CHAIN_ADDR3_H_STRUC, *PTX_CHAIN_ADDR3_HA_STRUC; +#endif + +/* */ +/* 4.2 MAC TIMING configuration registers (offset:0x1100) */ +/* */ +#define XIFS_TIME_CFG 0x1100 /* MAC_CSR8 MAC_CSR9 */ +#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, *PIFS_SLOT_CFG_STRUC; +#else +typedef union _IFS_SLOT_CFG_STRUC { + struct { + UINT32 CckmSifsTime:8; /* unit 1us. Applied after CCK RX/TX */ + UINT32 OfdmSifsTime:8; /* unit 1us. Applied after OFDM RX/TX */ + UINT32 OfdmXifsTime:4; /*OFDM SIFS. unit 1us. Applied after OFDM RX when MAC doesn't reference BBP signal BBRXEND */ + UINT32 EIFS:9; /* unit 1us */ + UINT32 BBRxendEnable:1; /* reference RXEND signal to begin XIFS defer */ + UINT32 rsv:2; + } field; + UINT32 word; +} IFS_SLOT_CFG_STRUC, *PIFS_SLOT_CFG_STRUC; +#endif + +#define BKOFF_SLOT_CFG 0x1104 /* mac_csr9 last 8 bits */ +#define NAV_TIME_CFG 0x1108 /* NAV (MAC_CSR15) */ +#define CH_TIME_CFG 0x110C /* Count as channel busy */ +#define PBF_LIFE_TIMER 0x1110 /*TX/RX MPDU timestamp timer (free run)Unit: 1us */ +#define BCN_TIME_CFG 0x1114 /* TXRX_CSR9 */ + +#define BCN_OFFSET0 0x042C +#define BCN_OFFSET1 0x0430 +#ifdef SPECIFIC_BCN_BUF_SUPPORT +#define BCN_OFFSET2 0x0444 +#define BCN_OFFSET3 0x0448 +#endif /* SPECIFIC_BCN_BUF_SUPPORT */ + +/* */ +/* BCN_TIME_CFG : Synchronization control register */ +/* */ +#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, *PBCN_TIME_CFG_STRUC; +#else +typedef union _BCN_TIME_CFG_STRUC { + struct { + UINT32 BeaconInterval:16; /* in unit of 1/16 TU */ + UINT32 bTsfTicking:1; /* Enable TSF auto counting */ + UINT32 TsfSyncMode:2; /* Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode */ + UINT32 bTBTTEnable:1; + UINT32 bBeaconGen:1; /* Enable beacon generator */ + UINT32 :3; + UINT32 TxTimestampCompensate:8; + } field; + UINT32 word; +} BCN_TIME_CFG_STRUC, *PBCN_TIME_CFG_STRUC; +#endif +#define TBTT_SYNC_CFG 0x1118 /* txrx_csr10 */ +#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. TXRX_CSR14 */ +#define INT_TIMER_CFG 0x1128 /* */ +#define INT_TIMER_EN 0x112c /* GP-timer and pre-tbtt Int enable */ +#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 */ +/* */ +/* 4.2 MAC POWER configuration registers (offset:0x1200) */ +/* */ +#define MAC_STATUS_CFG 0x1200 /* old MAC_CSR12 */ +#define PWR_PIN_CFG 0x1204 /* old MAC_CSR12 */ +#define AUTO_WAKEUP_CFG 0x1208 /* old MAC_CSR10 */ + +#define MIMO_PS_CFG 0x1210 + +#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 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 + + +/* */ +/* AUTO_WAKEUP_CFG: Manual power control / status register */ +/* */ +#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, *PAUTO_WAKEUP_STRUC; +#else +typedef union _AUTO_WAKEUP_STRUC { + struct { + UINT32 AutoLeadTime:8; + UINT32 NumofSleepingTbtt:7; /* ForceWake has high privilege than PutToSleep when both set */ + UINT32 EnableAutoWakeup:1; /* 0:sleep, 1:awake */ + UINT32 :16; + } field; + UINT32 word; +} AUTO_WAKEUP_STRUC, *PAUTO_WAKEUP_STRUC; +#endif +/* */ +/* 4.3 MAC TX configuration registers (offset:0x1300) */ +/* */ + +#define EDCA_AC0_CFG 0x1300 /*AC_TXOP_CSR0 0x3474 */ +#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, *PEDCA_AC_CFG_STRUC; +#else +typedef union _EDCA_AC_CFG_STRUC { + struct { + UINT32 AcTxop:8; /* in unit of 32us */ + UINT32 Aifsn:4; /* # of slot time */ + UINT32 Cwmin:4; /* */ + UINT32 Cwmax:4; /*unit power of 2 */ + UINT32 :12; /* */ + } field; + UINT32 word; +} EDCA_AC_CFG_STRUC, *PEDCA_AC_CFG_STRUC; +#endif + +/* */ +/* Default Tx power */ +/* */ +#define DEFAULT_TX_POWER 0x6 + +#define EDCA_TID_AC_MAP 0x1310 +#define TX_PWR_CFG_0 0x1314 +#define TX_PWR_CFG_0_EXT 0x1390 +#define TX_PWR_CFG_1 0x1318 +#define TX_PWR_CFG_1_EXT 0x1394 +#define TX_PWR_CFG_2 0x131C +#define TX_PWR_CFG_2_EXT 0x1398 +#define TX_PWR_CFG_3 0x1320 +#define TX_PWR_CFG_3_EXT 0x139C +#define TX_PWR_CFG_4 0x1324 +#define TX_PWR_CFG_4_EXT 0x13A0 +#define TX0_RF_GAIN_CORRECT 0x13A0 +#define TX1_RF_GAIN_CORRECT 0x13A4 +#define TX_PWR_CFG_5 0x1384 +#define TX_PWR_CFG_6 0x1388 +#define TX_PWR_CFG_7 0x13D4 +#define TX_PWR_CFG_8 0x13D8 +#define TX_PWR_CFG_9 0x13DC + +#ifdef RT_BIG_ENDIAN +typedef union _TX_PWR_CFG_STRUC { + struct { + ULONG Byte3:8; + ULONG Byte2:8; + ULONG Byte1:8; + ULONG Byte0:8; + } field; + ULONG word; +} TX_PWR_CFG_STRUC, *PTX_PWR_CFG_STRUC; +#else +typedef union _TX_PWR_CFG_STRUC { + struct { + ULONG Byte0:8; + ULONG Byte1:8; + ULONG Byte2:8; + ULONG Byte3:8; + } field; + ULONG word; +} TX_PWR_CFG_STRUC, *PTX_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, *PTXOP_THRESHOLD_CFG_STRUC; +#else +typedef union _TXOP_THRESHOLD_CFG_STRUC +{ + struct + { + UINT32 RDG_OUT_THRES:8; /* Tx RDG threshold (unit: 32us) */ + UINT32 RDG_IN_THRES:8; /* Rx RDG threshold (unit: 32us) */ + UINT32 CF_END_THRES:8; /* CF-END threshold (unit: 32us) */ + UINT32 TXOP_REM_THRES:8; /* Remaining TXOP threshold (unit: 32us) */ + } field; + + UINT32 word; +} TXOP_THRESHOLD_CFG_STRUC, *PTXOP_THRESHOLD_CFG_STRUC; +#endif + +#define TXOP_CTRL_CFG 0x1340 +#define TX_RTS_CFG 0x1344 + +#define TX_TXBF_CFG_0 0x138c +#define TX_TXBF_CFG_1 0x13A4 +#define TX_TXBF_CFG_2 0x13A8 +#define TX_TXBF_CFG_3 0x13AC + +#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, *PTX_RTS_CFG_STRUC; +#else +typedef union _TX_RTS_CFG_STRUC { + struct { + UINT32 AutoRtsRetryLimit:8; + UINT32 RtsThres:16; /* unit:byte */ + UINT32 RtsFbkEn:1; /* enable rts rate fallback */ + UINT32 rsv:7; /* 1: HT non-STBC control frame enable */ + } field; + UINT32 word; +} TX_RTS_CFG_STRUC, *PTX_RTS_CFG_STRUC; +#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, *PTX_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, *PTX_TIMEOUT_CFG_STRUC; +#else +typedef union _TX_TIMEOUT_CFG_STRUC { + struct { + UINT32 rsv:4; + UINT32 MpduLifeTime:4; /* expiration time = 2^(9+MPDU LIFE TIME) us */ + UINT32 RxAckTimeout:8; /* unit:slot. Used for TX precedure */ + UINT32 TxopTimeout:8; /*TXOP timeout value for TXOP truncation. It is recommended that (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT) */ + UINT32 rsv2:8; /* 1: HT non-STBC control frame enable */ + } field; + UINT32 word; +} TX_TIMEOUT_CFG_STRUC, *PTX_TIMEOUT_CFG_STRUC; +#endif + +#define TX_RTY_CFG 0x134c +#define TX_AC_RTY_LIMIT 0x13cc +#define TX_AC_FBK_SPEED 0x13d0 + +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED _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, *PTX_RTY_CFG_STRUC; +#else +typedef union GNU_PACKED _TX_RTY_CFG_STRUC { + struct { + UINT32 ShortRtyLimit:8; /* short retry limit */ + UINT32 LongRtyLimit:8; /*long retry limit */ + UINT32 LongRtyThre:12; /* Long retry threshoold */ + UINT32 NonAggRtyMode:1; /* Non-Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer */ + UINT32 AggRtyMode:1; /* Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer */ + UINT32 TxautoFBEnable:1; /* Tx retry PHY rate auto fallback enable */ + UINT32 rsv:1; /* 1: HT non-STBC control frame enable */ + } field; + UINT32 word; +} TX_RTY_CFG_STRUC, *PTX_RTY_CFG_STRUC; +#endif +#define TX_LINK_CFG 0x1350 +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED _TX_LINK_CFG_STRUC { + struct GNU_PACKED { + 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, *PTX_LINK_CFG_STRUC; +#else +typedef union GNU_PACKED _TX_LINK_CFG_STRUC { + struct GNU_PACKED { + UINT32 RemoteMFBLifeTime:8; /*remote MFB life time. unit : 32us */ + UINT32 MFBEnable:1; /* TX apply remote MFB 1:enable */ + UINT32 RemoteUMFSEnable:1; /* remote unsolicit MFB enable. 0: not apply remote remote unsolicit (MFS=7) */ + UINT32 TxMRQEn:1; /* MCS request TX enable */ + UINT32 TxRDGEn:1; /* RDG TX enable */ + UINT32 TxCFAckEn:1; /* Piggyback CF-ACK enable */ + UINT32 rsv:3; /* */ + UINT32 RemotMFB:8; /* remote MCS feedback */ + UINT32 RemotMFS:8; /*remote MCS feedback sequence number */ + } field; + UINT32 word; +} TX_LINK_CFG_STRUC, *PTX_LINK_CFG_STRUC; +#endif +#define HT_FBK_CFG0 0x1354 +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED _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, *PHT_FBK_CFG0_STRUC; +#else +typedef union GNU_PACKED _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, *PHT_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, *PHT_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, *PHT_FBK_CFG1_STRUC; +#endif +#define LG_FBK_CFG0 0x135c +#ifdef RT_BIG_ENDIAN +typedef union _LG_FBK_CFG0_STRUC { + struct { + UINT32 OFDMMCS7FBK:4; /*initial value is 6 */ + UINT32 OFDMMCS6FBK:4; /*initial value is 5 */ + UINT32 OFDMMCS5FBK:4; /*initial value is 4 */ + UINT32 OFDMMCS4FBK:4; /*initial value is 3 */ + UINT32 OFDMMCS3FBK:4; /*initial value is 2 */ + UINT32 OFDMMCS2FBK:4; /*initial value is 1 */ + UINT32 OFDMMCS1FBK:4; /*initial value is 0 */ + UINT32 OFDMMCS0FBK:4; /*initial value is 0 */ + } field; + UINT32 word; +} LG_FBK_CFG0_STRUC, *PLG_FBK_CFG0_STRUC; +#else +typedef union _LG_FBK_CFG0_STRUC { + struct { + UINT32 OFDMMCS0FBK:4; /*initial value is 0 */ + UINT32 OFDMMCS1FBK:4; /*initial value is 0 */ + UINT32 OFDMMCS2FBK:4; /*initial value is 1 */ + UINT32 OFDMMCS3FBK:4; /*initial value is 2 */ + UINT32 OFDMMCS4FBK:4; /*initial value is 3 */ + UINT32 OFDMMCS5FBK:4; /*initial value is 4 */ + UINT32 OFDMMCS6FBK:4; /*initial value is 5 */ + UINT32 OFDMMCS7FBK:4; /*initial value is 6 */ + } field; + UINT32 word; +} LG_FBK_CFG0_STRUC, *PLG_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; /*initial value is 2 */ + UINT32 CCKMCS2FBK:4; /*initial value is 1 */ + UINT32 CCKMCS1FBK:4; /*initial value is 0 */ + UINT32 CCKMCS0FBK:4; /*initial value is 0 */ + } field; + UINT32 word; +} LG_FBK_CFG1_STRUC, *PLG_FBK_CFG1_STRUC; +#else +typedef union _LG_FBK_CFG1_STRUC { + struct { + UINT32 CCKMCS0FBK:4; /*initial value is 0 */ + UINT32 CCKMCS1FBK:4; /*initial value is 0 */ + UINT32 CCKMCS2FBK:4; /*initial value is 1 */ + UINT32 CCKMCS3FBK:4; /*initial value is 2 */ + UINT32 rsv:16; + } field; + UINT32 word; +} LG_FBK_CFG1_STRUC, *PLG_FBK_CFG1_STRUC; +#endif + +#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, *PTX_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, *PTX_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, *PTX_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, *PTX_FBK_CFG_3S_1_STRUC; +#endif +#endif /* DOT11N_SS3_SUPPORT */ + +/*======================================================= */ +/*================ Protection Paramater================================ */ +/*======================================================= */ +#define CCK_PROT_CFG 0x1364 /*CCK Protection */ +#define ASIC_SHORTNAV 1 +#define ASIC_LONGNAV 2 +#define ASIC_RTS 1 +#define ASIC_CTS 2 +#ifdef RT_BIG_ENDIAN +typedef union _PROT_CFG_STRUC { + struct { + UINT32 rsv:5; + 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, *PPROT_CFG_STRUC; +#else +typedef union _PROT_CFG_STRUC { + struct { + UINT32 ProtectRate:16; /*Protection control frame rate for CCK TX(RTS/CTS/CFEnd). */ + UINT32 ProtectCtrl:2; /*Protection control frame type for CCK TX. 1:RTS/CTS, 2:CTS-to-self, 0:None, 3:rsv */ + UINT32 ProtectNav:2; /*TXOP protection type for CCK TX. 0:None, 1:ShortNAVprotect, 2:LongNAVProtect, 3:rsv */ + UINT32 TxopAllowCck:1; /*CCK TXOP allowance.0:disallow. */ + UINT32 TxopAllowOfdm:1; /*CCK TXOP allowance.0:disallow. */ + UINT32 TxopAllowMM20:1; /*CCK TXOP allowance. 0:disallow. */ + UINT32 TxopAllowMM40:1; /*CCK TXOP allowance.0:disallow. */ + UINT32 TxopAllowGF20:1; /*CCK TXOP allowance.0:disallow. */ + UINT32 TxopAllowGF40:1; /*CCK TXOP allowance.0:disallow. */ + UINT32 RTSThEn:1; /*RTS threshold enable on CCK TX */ + UINT32 rsv:5; + } field; + UINT32 word; +} PROT_CFG_STRUC, *PPROT_CFG_STRUC; +#endif + +#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 */ +#define EXP_CTS_TIME 0x137C /* */ +#define EXP_ACK_TIME 0x1380 /* */ +#ifdef RT6352 +#define TX_FBK_LIMIT 0x1398 +#define TX_ALC_VGA3 0x13C8 +#endif /* RT6352 */ + +/* */ +/* 4.4 MAC RX configuration registers (offset:0x1400) */ +/* */ +#define RX_FILTR_CFG 0x1400 /*TXRX_CSR0 */ +#define AUTO_RSP_CFG 0x1404 /*TXRX_CSR4 */ +/* */ +/* TXRX_CSR4: Auto-Responder/ */ +/* */ +#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, *PAUTO_RSP_CFG_STRUC; +#else +typedef union _AUTO_RSP_CFG_STRUC { + struct { + UINT32 AutoResponderEnable:1; + UINT32 BACAckPolicyEnable:1; /* 0:long, 1:short preamble */ + UINT32 CTS40MMode:1; /* Response CTS 40MHz duplicate mode */ + UINT32 CTS40MRef:1; /* Response CTS 40MHz duplicate mode */ + UINT32 AutoResponderPreamble:1; /* 0:long, 1:short preamble */ + UINT32 rsv:1; /* Power bit value in conrtrol frame */ + UINT32 DualCTSEn:1; /* Power bit value in conrtrol frame */ + UINT32 AckCtsPsmBit:1; /* Power bit value in conrtrol frame */ + UINT32 :24; + } field; + UINT32 word; +} AUTO_RSP_CFG_STRUC, *PAUTO_RSP_CFG_STRUC; +#endif + +#define LEGACY_BASIC_RATE 0x1408 /* TXRX_CSR5 0x3054 */ +#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 */ +#ifdef RT6352 +#define MAC_ADDR_EXT_EN 0x147C +#endif /* RT6352 */ + +/* */ +/* 4.5 MAC Security configuration (offset:0x1500) */ +/* */ +#define TX_SEC_CNT0 0x1500 /* */ +#define RX_SEC_CNT0 0x1504 /* */ +#define CCMP_FC_MUTE 0x1508 /* */ +/* */ +/* 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) */ +/* */ +#define RX_STA_CNT0 0x1700 /* */ +#define RX_STA_CNT1 0x1704 /* */ +#define RX_STA_CNT2 0x1708 /* */ + +/* */ +/* RX_STA_CNT0_STRUC: RX PLCP error count & RX CRC error count */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _RX_STA_CNT0_STRUC { + struct { + USHORT PhyErr; + USHORT CrcErr; + } field; + UINT32 word; +} RX_STA_CNT0_STRUC, *PRX_STA_CNT0_STRUC; +#else +typedef union _RX_STA_CNT0_STRUC { + struct { + USHORT CrcErr; + USHORT PhyErr; + } field; + UINT32 word; +} RX_STA_CNT0_STRUC, *PRX_STA_CNT0_STRUC; +#endif + +/* */ +/* RX_STA_CNT1_STRUC: RX False CCA count & RX LONG frame count */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _RX_STA_CNT1_STRUC { + struct { + USHORT PlcpErr; + USHORT FalseCca; + } field; + UINT32 word; +} RX_STA_CNT1_STRUC, *PRX_STA_CNT1_STRUC; +#else +typedef union _RX_STA_CNT1_STRUC { + struct { + USHORT FalseCca; + USHORT PlcpErr; + } field; + UINT32 word; +} RX_STA_CNT1_STRUC, *PRX_STA_CNT1_STRUC; +#endif + +/* */ +/* RX_STA_CNT2_STRUC: */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _RX_STA_CNT2_STRUC { + struct { + USHORT RxFifoOverflowCount; + USHORT RxDupliCount; + } field; + UINT32 word; +} RX_STA_CNT2_STRUC, *PRX_STA_CNT2_STRUC; +#else +typedef union _RX_STA_CNT2_STRUC { + struct { + USHORT RxDupliCount; + USHORT RxFifoOverflowCount; + } field; + UINT32 word; +} RX_STA_CNT2_STRUC, *PRX_STA_CNT2_STRUC; +#endif +#define TX_STA_CNT0 0x170C /* */ +/* */ +/* STA_CSR3: TX Beacon count */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _TX_STA_CNT0_STRUC { + struct { + USHORT TxBeaconCount; + USHORT TxFailCount; + } field; + UINT32 word; +} TX_STA_CNT0_STRUC, *PTX_STA_CNT0_STRUC; +#else +typedef union _TX_STA_CNT0_STRUC { + struct { + USHORT TxFailCount; + USHORT TxBeaconCount; + } field; + UINT32 word; +} TX_STA_CNT0_STRUC, *PTX_STA_CNT0_STRUC; +#endif +#define TX_STA_CNT1 0x1710 /* */ +/* */ +/* TX_STA_CNT1: TX tx count */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _TX_STA_CNT1_STRUC { + struct { + USHORT TxRetransmit; + USHORT TxSuccess; + } field; + UINT32 word; +} TX_STA_CNT1_STRUC, *PTX_STA_CNT1_STRUC; +#else +typedef union _TX_STA_CNT1_STRUC { + struct { + USHORT TxSuccess; + USHORT TxRetransmit; + } field; + UINT32 word; +} TX_STA_CNT1_STRUC, *PTX_STA_CNT1_STRUC; +#endif +#define TX_STA_CNT2 0x1714 /* */ +/* */ +/* TX_STA_CNT2: TX tx count */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _TX_STA_CNT2_STRUC { + struct { + USHORT TxUnderFlowCount; + USHORT TxZeroLenCount; + } field; + UINT32 word; +} TX_STA_CNT2_STRUC, *PTX_STA_CNT2_STRUC; +#else +typedef union _TX_STA_CNT2_STRUC { + struct { + USHORT TxZeroLenCount; + USHORT TxUnderFlowCount; + } field; + UINT32 word; +} TX_STA_CNT2_STRUC, *PTX_STA_CNT2_STRUC; +#endif +#define TX_STA_FIFO 0x1718 /* */ +/* */ +/* TX_STA_FIFO_STRUC: TX Result for specific PID status fifo register */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED _TX_STA_FIFO_STRUC { + struct { + UINT32 Reserve:2; + UINT32 iTxBF:1; /* iTxBF enable */ + UINT32 Sounding:1; /* Sounding 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, *PTX_STA_FIFO_STRUC; +#else +typedef union GNU_PACKED _TX_STA_FIFO_STRUC { + struct { + UINT32 bValid:1; /* 1:This register contains a valid TX result */ + UINT32 PidType:4; + UINT32 TxSuccess:1; /* Tx No retry success */ + UINT32 TxAggre:1; /* Tx Retry Success */ + UINT32 TxAckRequired:1; /* Tx fail */ + UINT32 wcid:8; /*wireless client index */ + UINT32 SuccessRate:11; /*include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16. */ + UINT32 eTxBF:1; /* eTxBF enable */ + UINT32 Sounding:1; /* Sounding enable */ + UINT32 iTxBF:1; /* iTxBF enable */ + UINT32 Reserve:2; + } field; + UINT32 word; +} TX_STA_FIFO_STRUC, *PTX_STA_FIFO_STRUC; +#endif + +#ifdef FIFO_EXT_SUPPORT + +#define TX_STA_FIFO_EXT 0x1798 /* Only work after RT53xx */ +/* + TX_STA_FIFO_EXT_STRUC: TX retry cnt for specific frame +*/ +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED _TX_STA_FIFO_EXT_STRUC { + struct { + UINT32 Reserve:24; + UINT32 txRtyCnt:8; /* frame Tx retry cnt */ + } field; + UINT32 word; +} TX_STA_FIFO_EXT_STRUC, *PTX_STA_FIFO_EXT_STRUC; +#else +typedef union GNU_PACKED _TX_STA_FIFO_EXT_STRUC { + struct { + UINT32 txRtyCnt:8; /* frame Tx retry cnt */ + UINT32 Reserve:24; + } field; + UINT32 word; +} TX_STA_FIFO_EXT_STRUC, *PTX_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 GNU_PACKED _WCID_TX_CNT_STRUC { + struct { + UINT32 reTryCnt:16; + UINT32 succCnt:16; + } field; + UINT32 word; +} WCID_TX_CNT_STRUC, *PWCID_TX_CNT_STRUC; +#else +typedef union GNU_PACKED _WCID_TX_CNT_STRUC { + struct { + UINT32 succCnt:16; + UINT32 reTryCnt:16; + } field; + UINT32 word; +} WCID_TX_CNT_STRUC, *PWCID_TX_CNT_STRUC; +#endif + + +#define WCID_MAPPING_0 0x178c +#define WCID_MAPPING_1 0x1790 +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED _WCID_MAPPING_STRUC { + struct { + UINT32 wcid3:8; + UINT32 wcid2:8; + UINT32 wcid1:8; + UINT32 wcid0:8; + } field; + UINT32 word; +} WCID_MAPPING_STRUC, *PWCID_MAPPING_STRUC; +#else +typedef union GNU_PACKED _WCID_MAPPING_STRUC { + struct { + UINT32 wcid0:8; + UINT32 wcid1:8; + UINT32 wcid2:8; + UINT32 wcid3:8; + } field; + UINT32 word; +} WCID_MAPPINGT_STRUC, *PWCID_MAPPING_STRUC; +#endif +#endif /* FIFO_EXT_SUPPORT */ + +/* Debug counter */ +#define TX_AGG_CNT 0x171c +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT_STRUC { + struct { + USHORT AggTxCount; + USHORT NonAggTxCount; + } field; + UINT32 word; +} TX_AGG_CNT_STRUC, *PTX_AGG_CNT_STRUC; +#else +typedef union _TX_AGG_CNT_STRUC { + struct { + USHORT NonAggTxCount; + USHORT AggTxCount; + } field; + UINT32 word; +} TX_AGG_CNT_STRUC, *PTX_AGG_CNT_STRUC; +#endif +/* Debug counter */ +#define TX_AGG_CNT0 0x1720 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT0_STRUC { + struct { + USHORT AggSize2Count; + USHORT AggSize1Count; + } field; + UINT32 word; +} TX_AGG_CNT0_STRUC, *PTX_AGG_CNT0_STRUC; +#else +typedef union _TX_AGG_CNT0_STRUC { + struct { + USHORT AggSize1Count; + USHORT AggSize2Count; + } field; + UINT32 word; +} TX_AGG_CNT0_STRUC, *PTX_AGG_CNT0_STRUC; +#endif +/* Debug counter */ +#define TX_AGG_CNT1 0x1724 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT1_STRUC { + struct { + USHORT AggSize4Count; + USHORT AggSize3Count; + } field; + UINT32 word; +} TX_AGG_CNT1_STRUC, *PTX_AGG_CNT1_STRUC; +#else +typedef union _TX_AGG_CNT1_STRUC { + struct { + USHORT AggSize3Count; + USHORT AggSize4Count; + } field; + UINT32 word; +} TX_AGG_CNT1_STRUC, *PTX_AGG_CNT1_STRUC; +#endif +#define TX_AGG_CNT2 0x1728 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT2_STRUC { + struct { + USHORT AggSize6Count; + USHORT AggSize5Count; + } field; + UINT32 word; +} TX_AGG_CNT2_STRUC, *PTX_AGG_CNT2_STRUC; +#else +typedef union _TX_AGG_CNT2_STRUC { + struct { + USHORT AggSize5Count; + USHORT AggSize6Count; + } field; + UINT32 word; +} TX_AGG_CNT2_STRUC, *PTX_AGG_CNT2_STRUC; +#endif +/* Debug counter */ +#define TX_AGG_CNT3 0x172c +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT3_STRUC { + struct { + USHORT AggSize8Count; + USHORT AggSize7Count; + } field; + UINT32 word; +} TX_AGG_CNT3_STRUC, *PTX_AGG_CNT3_STRUC; +#else +typedef union _TX_AGG_CNT3_STRUC { + struct { + USHORT AggSize7Count; + USHORT AggSize8Count; + } field; + UINT32 word; +} TX_AGG_CNT3_STRUC, *PTX_AGG_CNT3_STRUC; +#endif +/* Debug counter */ +#define TX_AGG_CNT4 0x1730 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT4_STRUC { + struct { + USHORT AggSize10Count; + USHORT AggSize9Count; + } field; + UINT32 word; +} TX_AGG_CNT4_STRUC, *PTX_AGG_CNT4_STRUC; +#else +typedef union _TX_AGG_CNT4_STRUC { + struct { + USHORT AggSize9Count; + USHORT AggSize10Count; + } field; + UINT32 word; +} TX_AGG_CNT4_STRUC, *PTX_AGG_CNT4_STRUC; +#endif +#define TX_AGG_CNT5 0x1734 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT5_STRUC { + struct { + USHORT AggSize12Count; + USHORT AggSize11Count; + } field; + UINT32 word; +} TX_AGG_CNT5_STRUC, *PTX_AGG_CNT5_STRUC; +#else +typedef union _TX_AGG_CNT5_STRUC { + struct { + USHORT AggSize11Count; + USHORT AggSize12Count; + } field; + UINT32 word; +} TX_AGG_CNT5_STRUC, *PTX_AGG_CNT5_STRUC; +#endif +#define TX_AGG_CNT6 0x1738 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT6_STRUC { + struct { + USHORT AggSize14Count; + USHORT AggSize13Count; + } field; + UINT32 word; +} TX_AGG_CNT6_STRUC, *PTX_AGG_CNT6_STRUC; +#else +typedef union _TX_AGG_CNT6_STRUC { + struct { + USHORT AggSize13Count; + USHORT AggSize14Count; + } field; + UINT32 word; +} TX_AGG_CNT6_STRUC, *PTX_AGG_CNT6_STRUC; +#endif +#define TX_AGG_CNT7 0x173c +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT7_STRUC { + struct { + USHORT AggSize16Count; + USHORT AggSize15Count; + } field; + UINT32 word; +} TX_AGG_CNT7_STRUC, *PTX_AGG_CNT7_STRUC; +#else +typedef union _TX_AGG_CNT7_STRUC { + struct { + USHORT AggSize15Count; + USHORT AggSize16Count; + } field; + UINT32 word; +} TX_AGG_CNT7_STRUC, *PTX_AGG_CNT7_STRUC; +#endif + +typedef union _TX_AGG_CNTN_STRUC { + struct { +#ifdef RT_BIG_ENDIAN + USHORT AggSizeHighCount; + USHORT AggSizeLowCount; +#else + USHORT AggSizeLowCount; + USHORT AggSizeHighCount; +#endif + } field; + UINT32 word; +} TX_AGG_CNTN_STRUC, *PTX_AGG_CNTN_STRUC; + + +#define MPDU_DENSITY_CNT 0x1740 +#ifdef RT_BIG_ENDIAN +typedef union _MPDU_DEN_CNT_STRUC { + struct { + USHORT RXZeroDelCount; /*RX zero length delimiter count */ + USHORT TXZeroDelCount; /*TX zero length delimiter count */ + } field; + UINT32 word; +} MPDU_DEN_CNT_STRUC, *PMPDU_DEN_CNT_STRUC; +#else +typedef union _MPDU_DEN_CNT_STRUC { + struct { + USHORT TXZeroDelCount; /*TX zero length delimiter count */ + USHORT RXZeroDelCount; /*RX zero length delimiter count */ + } field; + UINT32 word; +} MPDU_DEN_CNT_STRUC, *PMPDU_DEN_CNT_STRUC; +#endif + +#ifdef RT6352 +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED _WCID_TX_RATE_LU_STRUC { + struct { + UINT32 rsv2:16; + UINT32 MODE:2; /* Use definition MODE_xxx. */ + UINT32 rsv:3; + UINT32 STBC:2; /* SPACE */ + UINT32 ShortGI:1; + UINT32 BW:1; /* channel bandwidth 20MHz or 40 MHz */ + UINT32 MCS:7; /* MCS */ + } field; + UINT32 word; +} WCID_TX_RATE_LU_STRUC, *PWCID_TX_RATE_LU_STRUC; +#else +typedef union GNU_PACKED _WCID_TX_RATE_LU_STRUC { + struct { + UINT32 MCS:7; /* MCS */ + UINT32 BW:1; /* channel bandwidth 20MHz or 40 MHz */ + UINT32 ShortGI:1; + UINT32 STBC:2; /* SPACE */ + UINT32 rsv:3; + UINT32 MODE:2; /* Use definition MODE_xxx. */ + UINT32 rsv2:16; + } field; + UINT32 word; +} WCID_TX_RATE_LU_STRUC, *PWCID_TX_RATE_LU_STRUC; +#endif /* RT_BIG_ENDIAN */ +#endif /* RT6352 */ + +/* */ +/* TXRX control registers - base address 0x3000 */ +/* */ +/* rt2860b UNKNOWN reg use R/O Reg Addr 0x77d0 first.. */ +#define TXRX_CSR1 0x77d0 + +/* */ +/* 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 +#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 WCID_RESERVED 0x6bfc +#define SHARED_KEY_TABLE_BASE 0x6c00 /* 32-byte * 16-entry = 512-byte */ +#define SHARED_KEY_TABLE_BASE_EXT 0x7400 /* 32-byte * 16-entry = 512-byte */ +#define SHARED_KEY_MODE_BASE 0x7000 /* 32-byte * 16-entry = 512-byte */ +#define SHARED_KEY_MODE_BASE_EXT 0x73F0 /* 32-byte * 16-entry = 512-byte */ +#define HW_SHARED_KEY_MODE_SIZE 4 +#define SHAREDKEYTABLE 0 +#define PAIRWISEKEYTABLE 1 + +/* 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 + +#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, *PSHAREDKEY_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, *PSHAREDKEY_MODE_STRUC; +#endif +/* 64-entry for pairwise key table */ +typedef struct _HW_WCID_ENTRY { /* 8-byte per entry */ + UCHAR Address[6]; + UCHAR Rsv[2]; +} HW_WCID_ENTRY, PHW_WCID_ENTRY; + + +/* ================================================================================= */ +/* WCID format */ +/* ================================================================================= */ +/*7.1 WCID ENTRY format : 8bytes */ +typedef struct _WCID_ENTRY_STRUC { + UCHAR RXBABitmap7; /* bit0 for TID8, bit7 for TID 15 */ + UCHAR RXBABitmap0; /* bit0 for TID0, bit7 for TID 7 */ + UCHAR MAC[6]; /* 0 for shared key table. 1 for pairwise key table */ +} WCID_ENTRY_STRUC, *PWCID_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 { /* 32-byte per entry */ + UCHAR Key[16]; + UCHAR TxMic[8]; + UCHAR RxMic[8]; +} HW_KEY_ENTRY, *PHW_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, *PWCID_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, *PWCID_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, *PH2M_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, *PH2M_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, *PM2H_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, *PM2H_CMD_DONE_STRUC; +#endif + + +/*NAV_TIME_CFG :NAV */ +#ifdef RT_BIG_ENDIAN +typedef union _NAV_TIME_CFG_STRUC { + struct { + USHORT rsv:6; + USHORT ZeroSifs:1; /* Applied zero SIFS timer after OFDM RX 0: disable */ + USHORT Eifs:9; /* in unit of 1-us */ + UCHAR SlotTime; /* in unit of 1-us */ + UCHAR Sifs; /* in unit of 1-us */ + } field; + UINT32 word; +} NAV_TIME_CFG_STRUC, *PNAV_TIME_CFG_STRUC; +#else +typedef union _NAV_TIME_CFG_STRUC { + struct { + UCHAR Sifs; /* in unit of 1-us */ + UCHAR SlotTime; /* in unit of 1-us */ + USHORT Eifs:9; /* in unit of 1-us */ + USHORT ZeroSifs:1; /* Applied zero SIFS timer after OFDM RX 0: disable */ + USHORT rsv:6; + } field; + UINT32 word; +} NAV_TIME_CFG_STRUC, *PNAV_TIME_CFG_STRUC; +#endif + + +/* */ +/* RX_FILTR_CFG: /RX configuration register */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union RX_FILTR_CFG_STRUC { + struct { + UINT32 :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, *PRX_FILTR_CFG_STRUC; +#else +typedef union _RX_FILTR_CFG_STRUC { + struct { + UINT32 DropCRCErr:1; /* Drop CRC error */ + UINT32 DropPhyErr:1; /* Drop physical error */ + UINT32 DropNotToMe:1; /* Drop not to me unicast frame */ + UINT32 DropNotMyBSSID:1; /* Drop fram ToDs bit is true */ + + UINT32 DropVerErr:1; /* Drop version error frame */ + UINT32 DropMcast:1; /* Drop multicast frames */ + UINT32 DropBcast:1; /* Drop broadcast frames */ + UINT32 DropDuplicate:1; /* Drop duplicate frame */ + + UINT32 DropCFEndAck:1; /* Drop Ps-Poll */ + UINT32 DropCFEnd:1; /* Drop Ps-Poll */ + UINT32 DropAck:1; /* Drop Ps-Poll */ + UINT32 DropCts:1; /* Drop Ps-Poll */ + + UINT32 DropRts:1; /* Drop Ps-Poll */ + UINT32 DropPsPoll:1; /* Drop Ps-Poll */ + UINT32 DropBA:1; /* */ + UINT32 DropBAR:1; /* */ + + UINT32 DropRsvCntlType:1; + UINT32 :15; + } field; + UINT32 word; +} RX_FILTR_CFG_STRUC, *PRX_FILTR_CFG_STRUC; +#endif + + + + +/* */ +/* PHY_CSR4: RF serial control register */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _PHY_CSR4_STRUC { + struct { + UINT32 Busy:1; /* 1: ASIC is busy execute RF programming. */ + UINT32 PLL_LD:1; /* RF PLL_LD status */ + UINT32 IFSelect:1; /* 1: select IF to program, 0: select RF to program */ + UINT32 NumberOfBits:5; /* Number of bits used in RFRegValue (I:20, RFMD:22) */ + UINT32 RFRegValue:24; /* Register value (include register id) serial out to RF/IF chip. */ + } field; + UINT32 word; +} PHY_CSR4_STRUC, *PPHY_CSR4_STRUC; +#else +typedef union _PHY_CSR4_STRUC { + struct { + UINT32 RFRegValue:24; /* Register value (include register id) serial out to RF/IF chip. */ + UINT32 NumberOfBits:5; /* Number of bits used in RFRegValue (I:20, RFMD:22) */ + UINT32 IFSelect:1; /* 1: select IF to program, 0: select RF to program */ + UINT32 PLL_LD:1; /* RF PLL_LD status */ + UINT32 Busy:1; /* 1: ASIC is busy execute RF programming. */ + } field; + UINT32 word; +} PHY_CSR4_STRUC, *PPHY_CSR4_STRUC; +#endif + + +/* */ +/* SEC_CSR5: shared key table security mode register */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _SEC_CSR5_STRUC { + struct { + UINT32 :1; + UINT32 Bss3Key3CipherAlg:3; + UINT32 :1; + UINT32 Bss3Key2CipherAlg:3; + UINT32 :1; + UINT32 Bss3Key1CipherAlg:3; + UINT32 :1; + UINT32 Bss3Key0CipherAlg:3; + UINT32 :1; + UINT32 Bss2Key3CipherAlg:3; + UINT32 :1; + UINT32 Bss2Key2CipherAlg:3; + UINT32 :1; + UINT32 Bss2Key1CipherAlg:3; + UINT32 :1; + UINT32 Bss2Key0CipherAlg:3; + } field; + UINT32 word; +} SEC_CSR5_STRUC, *PSEC_CSR5_STRUC; +#else +typedef union _SEC_CSR5_STRUC { + struct { + UINT32 Bss2Key0CipherAlg:3; + UINT32 :1; + UINT32 Bss2Key1CipherAlg:3; + UINT32 :1; + UINT32 Bss2Key2CipherAlg:3; + UINT32 :1; + UINT32 Bss2Key3CipherAlg:3; + UINT32 :1; + UINT32 Bss3Key0CipherAlg:3; + UINT32 :1; + UINT32 Bss3Key1CipherAlg:3; + UINT32 :1; + UINT32 Bss3Key2CipherAlg:3; + UINT32 :1; + UINT32 Bss3Key3CipherAlg:3; + UINT32 :1; + } field; + UINT32 word; +} SEC_CSR5_STRUC, *PSEC_CSR5_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, *PHOST_CMD_CSR_STRUC; +#else +typedef union _HOST_CMD_CSR_STRUC { + struct { + UINT32 HostCommand:8; + UINT32 Rsv:24; + } field; + UINT32 word; +} HOST_CMD_CSR_STRUC, *PHOST_CMD_CSR_STRUC; +#endif + + +/* */ +/* 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, *PE2PROM_CSR_STRUC; +#else +typedef union _E2PROM_CSR_STRUC { + struct { + UINT32 Reload:1; /* Reload EEPROM content, write one to reload, self-cleared. */ + UINT32 EepromSK:1; + UINT32 EepromCS:1; + UINT32 EepromDI:1; + UINT32 EepromDO:1; + UINT32 Type:1; /* 1: 93C46, 0:93C66 */ + UINT32 LoadStatus:1; /* 1:loading, 0:done */ + UINT32 Rsvd:25; + } field; + UINT32 word; +} E2PROM_CSR_STRUC, *PE2PROM_CSR_STRUC; +#endif + +/* */ +/* QOS_CSR0: TXOP holder address0 register */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _QOS_CSR0_STRUC { + struct { + UCHAR Byte3; /* MAC address byte 3 */ + UCHAR Byte2; /* MAC address byte 2 */ + UCHAR Byte1; /* MAC address byte 1 */ + UCHAR Byte0; /* MAC address byte 0 */ + } field; + UINT32 word; +} QOS_CSR0_STRUC, *PQOS_CSR0_STRUC; +#else +typedef union _QOS_CSR0_STRUC { + struct { + UCHAR Byte0; /* MAC address byte 0 */ + UCHAR Byte1; /* MAC address byte 1 */ + UCHAR Byte2; /* MAC address byte 2 */ + UCHAR Byte3; /* MAC address byte 3 */ + } field; + UINT32 word; +} QOS_CSR0_STRUC, *PQOS_CSR0_STRUC; +#endif + +/* */ +/* QOS_CSR1: TXOP holder address1 register */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _QOS_CSR1_STRUC { + struct { + UCHAR Rsvd1; + UCHAR Rsvd0; + UCHAR Byte5; /* MAC address byte 5 */ + UCHAR Byte4; /* MAC address byte 4 */ + } field; + UINT32 word; +} QOS_CSR1_STRUC, *PQOS_CSR1_STRUC; +#else +typedef union _QOS_CSR1_STRUC { + struct { + UCHAR Byte4; /* MAC address byte 4 */ + UCHAR Byte5; /* MAC address byte 5 */ + UCHAR Rsvd0; + UCHAR Rsvd1; + } field; + UINT32 word; +} QOS_CSR1_STRUC, *PQOS_CSR1_STRUC; +#endif + +#define RF_CSR_CFG 0x500 +#ifdef RT6352 +#ifdef RT_BIG_ENDIAN +typedef union _RF_CSR_CFG_STRUC { + struct { + UINT Rsvd3:6; + UINT TESTCSR_RFACC_REGNUM:10; /* RF register ID */ + UINT RF_CSR_DATA:8; /* DATA */ + UINT Rsvd2:3; /* Reserved */ + UINT RF_CSR_WR:1; /* 0: read 1: write */ + UINT Rsvd1:3; /* Reserved */ + UINT RF_CSR_KICK:1; /* kick RF register read/write */ + } field; + UINT word; +} RF_CSR_CFG_STRUC, *PRF_CSR_CFG_STRUC; +#else +typedef union _RF_CSR_CFG_STRUC { + struct { + UINT RF_CSR_KICK:1; /* kick RF register read/write */ + UINT Rsvd1:3; /* Reserved */ + UINT RF_CSR_WR:1; /* 0: read 1: write */ + UINT Rsvd2:3; /* Reserved */ + UINT RF_CSR_DATA:8; /* DATA */ + UINT TESTCSR_RFACC_REGNUM:10; /* RF register ID */ + UINT Rsvd3:6; /* Reserved */ + } field; + UINT word; +} RF_CSR_CFG_STRUC, *PRF_CSR_CFG_STRUC; +#endif +#else +#ifdef RT_BIG_ENDIAN +typedef union _RF_CSR_CFG_STRUC { + struct { + UINT Rsvd1:14; /* Reserved */ + UINT RF_CSR_KICK:1; /* kick RF register read/write */ + UINT RF_CSR_WR:1; /* 0: read 1: write */ + UINT TESTCSR_RFACC_REGNUM:8; /* RF register ID */ + UINT RF_CSR_DATA:8; /* DATA */ + } field; + UINT word; +} RF_CSR_CFG_STRUC, *PRF_CSR_CFG_STRUC; +#else +typedef union _RF_CSR_CFG_STRUC { + struct { + UINT RF_CSR_DATA:8; /* DATA */ + UINT TESTCSR_RFACC_REGNUM:8; /* RF register ID */ + UINT RF_CSR_WR:1; /* 0: read 1: write */ + UINT RF_CSR_KICK:1; /* kick RF register read/write */ + UINT Rsvd1:14; /* Reserved */ + } field; + UINT word; +} RF_CSR_CFG_STRUC, *PRF_CSR_CFG_STRUC; +#endif +#endif + +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_WORD_STRUC { + struct + { + UCHAR Byte1; // High Byte + UCHAR Byte0; // Low Byte + } field; + USHORT word; +} EEPROM_WORD_STRUC, *PEEPROM_WORD_STRUC; +#else +typedef union _EEPROM_WORD_STRUC { + struct + { + UCHAR Byte0; // Low Byte + UCHAR Byte1; // High Byte + } field; + USHORT word; +} EEPROM_WORD_STRUC, *PEEPROM_WORD_STRUC; +#endif + +/* */ +/* 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 */ + +#ifdef WOW_SUPPORT +/* WOW - NullFrame buffer */ +#define HW_NULL2_BASE 0x7780 +#define GPIO_HOLDTIME_OFFSET 0x7020 /* Target is 0x7023 */ +#endif /* WOW_SUPPORT */ + +/* + 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 + + +/* 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 QID_MGMT 13 +#define QID_RX 14 +#define QID_OTHER 15 + + +#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 + */ +#define RTMP_HIGH_SHARED_MEM_SET(_pAd) \ + do{ \ + if (_pAd->chipCap.FlgIsSupSpecBcnBuf == TRUE) \ + { \ + UINT32 regValue; \ + \ + if (_pAd->ShrMSel != HIGHER_SHRMEM) \ + { \ + _pAd->ShrMSel = HIGHER_SHRMEM; \ + RTMP_IO_READ32(_pAd, PBF_SYS_CTRL, ®Value); \ + RTMP_IO_WRITE32(_pAd, PBF_SYS_CTRL, regValue | (1 << 19)); \ + } \ + } \ + } while(0) + +#define RTMP_LOW_SHARED_MEM_SET(_pAd) \ + do{ \ + if (_pAd->chipCap.FlgIsSupSpecBcnBuf == TRUE) \ + { \ + UINT32 regValue; \ + \ + if (_pAd->ShrMSel != LOWER_SHRMEM) \ + { \ + _pAd->ShrMSel = LOWER_SHRMEM; \ + RTMP_IO_READ32(_pAd, PBF_SYS_CTRL, ®Value); \ + RTMP_IO_WRITE32(_pAd, PBF_SYS_CTRL, regValue & ~(1 << 19)); \ + } \ + } \ + } while(0) + +/* + 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 //Should add RBUS? +#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); +#endif /* RTMP_MAC_PCI */ //Should add RBUS? + + +#ifdef RTMP_MAC_PCI //Should add RBUS? +/* + 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 __regValue; \ + \ + RTMP_INT_LOCK(&_pAd->ShrMemLock, _irqFlag); \ + _pAd->ShrMSel = _shr_msel; \ + RTMP_IO_READ32(_pAd, PBF_SYS_CTRL, &__regValue); \ + if (_shr_msel == HIGHER_SHRMEM) \ + { \ + RTMP_IO_WRITE32(_pAd, PBF_SYS_CTRL, __regValue | (1 << 19)); \ + } \ + else \ + { \ + RTMP_IO_WRITE32(_pAd, PBF_SYS_CTRL, __regValue & ~(1 << 19)); \ + } \ + } \ + } while(0) + + +#define RTMP_MAC_SHR_MSEL_UNLOCK(_pAd, _shr_msel, _irqFlag) \ + do{ \ + if (_pAd->chipCap.FlgIsSupSpecBcnBuf == TRUE) \ + { \ + UINT32 __regValue; \ + \ + _pAd->ShrMSel = _shr_msel; \ + RTMP_IO_READ32(_pAd, PBF_SYS_CTRL, &__regValue); \ + if (_shr_msel == HIGHER_SHRMEM) \ + { \ + RTMP_IO_WRITE32(_pAd, PBF_SYS_CTRL, __regValue | (1 << 19)); \ + } \ + else \ + { \ + RTMP_IO_WRITE32(_pAd, PBF_SYS_CTRL, __regValue & ~(1 << 19)); \ + } \ + RTMP_INT_UNLOCK(&_pAd->ShrMemLock, _irqFlag); \ + } \ + } while(0) +#endif /* RTMP_MAC_PCI */ //Should add RBUS? + +#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 */ + + +#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 */ + +#endif /* __RTMP_MAC_H__ */ + diff --git a/mt7620/src/include/chip/rtmp_phy.h b/mt7620/src/include/chip/rtmp_phy.h new file mode 100644 index 0000000..572986a --- /dev/null +++ b/mt7620/src/include/chip/rtmp_phy.h @@ -0,0 +1,1062 @@ +/* + *************************************************************************** + * 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__ + + +/* + 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 + + +/* 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_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_UNKNOWN)) + +/* + 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_R7 7 +#define BBP_R8 8 +#define BBP_R9 9 +#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_R29 29 +#define BBP_R30 30 +#define BBP_R31 31 +#define BBP_R40 40 +#define BBP_R41 41 +#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_R57 57 +#define BBP_R58 58 +#define BBP_R60 60 +#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_R71 71 +#define BBP_R72 72 +#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_R85 85 +#define BBP_R86 86 +#define BBP_R87 87 +#define BBP_R88 88 +#define BBP_R89 89 +#define BBP_R90 90 +#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_R97 97 +#define BBP_R98 98 +#define BBP_R99 99 +#define BBP_R100 100 +#define BBP_R101 101 +#define BBP_R102 102 +#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_R111 111 +#define BBP_R112 112 +#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_R251 251 +#define BBP_R252 252 +#define BBP_R253 253 +#define BBP_R254 254 +#define BBP_R255 255 + +#define BBPR94_DEFAULT 0x06 /* Add 1 value will gain 1db */ + +typedef enum{ + RX_CHAIN_0 = 1<<0, + RX_CHAIN_1 = 1<<1, + RX_CHAIN_2 = 1<<2, + RX_CHAIN_ALL = 0xf +}RX_CHAIN_IDX; + +#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 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 + +/* */ +/* 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 + #define MAX_BBP_MSG_SIZE 4096 + +#if defined(RT3352) || defined(RT5350) + #undef MAX_BBP_ID + #define MAX_BBP_ID 255 +#endif /* RT3352 */ +#else + #define MAX_BBP_ID 136 + + #define MAX_BBP_MSG_SIZE 2048 +#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 + + +/* */ +/* 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 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) \ + { \ + PHY_CSR4_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 */ + +#define _RTMP_BBP_IO_READ8(_pAd, _bbpID, _pV, _bViaMCU) \ + do{ \ + BBP_CSR_CFG_STRUC BbpCsr; \ + int _busyCnt, _secCnt, _regID; \ + ULONG __IrqFlags = 0; \ + \ + if ((_bViaMCU) == TRUE) \ + RTMP_MAC_SHR_MSEL_PROTECT_LOCK(_pAd, __IrqFlags); \ + _regID = ((_bViaMCU) == TRUE ? H2M_BBP_AGENT : BBP_CSR_CFG); \ + for (_busyCnt=0; _busyCntBbpWriteLatch[_bbpID]; \ + 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); \ + }while(0) + +/* + 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) + +/* + 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. +*/ +#define _RTMP_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) \ + do{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + if ((_A)->infType == RTMP_DEV_INF_RBUS) \ + RTMP_BBP_IO_READ8((_A), (_I), (_pV), FALSE); \ + else \ + if(IS_SUPPORT_PCIE_PS_L3((_A))) \ + RTMP_PCIE_PS_L3_BBP_IO_READ8((_A), (_I), (_pV), TRUE); \ + else \ + RTMP_BBP_IO_READ8((_A), (_I), (_pV), TRUE); \ + } \ + }while(0) + +/* + 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 */ + +#define _RTMP_BBP_IO_WRITE8(_pAd, _bbpID, _pV, _bViaMCU) \ + do{ \ + BBP_CSR_CFG_STRUC BbpCsr; \ + int _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); \ + 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[_bbpID] = _pV; \ + break; \ + } \ + if (_busyCnt == MAX_BUSY_COUNT) \ + { \ + DBGPRINT_ERR(("BBP write R%d fail\n", _bbpID)); \ + 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); \ + }while(0) + + +/* + 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) + +/* + 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. +*/ +#define _RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, _I, _pV) \ + do{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + if ((_A)->infType == RTMP_DEV_INF_RBUS) \ + RTMP_BBP_IO_WRITE8((_A), (_I), (_pV), FALSE); \ + else \ + if(IS_SUPPORT_PCIE_PS_L3((_A))) \ + RTMP_PCIE_PS_L3_BBP_IO_WRITE8((_A), (_I), (_pV), TRUE); \ + else \ + RTMP_BBP_IO_WRITE8((_A), (_I), (_pV), TRUE); \ + } \ + }while(0) + +#ifndef VENDOR_FEATURE3_SUPPORT +#define RTMP_BBP_IO_READ8 _RTMP_BBP_IO_READ8 +#define RTMP_BBP_IO_READ8_BY_REG_ID _RTMP_BBP_IO_READ8_BY_REG_ID +#define RTMP_BBP_IO_WRITE8 _RTMP_BBP_IO_WRITE8 +#define RTMP_BBP_IO_WRITE8_BY_REG_ID _RTMP_BBP_IO_WRITE8_BY_REG_ID +#endif /* VENDOR_FEATURE3_SUPPORT */ + +/* + 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*/ + + + + +#endif /* __RTMP_PHY_H__ */ + diff --git a/mt7620/src/include/chlist.h b/mt7620/src/include/chlist.h new file mode 100644 index 0000000..a6b81ab --- /dev/null +++ b/mt7620/src/include/chlist.h @@ -0,0 +1,157 @@ +/* + *************************************************************************** + * 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 + -------- ---------- ---------------------------------------------- + Fonchi Wu 2007-12-19 created +*/ + +#ifndef __CHLIST_H__ +#define __CHLIST_H__ + +#include "rtmp_type.h" +#include "rtmp_def.h" + +#define BAND_5G 1 +#define BAND_24G 2 +#define BAND_BOTH (BAND_5G | BAND_24G) + +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; +} CH_REGION, *PCH_REGION; + +extern CH_REGION ChRegion[]; +#endif /* EXT_BUILD_CHANNEL_LIST */ + +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; + +#ifdef SINGLE_SKU_V2 +#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 + +typedef struct _CH_POWER_{ + DL_LIST List; + UCHAR channel; + UCHAR num; + 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]; +}CH_POWER; +#endif /* SINGLE_SKU_V2 */ + + + +#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)) + + +#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 */ + +#ifdef DOT11_N_SUPPORT +VOID N_ChannelCheck( + IN PRTMP_ADAPTER pAd); + +VOID N_SetCenCh( + IN PRTMP_ADAPTER pAd); + +BOOLEAN N_ChannelGroupCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel); + +#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/mt7620/src/include/client_wds.h b/mt7620/src/include/client_wds.h new file mode 100644 index 0000000..cd5bf7a --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/client_wds_cmm.h b/mt7620/src/include/client_wds_cmm.h new file mode 100644 index 0000000..fad7171 --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/crypt_aes.h b/mt7620/src/include/crypt_aes.h new file mode 100644 index 0000000..dff7a49 --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/crypt_arc4.h b/mt7620/src/include/crypt_arc4.h new file mode 100644 index 0000000..63d87ce --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/crypt_biginteger.h b/mt7620/src/include/crypt_biginteger.h new file mode 100644 index 0000000..f7c48f4 --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/crypt_dh.h b/mt7620/src/include/crypt_dh.h new file mode 100644 index 0000000..f0379a8 --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/crypt_hmac.h b/mt7620/src/include/crypt_hmac.h new file mode 100644 index 0000000..e6dd220 --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/crypt_md5.h b/mt7620/src/include/crypt_md5.h new file mode 100644 index 0000000..60cf5d3 --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/crypt_sha2.h b/mt7620/src/include/crypt_sha2.h new file mode 100644 index 0000000..9d2e43e --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/cs.h b/mt7620/src/include/cs.h new file mode 100644 index 0000000..71f3145 --- /dev/null +++ b/mt7620/src/include/cs.h @@ -0,0 +1,176 @@ +#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 0x1fffffff +#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 420 +#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_VERSION; + +typedef struct CARRIER_DETECTION_s { + BOOLEAN Enable; + 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); + +VOID ToneRadarProgram_v1( + IN PRTMP_ADAPTER pAd, + IN ULONG threshold); + +VOID ToneRadarProgram_v2( + IN PRTMP_ADAPTER pAd, + IN ULONG threshold); + +#ifdef CARRIER_DETECTION_FIRMWARE_SUPPORT +VOID CarrierDetectionPeriodicStateCtrl( + IN PRTMP_ADAPTER pAd); +#endif /* CARRIER_DETECTION_FIRMWARE_SUPPORT */ + +#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/mt7620/src/include/dfs.h b/mt7620/src/include/dfs.h new file mode 100644 index 0000000..c11ea84 --- /dev/null +++ b/mt7620/src/include/dfs.h @@ -0,0 +1,576 @@ + +/* + *************************************************************************** + * 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*/ +#define DFS_EVENT_SIZE 6 /* Number of bytes of each DFS event */ +#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 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)) + +#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)) + + +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 _NewDFSParam { + 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; +} NewDFSParam, *pNewDFSParam; + +typedef struct _DFS_PROGRAM_PARAM{ + NewDFSParam NewDFSTableEntry[NEW_DFS_MAX_CHANNEL*4]; + USHORT ChEnable; /* Enabled Dfs channels (bit wise)*/ + UCHAR DeltaDelay; + /* Support after dfs_func >= 2 */ + UCHAR Symmetric_Round; + UCHAR VGA_Mask; + UCHAR Packet_End_Mask; + UCHAR Rx_PE_Mask; + ULONG RadarEventExpire[NEW_DFS_MAX_CHANNEL]; +}DFS_PROGRAM_PARAM, *PDFS_PROGRAM_PARAM; + +typedef struct _NewDFSTable +{ + USHORT type; + NewDFSParam 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; +}DFS_EVENT, *PDFS_EVENT; + +typedef struct _DFS_SW_DETECT_PARAM{ + NewDFSDebugPort FCC_5[NEW_DFS_FCC_5_ENT_NUM]; + UCHAR fcc_5_idx; + UCHAR fcc_5_last_idx; + USHORT fcc_5_threshold; /* to check the width of long pulse radar */ + 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 */ + /*UCHAR ce_sw_id_check;*/ + /*USHORT ce_sw_t_diff;*/ + /*ULONG fcc_5_counter;*/ + /* CE Staggered radar / weather radar */ +#ifdef DFS_DEBUG + /* Roger debug */ + UCHAR DebugPort[384]; + UCHAR DebugPortPrint; /* 0 = stop, 1 = log req, 2 = loging, 3 = log done */ + ULONG TotalEntries[4]; + ULONG T_Matched_2; + ULONG T_Matched_3; + ULONG T_Matched_4; + ULONG T_Matched_5; + UCHAR BBP127Repeat; + ULONG CounterStored[5]; + ULONG CounterStored2[5]; + ULONG CounterStored3; + NewDFSDebugPort CE_DebugCh0[NEW_DFS_DBG_PORT_ENT_NUM]; + NewDFSMPeriod CE_TCh0[NEW_DFS_MPERIOD_ENT_NUM]; +#endif +}DFS_SW_DETECT_PARAM, *PDFS_SW_DETECT_PARAM; + +/*************************************************************************** + * structure for radar detection and channel switch + **************************************************************************/ +typedef struct _RADAR_DETECT_STRUCT { + UCHAR DFSAPRestart; + ULONG MCURadarRegion; + CHAR AvgRssiReq; + ULONG DfsLowerLimit; + ULONG DfsUpperLimit; + ULONG upperlimit; + ULONG lowerlimit; + 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; + DFS_VERSION dfs_func; + BOOLEAN DFSWatchDogIsRunning; + 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 fdf_num; + USHORT ch_busy_threshold[MAX_FDF_NUMBER]; + INT rssi_threshold[MAX_FDF_NUMBER]; + UCHAR McuRadarDebug; + USHORT McuRadarTick; + ULONG RadarTimeStampHigh; + ULONG RadarTimeStampLow; + UCHAR EnabledChMask; /* Bit-wise mask for enabled DFS channels */ + DFS_PROGRAM_PARAM DfsProgramParam; + DFS_SW_DETECT_PARAM DfsSwParam; +} 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 pDFS2Table); + +BOOLEAN DfsSwCheckOnHwDetection( + IN PRTMP_ADAPTER pAd, + IN pNewDFSTable pDFS2Table, + IN UINT8 DfsChannel, + IN ULONG RadarPeriod, + IN ULONG RadarWidth); + +INT Set_RfReg_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +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); + +INT Set_RadarSetTbl1_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_RadarSetTbl2_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_Fcc5Thrd_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ChBusyThrd_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_RssiThrd_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_RadarSim_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); + +INT Set_Ch0EventExpire_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_Ch1EventExpire_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_Ch2EventExpire_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_Ch3EventExpire_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_CEPrint_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_Ch0LErr_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MaxPeriod_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_PeriodErr_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_Ch0HErr_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_Ch1Shift_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_Ch2Shift_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_DeclareThres_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_CheckLoop_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef DFS_DEBUG +INT Set_DfsLowerLimit_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_DfsUpperLimit_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_FixDfsLimit_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_AvgRssiReq_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_CEPrintDebug_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* DFS_DEBUG */ + +#ifdef WORKQUEUE_BH +void dfs_workq(struct work_struct *work); +#else +void dfs_tasklet(unsigned long data); +#endif /* WORKQUEUE_BH */ + +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/mt7620/src/include/dot11i_wpa.h b/mt7620/src/include/dot11i_wpa.h new file mode 100644 index 0000000..904036c --- /dev/null +++ b/mt7620/src/include/dot11i_wpa.h @@ -0,0 +1,291 @@ +/* + *************************************************************************** + * 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" + +/* 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 + +/* Key Descriptor Version of Key Information */ +#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, + 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/mt7620/src/include/dot11r_ft.h b/mt7620/src/include/dot11r_ft.h new file mode 100644 index 0000000..47fbbac --- /dev/null +++ b/mt7620/src/include/dot11r_ft.h @@ -0,0 +1,113 @@ +/**************************************************************************** + * 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 + +#define GNU_PACKED __attribute__ ((packed)) + + +#if defined(DOT11R_FT_SUPPORT) || defined(DOT11Z_TDLS_SUPPORT) +#define FT_MIC_LEN 16 +#define FT_NONCE_LEN 32 +#endif + + +#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 + + +#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 + + +#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. */ + 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 + + +#endif /* __DOT11R_FT_H */ + diff --git a/mt7620/src/include/dot11z_tdls.h b/mt7620/src/include/dot11z_tdls.h new file mode 100644 index 0000000..117a9d6 --- /dev/null +++ b/mt7620/src/include/dot11z_tdls.h @@ -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, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering 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 + +#define GNU_PACKED __attribute__ ((packed)) + +/* 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 300 // unit: sec +#define TDLS_LEY_LIFETIME 3600 + +#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. */ + 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; + +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/mt7620/src/include/drs_extr.h b/mt7620/src/include/drs_extr.h new file mode 100644 index 0000000..d9660ff --- /dev/null +++ b/mt7620/src/include/drs_extr.h @@ -0,0 +1,357 @@ +/**************************************************************************** + * 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_SWITCH +{ + UCHAR ItemNo; +#ifdef RT_BIG_ENDIAN + UCHAR Rsv2:2; + UCHAR Mode:2; + UCHAR Rsv1:1; + UCHAR BW:1; + UCHAR ShortGI:1; + UCHAR STBC:1; +#else + UCHAR STBC:1; + UCHAR ShortGI:1; + UCHAR BW:1; + UCHAR Rsv1:1; + UCHAR Mode:2; + UCHAR Rsv2:2; +#endif + UCHAR CurrMCS; + UCHAR TrainUp; + UCHAR TrainDown; +} RTMP_TX_RATE_SWITCH, *PRTMP_TX_RATE_SWITCH; + +#define PTX_RATE_SWITCH_ENTRY(pTable, idx) ((PRTMP_TX_RATE_SWITCH)&(pTable[(idx+1)*5])) +#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 */ + +#ifdef NEW_RATE_ADAPT_SUPPORT +typedef struct _RTMP_TX_RATE_SWITCH_3S +{ + UCHAR ItemNo; +#ifdef RT_BIG_ENDIAN + UCHAR Rsv2:2; + UCHAR Mode:2; + UCHAR Rsv1:1; + UCHAR BW:1; + UCHAR ShortGI:1; + UCHAR STBC:1; +#else + UCHAR STBC:1; + UCHAR ShortGI:1; + UCHAR BW:1; + UCHAR Rsv1:1; + UCHAR Mode:2; + UCHAR Rsv2:2; +#endif + UCHAR CurrMCS; + UCHAR TrainUp; + UCHAR TrainDown; + UCHAR downMcs; + UCHAR upMcs3; + UCHAR upMcs2; + UCHAR upMcs1; + UCHAR dataRate; +} RTMP_TX_RATE_SWITCH_3S, *PRTMP_TX_RATE_SWITCH_3S; + +#define PTX_RATE_SWITCH_ENTRY_3S(pTable, idx) ((PRTMP_TX_RATE_SWITCH_3S)&(pTable[(idx+1)*10])) +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +enum RATE_ADAPT_ALG{ + RATE_ALG_LEGACY = 1, + RATE_ALG_GRP = 2, + RATE_ALG_AGS = 3, + RATE_ALG_MAX_NUM +}; + + +extern UCHAR RateSwitchTable[]; +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 */ +#define ADAPT_RATE_TABLE(pTable) ((pTable)==RateSwitchTableAdapt11N1S || (pTable)==RateSwitchTableAdapt11N2S || (pTable)==RateSwitchTableAdapt11N3S) +#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( + IN struct _MAC_TABLE_ENTRY *pEntry); + +VOID MlmeClearAllTxQuality( + IN struct _MAC_TABLE_ENTRY *pEntry); + +VOID MlmeDecTxQuality( + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UCHAR rateIndex); + +VOID MlmeSetTxQuality( + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UCHAR rateIndex, + IN USHORT txQuality); + +USHORT MlmeGetTxQuality( + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UCHAR rateIndex); + +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, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen); + +#ifdef NEW_RATE_ADAPT_SUPPORT +VOID MlmeSetMcsGroup( + IN struct _RTMP_ADAPTER *pAd, + OUT struct _MAC_TABLE_ENTRY *pEntry); + +UCHAR MlmeSelectUpRate( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN struct _RTMP_TX_RATE_SWITCH_3S *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 struct _RTMP_TX_RATE_SWITCH_3S *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); + +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); + +#ifdef CONFIG_AP_SUPPORT +VOID APMlmeDynamicTxRateSwitchingAdapt( + IN struct _RTMP_ADAPTER *pAd, + IN ULONG idx); + +VOID APQuickResponeForRateUpExecAdapt( + IN struct _RTMP_ADAPTER *pAd, + IN ULONG 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 PRTMP_TX_RATE_SWITCH 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 PRTMP_TX_RATE_SWITCH pTxRate); +#endif /* CONFIG_STA_SUPPORT */ + +VOID MlmeRAInit( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry); + +VOID MlmeNewTxRate( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry); + +typedef enum { + RAL_OLD_DRS, + RAL_NEW_DRS, + RAL_QUICK_DRS +}RA_LOG_TYPE; + +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 PUCHAR *ppTable, + IN PUCHAR pTableSize, + IN PUCHAR pInitTxRateIdx); + +#ifdef MCS_LUT_SUPPORT +#define IS_HW_TXRATE_LOOKUP_SUPPORT(__pAd) (__pAd->chipCap.bFlgHwTxLuCap) + +VOID MlmeSetHwTxRateTable( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry); +#endif /* MCS_LUT_SUPPORT */ + +/* normal rate switch */ +#define RTMP_DRS_ALG_INIT(__pAd, __Alg) \ + (__pAd)->rateAlg = __Alg; + +#endif /* __DRS_EXTR_H__ */ + +/* End of drs_extr.h */ diff --git a/mt7620/src/include/eeprom.h b/mt7620/src/include/eeprom.h new file mode 100644 index 0000000..3d5b9b7 --- /dev/null +++ b/mt7620/src/include/eeprom.h @@ -0,0 +1,97 @@ +/* + *************************************************************************** + * 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__ + +/* For ioctl check usage */ +#define EEPROM_IS_PROGRAMMED 0x80 + +#ifdef RTMP_MAC_PCI +#ifdef RT3883 +#define EEPROM_SIZE 0x400 +#else +#define EEPROM_SIZE 0x200 +#endif /* RT3883 */ +#endif /* RTMP_MAC_PCI */ + + + +#ifdef RTMP_PCI_SUPPORT +/************************************************************************* + * Public function declarations for prom-based chipset + ************************************************************************/ +int rtmp_ee_prom_read16( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + OUT USHORT *pValue); + +int rtmp_ee_prom_write16( + IN PRTMP_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 PRTMP_ADAPTER pAd); + +int rtmp_ee_flash_read( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + OUT USHORT *pValue); + +int rtmp_ee_flash_write( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Data); + +VOID rtmp_ee_flash_read_all( + IN PRTMP_ADAPTER pAd, + IN USHORT *Data); + +VOID rtmp_ee_flash_write_all( + IN PRTMP_ADAPTER pAd, + IN USHORT *Data); + +#endif /* defined(RTMP_RBUS_SUPPORT) || defined(RTMP_FLASH_SUPPORT) */ + + +/************************************************************************* + * Public function declarations for prom operation callback functions setting + ************************************************************************/ +INT RtmpChipOpsEepromHook( + IN RTMP_ADAPTER *pAd, + IN INT infType); + +#endif /* __EEPROM_H__ */ diff --git a/mt7620/src/include/firmware.h b/mt7620/src/include/firmware.h new file mode 100644 index 0000000..27588bb --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/frq_cal.h b/mt7620/src/include/frq_cal.h new file mode 100644 index 0000000..86cf604 --- /dev/null +++ b/mt7620/src/include/frq_cal.h @@ -0,0 +1,90 @@ +/* + *************************************************************************** + * 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/mt7620/src/include/iface/iface_util.h b/mt7620/src/include/iface/iface_util.h new file mode 100644 index 0000000..c9b8cb3 --- /dev/null +++ b/mt7620/src/include/iface/iface_util.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. + **************************************************************************** + + Module Name: + rtmp_util.h + + Abstract: + Common for PCI/USB/RBUS. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- +*/ + +#ifndef __RTMP_UTIL_H__ +#define __RTMP_UTIL_H__ + +/* 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_RTUSBMlmeUp RtmpOsMlmeUp + + + + +#endif /* __RTMP_UTIL_H__ */ diff --git a/mt7620/src/include/iface/rtmp_pci.h b/mt7620/src/include/iface/rtmp_pci.h new file mode 100644 index 0000000..d3e0849 --- /dev/null +++ b/mt7620/src/include/iface/rtmp_pci.h @@ -0,0 +1,489 @@ +/**************************************************************************** + * 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__ + +#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 */ + + + +// TODO: shiang, for RT3290, make sure following definition is correct to put as here + +#define ASIC_VERSION 0x0000 + +#define CMB_CTRL 0x20 +#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; + UINT32 Rsv:2; + UINT32 LDO25_FRC_ON:1;//4 + UINT32 LDO25_LARGEA:1; + UINT32 LDO25_LEVEL:2; + 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; + UINT32 LDO25_LEVEL:2; + UINT32 LDO25_LARGEA:1; + UINT32 LDO25_FRC_ON:1;//4 + UINT32 Rsv:2; + 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 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 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 + + +#define COEXCFG0 0x40 +#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 + + +#define COEXCFG1 0x44 +#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 + + +#define COEXCFG2 0x48 +#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 WLAN_FUN_CTRL 0x80 +#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 Rsv1: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 Rsv1: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; + +#endif /* __RTMP_PCI_H__ */ diff --git a/mt7620/src/include/iface/rtmp_rbs.h b/mt7620/src/include/iface/rtmp_rbs.h new file mode 100644 index 0000000..b0fc752 --- /dev/null +++ b/mt7620/src/include/iface/rtmp_rbs.h @@ -0,0 +1,142 @@ +/**************************************************************************** + * 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__ + +/*#ifdef LINUX */ +/*#include */ +/*#endif */ + + +/************************************************************************* + * + * Device hardware/ Interface related definitions. + * + ************************************************************************/ + +#define RTMP_MAC_IRQ_NUM 4 + + +/************************************************************************* + * + * EEPROM Related definitions + * + ************************************************************************/ +#if defined(CONFIG_RALINK_RT3050_1T1R) +#if defined(CONFIG_RALINK_RT3350) +#define EEPROM_DEFAULT_FILE_PATH "/etc_ro/wlan/RT3350_AP_1T1R_V1_0.bin" +#else +#define EEPROM_DEFAULT_FILE_PATH "/etc_ro/wlan/RT3050_AP_1T1R_V1_0.bin" +#endif /* CONFIG_RALINK_RT3350 */ +#endif /* CONFIG_RALINK_RT3050_1T1R */ + +#if defined(CONFIG_RALINK_RT3051_1T2R) +#define EEPROM_DEFAULT_FILE_PATH "/etc_ro/wlan/RT3051_AP_1T2R_V1_0.bin" +#endif /* CONFIG_RALINK_RT3051_1T2R */ + +#if defined(CONFIG_RALINK_RT3052_2T2R) +#define EEPROM_DEFAULT_FILE_PATH "/etc_ro/wlan/RT3052_AP_2T2R_V1_1.bin" +#endif /* CONFIG_RALINK_RT3052_2T2R */ + +#if defined(CONFIG_RALINK_RT3883_3T3R) +#define EEPROM_DEFAULT_FILE_PATH "/etc_ro/wlan/RT3883_AP_3T3R_V0_1.bin" +#endif /* CONFIG_RALINK_RT3883_3T3R */ + +#if defined(CONFIG_RALINK_RT3662_2T2R) +#define EEPROM_DEFAULT_FILE_PATH "/etc_ro/wlan/RT3662_AP_2T2R_V0_0.bin" +#endif /* CONFIG_RALINK_RT3662_2T2R */ + +#if defined(CONFIG_RALINK_RT3352_2T2R) +#define EEPROM_DEFAULT_FILE_PATH "/etc_ro/wlan/RT3352_AP_2T2R-4L_V12.BIN" +#endif /* CONFIG_RALINK_RT3352_2T2R */ + +#if defined(CONFIG_RALINK_RT5350_1T1R) +#define EEPROM_DEFAULT_FILE_PATH "/etc_ro/wlan/RT5350_AP_1T1R_V1_0.bin" +#endif // CONFIG_RALINK_RT5350_1T1R // + +#if defined(CONFIG_RT2860V2_2850) +#define EEPROM_DEFAULT_FILE_PATH "/etc_ro/wlan/RT2880_RT2850_AP_2T3R_V1_6.bin" +#endif /* CONFIG_RT2860V2_2850 */ + +#if defined (CONFIG_RALINK_RT6352) || defined (CONFIG_RALINK_MT7620) +#if defined(CONFIG_SUPPORT_OPENWRT) +#define EEPROM_DEFAULT_FILE_PATH "/etc/wireless/mt7620/mt7620.eeprom.bin" +#else +#define EEPROM_DEFAULT_FILE_PATH "/etc_ro/wlan/MT7620_AP_2T2R-4L_V15.BIN" +#endif /* CONFIG_SUPPORT_OPENWRT */ +#endif /* defined (CONFIG_RALINK_RT6352) || defined (CONFIG_RALINK_MT7620) */ + +#ifndef EEPROM_DEFAULT_FILE_PATH +/* RFIC 2820 */ +#define EEPROM_DEFAULT_FILE_PATH "/etc_ro/wlan/RT2880_RT2820_AP_2T3R_V1_6.bin" +#endif /* EEPROM_DEFAULT_FILE_PATH */ + +#if defined (CONFIG_RT2880_FLASH_32M) +#define MTD_NUM_FACTORY 5 +#else +#define MTD_NUM_FACTORY 2 +#endif + +#define NVRAM_OFFSET 0x30000 + +#if defined (CONFIG_RT2880_FLASH_32M) +#define RF_OFFSET 0x1FE0000 +#else +#define RF_OFFSET 0x40000 +#endif + +#define RALINK_SYSCTL_BASE 0xb0000000 + + +#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 */ + + +/*#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) */ +/*#ifndef SA_SHIRQ */ +/*#define SA_SHIRQ IRQF_SHARED */ +/*#endif */ +/*#endif */ + +#endif /* LINUX */ + + +#endif /* __RTMP_RBUS_H__ */ + diff --git a/mt7620/src/include/igmp_snoop.h b/mt7620/src/include/igmp_snoop.h new file mode 100644 index 0000000..f51f821 --- /dev/null +++ b/mt7620/src/include/igmp_snoop.h @@ -0,0 +1,155 @@ +/**************************************************************************** + * 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_V1_LISTENER_REPORT 131 +#define MLD_V1_LISTENER_DONE 132 +#define MLD_V2_LISTERNER_REPORT 143 + +#define IGMPMAC_TB_ENTRY_AGEOUT_TIME (120 * 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 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); + +PMULTICAST_FILTER_TABLE_ENTRY MulticastFilterTableLookup( + IN PMULTICAST_FILTER_TABLE pMulticastFilterTable, + IN PUCHAR pAddr, + IN PNET_DEV dev); + +BOOLEAN isIgmpPkt( + IN PUCHAR pDstMacAddr, + IN PUCHAR pIpHeader); + +VOID IGMPSnooping( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDstMacAddr, + IN PUCHAR pSrcMacAddr, + IN PUCHAR pIpHeader, + IN PNET_DEV pDev); + +BOOLEAN isMldPkt( + IN PUCHAR pDstMacAddr, + IN PUCHAR pIpHeader, + OUT UINT8 *pProtoType, + OUT PUCHAR *pMldHeader); + +BOOLEAN IPv6MulticastFilterExcluded( + IN PUCHAR pDstMacAddr, + IN PUCHAR pIpHeader); + +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 UCHAR FromWhichBSSID, + 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, + IN PNET_DEV pNetDev); + +#endif /* __RTMP_IGMP_SNOOP_H__ */ + diff --git a/mt7620/src/include/ipv6.h b/mt7620/src/include/ipv6.h new file mode 100644 index 0000000..16c9b8e --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/link_list.h b/mt7620/src/include/link_list.h new file mode 100644 index 0000000..f00bae6 --- /dev/null +++ b/mt7620/src/include/link_list.h @@ -0,0 +1,180 @@ + +#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/mt7620/src/include/mat.h b/mt7620/src/include/mat.h new file mode 100644 index 0000000..336b612 --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/mesh.h b/mt7620/src/include/mesh.h new file mode 100644 index 0000000..c7f17fb --- /dev/null +++ b/mt7620/src/include/mesh.h @@ -0,0 +1,1047 @@ +/* + *************************************************************************** + * 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: + mesh.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi 2007-06-25 To Support Mesh (802.11s) feature. +*/ + +#ifndef __MESH_H__ +#define __MESH_H__ + +#define PRINT_MAC(addr) \ + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] + + +#define MESH_ON(_pAd) \ + (((_pAd)->flg_mesh_init) \ + && ((_pAd)->MeshTab.dev) \ + && (RtmpOSNetDevIsUp((_pAd)->MeshTab.dev) == TRUE)) + +#define INT24(_a) (((_a) & 0x800000) ? (~(_a)) : (_a)) +/*#define MESH_SEQ_AFTER(a, b) (INT24(b) - INT24(a) < 0) // Mesh Seq become 4 bytes in Draft 2.0. */ +#define MESH_SEQ_AFTER(a, b) ((INT32)(b) - (INT32)(a) < 0) +/*#define MESH_SEQ_SUB(a, b) (((a) >= (b)) ? ((a) - (b)) : ((a) + 0x007fffff - (b))) */ +#define MESH_SEQ_SUB(a, b) ((INT32)(a) - (INT32)(b)) + +#define MESH_MAC_ADDR_HASH_INDEX(_Addr) (MAC_ADDR_HASH((_Addr)) % MAX_HASH_NEIGHBOR_MP) +#define BMPKT_MAC_ADDR_HASH_INDEX(_Addr) (MAC_ADDR_HASH((_Addr)) & (MAX_HASH_BMPKTSIG_TAB_SIZE - 1)) +/*#define INC_MESH_SEQ(_idx) ((_idx) = (((_idx) + 1) & (0x00ffffff))) // Mesh Seq become 4 bytes in Draft 2.0. */ +#define INC_MESH_SEQ(_idx) ((_idx)++) + +#define IS_MULTICAST_MAC_ADDR(Addr) ((((Addr[0]) & 0x01) == 0x01) && ((Addr[0]) != 0xff)) + +/* + ========================================================================== + Description: + Get the Index of Beacon buffer. Mesh use the beacon buffer behind Last BBS. + So the index of Mesh Beacon buffer shall be BssidNum. + + Output: + the index of Mesh beacon. + ========================================================================== +*/ +static inline UCHAR MESH_BEACON_IDX(IN PRTMP_ADAPTER pAd) +{ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + return pAd->MeshTab.BcnBufIdx; + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + return 0; + } +#endif /* CONFIG_STA_SUPPORT */ +} + +static inline UCHAR GET_CAPABILITY_INFO(IN PRTMP_ADAPTER pAd) +{ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + return pAd->ApCfg.MBSSID[MAIN_MBSSID].CapabilityInfo; + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + return pAd->StaCfg.AssocInfo.RequestFixedIEs.Capabilities; + } +#endif /* CONFIG_STA_SUPPORT */ +} + +static inline VOID MeshChannelInit(IN PRTMP_ADAPTER pAd) +{ + /*if (!((pAd->net_dev) && (RTMP_OS_NETDEV_STATE_RUNNING(pAd->net_dev)))) */ + if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { +#ifdef DOT11_N_SUPPORT + N_ChannelCheck(pAd); + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && + pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + { + N_SetCenCh(pAd); + SetCommonHT(pAd); + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + pAd->MeshTab.ExtChOffset=pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset; + } + else +#endif /* DOT11_N_SUPPORT */ + { + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + } + } +} + +extern UCHAR MeshOUI[]; +extern UINT8 LenPeerLinkMngIE[]; + +INT Set_MeshId_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MeshHostName_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MeshAutoLink_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MeshForward_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MeshAddLink_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MeshPortal_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MeshDelLink_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MeshMaxTxRate_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MeshAuthMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MeshEncrypType_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MeshDefaultkey_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MeshWEPKEY_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MeshWPAKEY_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +BOOLEAN MeshValid( + PMESH_STRUCT pMesh); + +BOOLEAN PeerLinkMngRuning( + IN PRTMP_ADAPTER pAd, + IN USHORT Idx); + +BOOLEAN PeerLinkValidCheck( + IN PRTMP_ADAPTER pAd, + IN USHORT Idx); + +PMESH_LINK_ENTRY MeshLinkLookUp( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +ULONG MeshLinkAlloc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR LinkType); + +VOID MeshLinkDelete( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UINT MeshLinkIdx); + +VOID MeshPeerLinkOpenProcess( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk); + +VOID MeshPeerLinkConfirmProcess( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk); + +VOID MeshPeerLinkCloseProcess( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk); + +VOID MeshPeerLinkMetricReportProcess( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk); + +VOID MeshTimerInit( + IN PRTMP_ADAPTER pAd); + +VOID MeshLinkTableMaintenace( + IN PRTMP_ADAPTER pAd); + +BOOLEAN MeshAcceptPeerLink( + IN PRTMP_ADAPTER pAd); + +MAC_TABLE_ENTRY *MacTableInsertMeshEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UINT MeshLinkIdx); + +BOOLEAN MacTableDeleteMeshEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT wcid, + IN PUCHAR pAddr); + +MAC_TABLE_ENTRY *MeshTableLookup( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount); + +MAC_TABLE_ENTRY *MeshTableLookupByWcid( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount); + +MAC_TABLE_ENTRY *FindMeshEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN PUCHAR pAddr); + +BOOLEAN NeighborMPCheck( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMeshId, + IN UINT8 PathSelProtocolId, + IN UINT8 PathSelMetricId); + +PMESH_NEIGHBOR_ENTRY InsertNeighborMP( + IN PRTMP_ADAPTER pAd, + IN CHAR RealRssi, + IN PUCHAR pPeerMacAddr, + IN UCHAR Channel, + IN UINT8 ChBW, + IN UINT8 ExtChOffset, + IN PUCHAR pHostName, + IN PUCHAR pMeshId, + IN UCHAR MeshIdLen, + IN USHORT CapabilityInfo, + IN PUCHAR pVIE, + IN USHORT LenVIE, + IN PMESH_CONFIGURAION_IE pMeshConfig); + +VOID DeleteNeighborMP( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pPeerMacAddr); + +PMESH_NEIGHBOR_ENTRY NeighborSearch( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pPeerMacAddr); + +VOID NeighborTableUpdate( + IN PRTMP_ADAPTER pAd); + +VOID CandidateMPSelect( + IN PRTMP_ADAPTER pAd); + +void NeighborTableReset( + IN PRTMP_ADAPTER pAd); + +void NeighborTableInit( + IN PRTMP_ADAPTER pAd); + +void NeighborTableDestroy( + IN PRTMP_ADAPTER pAd); + +void ValidateLocalMPAsSelector( + IN PRTMP_ADAPTER pAd, + IN INT idx); + +void ValidateLocalMPAsAuthenticator( + IN PRTMP_ADAPTER pAd, + IN UCHAR idx, + IN PUCHAR pMscIe, + IN PUCHAR pMsaIe); + +BOOLEAN MeshKeySelectionAction( + IN PRTMP_ADAPTER pAd, + IN PMESH_LINK_ENTRY pMeshLinkEntry, + IN PUCHAR pMscIe, + IN PUCHAR pPmkId, + IN UCHAR PmkIdLen); + +VOID MeshUp( + IN PRTMP_ADAPTER pAd); + +VOID MeshDown( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN WaitFlag); + +VOID MeshHalt( + IN PRTMP_ADAPTER pAd); + +VOID TearDownAllMeshLink( + IN PRTMP_ADAPTER pAd); + +VOID MeshHeaderInit( + IN PRTMP_ADAPTER pAd, + OUT PHEADER_802_11 pMeshHdr, + IN PUCHAR Addr1, + IN PUCHAR Addr2, + IN PUCHAR Addr3); + +VOID InsertMeshHeader( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 MeshFlag, + IN UINT8 TTL, + IN UINT32 MeshSeq, + IN PUCHAR Addr4, + IN PUCHAR Addr5, + IN PUCHAR Addr6); + +VOID InsertMeshActField( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Category, + IN UINT8 ActCode); + +VOID InsertCapabilityInfo( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT16 CapabilityInfo); + +VOID InsertStatusCode( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT16 StatusCode); + +VOID InsertReasonCode( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT16 ReasonCode); + +VOID InsertAID( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT16 Aid); + +VOID InsertSupRateIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +VOID InsertExtRateIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +VOID InsertMeshConfigurationIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN BOOLEAN AcptLink); + +VOID InsertMeshIdIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +VOID InsertMSCIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +VOID InsertRSNIE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +VOID InsertMSAIE( + IN PRTMP_ADAPTER pAd, + IN UCHAR LinkIdx, + IN UCHAR state, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +VOID InsertMeshPeerLinkMngIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 SubType, + IN UINT16 LocalLinkId, + IN UINT16 PeerLinkId, + IN UINT16 ReasonCode); + +VOID InsertMeshPathRequestIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 MeshPreqFlag, + IN UCHAR HopCount, + IN UCHAR TTL, + IN ULONG ReqID, + IN PUCHAR pOrigAddr, + IN ULONG OrigSeq, + IN PUCHAR pProxyAddr, + IN ULONG LifeTime, + IN ULONG Metric, + IN UCHAR DestCount, + IN MESH_DEST_ENTRY MeshDestEntry); + +VOID InsertMeshPathResponseIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 MeshPrepFlag, + IN UCHAR HopCount, + IN UCHAR TTL, + IN PUCHAR pDestAddr, + IN ULONG DestSeq, + IN PUCHAR pDestProxyAddr, + IN ULONG LifeTime, + IN ULONG Metric, + IN PUCHAR pOrigAddr, + IN ULONG OrigSeq); + +VOID InsertMeshPathErrorIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UCHAR DestCount, + IN PMESH_PERR_ENTRY MeshPerrEntry); + +VOID InsertMeshProxyUpdateIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 ProxyFlags, + IN UINT8 ProxySeq, + IN PUCHAR pProxyMPAddr, + IN USHORT ProxiedCount, + IN PUCHAR pMeshProxiedEntry); + +VOID InsertMeshProxyUpdateConfirmationIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 ProxyFlags, + IN UINT8 ProxySeq, + IN PUCHAR pMeshProxiedEntry); + +VOID InsertMeshHostNameIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +VOID InsertMeshCongestionNotofocationIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUCHAR pPeerMac, + IN UCHAR SwitchOn); + +VOID InsertMeshChSwAnnIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 ChSwMode, + IN UINT8 NewCh, + IN UINT32 NewCPI, + IN UINT8 ChSwCnt, + IN PUCHAR pMeshSA); + +#ifdef DOT11_N_SUPPORT +VOID InsertHtCapIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PHT_CAPABILITY_IE pHtCapability); + +VOID InsertAddHtInfoIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PADD_HT_INFO_IE pAddHTInfo); +#endif /* DOT11_N_SUPPORT */ + +VOID InsertLinkMetricReportIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT32 LinkMetric); + +INT Set_MeshRouteAdd_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MeshRouteDelete_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MeshRouteUpdate_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MeshMultiCastAgeOut_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MeshInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_NeighborInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MeshRouteInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MeshProxyInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MeshEntryInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MultipathInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MultiCastAgeOut_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MeshOnly_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_PktSig_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + + +VOID RTMP_Mesh_Close( + IN PRTMP_ADAPTER ad_p); + +VOID MESH_Remove( + IN PRTMP_ADAPTER ad_p); + +VOID MeshCtrlStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID MeshLinkMngStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID MlmeHandleRxMeshFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk); + +VOID MeshPreqCreate( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pProxyAddr, + IN PUCHAR pDestAddr, + IN ULONG DestDsn); + +VOID MeshPreqRcvProcess( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk); + +VOID +MeshPreqForward( + IN PRTMP_ADAPTER pAd, + IN UINT8 MeshTTL, + IN UINT32 MeshSeq, + IN UINT8 MeshPreqFlag, + IN UCHAR HopCount, + IN UCHAR PreqTTL, + IN ULONG ReqID, + IN PUCHAR pOrigAddr, + IN ULONG OrigSeq, + IN PUCHAR pProxyAddr, + IN ULONG LifeTime, + IN ULONG Metric, + IN UCHAR DestCount, + IN MESH_DEST_ENTRY MeshDestEntry, + IN PUCHAR TransmissionAddr); + +VOID +MeshPrepCreate( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pNextHop, + IN PUCHAR pOrigAddr, + IN ULONG OrigDsn, + IN PUCHAR pProxyAddr); + +VOID +MeshPrepRcvProcess( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk); + +VOID +MeshPrepForward( + IN PRTMP_ADAPTER pAd, + IN UINT8 MeshTTL, + IN UINT32 MeshSeq, + IN UINT8 MeshPrepFlag, + IN UCHAR HopCount, + IN UCHAR PrepTTL, + IN PUCHAR pDestAddr, + IN ULONG DestSeq, + IN PUCHAR pProxyAddr, + IN ULONG LifeTime, + IN ULONG Metric, + IN PUCHAR pOrigAddr, + IN ULONG OrigSeq); + +VOID +MeshPerrRcvProcess( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk); + +VOID +MeshPerrCreate( + IN PRTMP_ADAPTER pAd, + IN UCHAR DestCount, + IN PMESH_PERR_ENTRY pDestEntry); +VOID +MeshPerrForward( + IN PRTMP_ADAPTER pAd, + IN UINT8 MeshTTL, + IN UINT32 MeshSeq, + IN UCHAR DestCount, + IN PMESH_PERR_ENTRY pDestEntry, + IN PUCHAR TxAddr); + +NDIS_STATUS +MeshRoutingTable_Init( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS +MeshRoutingTable_Exit( + IN PRTMP_ADAPTER pAd); + +PMESH_ROUTING_ENTRY +MeshRoutingTableLookup( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +PMESH_ROUTING_ENTRY +MeshRoutingTableInsert( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMeshDestAddr, + IN UINT32 Dsn, + IN PUCHAR pNextHop, + IN UCHAR Wcid, + IN UINT32 Metric); + +BOOLEAN +MeshRoutingTableDelete( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +PMESH_ROUTING_ENTRY +MeshRoutingTableUpdate( + IN PRTMP_ADAPTER pAd, + IN PUCHAR MeshDestAddr, + IN UINT32 Dsn, + IN PUCHAR NextHop, + IN UCHAR NextHopLinkID, + IN UINT32 Metric); + +PMESH_ROUTING_ENTRY +MeshRoutingTablePrecursorUpdate( + IN PRTMP_ADAPTER pAd, + IN PUCHAR MeshDestAddr, + IN PUCHAR Precursor); + +NDIS_STATUS +MeshEntryTable_Init( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS +MeshEntryTable_Exit( + IN PRTMP_ADAPTER pAd); + +PMESH_ENTRY +MeshEntryTableLookUp( + IN PRTMP_ADAPTER pAd, + IN PUCHAR DestAddr); + +PMESH_ENTRY +MeshEntryTableInsert( + IN PRTMP_ADAPTER pAd, + IN PUCHAR DestAddr, + IN UCHAR Idx); + +BOOLEAN +MeshEntryTableDelete( + IN PRTMP_ADAPTER pAd, + IN PUCHAR DestAddr); + +PMESH_ENTRY +MeshEntryTableUpdate( + IN PRTMP_ADAPTER pAd, + IN PUCHAR DestAddr, + IN UCHAR Idx); + +VOID +MeshEntryTableGet( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS +MeshProxyEntryTable_Init( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS +MeshProxyEntryTable_Exit( + IN PRTMP_ADAPTER pAd); + +PMESH_PROXY_ENTRY +MeshProxyEntryTableLookUp( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSA); + +PMESH_PROXY_ENTRY +MeshProxyEntryTableInsert( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMeshSA, + IN PUCHAR pSA); + +BOOLEAN +MeshProxyEntryTableDelete( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSA); + +PMESH_PROXY_ENTRY +MeshProxyEntryTableUpdate( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMeshSA, + IN PUCHAR pSA); + +VOID +MeshCreatePreqAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pProxyAddr, + IN PUCHAR pDestAddr); + +VOID +MeshPathReqTimeoutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID +MeshCreatePerrAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBreakMeshPoint); + +BOOLEAN +MeshAllowToSendPathResponse( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSA); + +VOID +MeshMultipathNotice( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pPeerMac, + IN PUCHAR pMeshSA, + IN UCHAR SwitchOn); + +VOID +MeshMultipathNoticeRcvProcess( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk); + +VOID +MeshChSwAnnounceProcess( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk); + +LONG +PathRouteIDSearch( + IN PRTMP_ADAPTER pAd, + IN PUCHAR DestAddr); + +INT +PathMeshLinkIDSearch( + IN PRTMP_ADAPTER pAd, + IN UCHAR RouteIdx); + +PUCHAR +PathRouteAddrSearch( + IN PRTMP_ADAPTER pAd, + IN UCHAR RouteIdx); + +UINT GetMeshHederLen( + IN PUCHAR pSrcBufVA); + +UINT8 GetMeshFlag( + IN PUCHAR pSrcBufVA); + +UINT8 GetMeshFlagAE( + IN PUCHAR pSrcBufVA); + +UINT8 GetMeshTTL( + IN PUCHAR pSrcBufVA); + +UINT32 GetMeshSeq( + IN PUCHAR pSrcBufVA); + +PUCHAR GetMeshAddr4( + IN PUCHAR pSrcBufVA); + +PUCHAR GetMeshAddr5( + IN PUCHAR pSrcBufVA); + +PUCHAR GetMeshAddr6( + IN PUCHAR pSrcBufVA); + +ULONG GetMeshLinkId( + IN PRTMP_ADAPTER pAd, + IN PCHAR PeerMacAddr); + +VOID MeshClonePacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UINT8 MeshSrc, + IN UINT8 MeshLinkIdx); + +VOID MultipathPoolInit( + IN PRTMP_ADAPTER pAd); + +VOID MultipathPoolExit( + IN PRTMP_ADAPTER pAd); + +PMESH_MULTIPATH_ENTRY MultipathEntyAlloc( + IN PRTMP_ADAPTER pAd); + +VOID MultipathEntyFree( + IN PRTMP_ADAPTER pAd, + IN PMESH_MULTIPATH_ENTRY pEntry); + +VOID MultipathEntryInsert( + IN PRTMP_ADAPTER pAd, + IN UCHAR LinkIdx, + IN PUCHAR pMac); + +VOID MultipathEntryDelete( + IN PRTMP_ADAPTER pAd, + IN UCHAR LinkIdx, + IN PUCHAR pMac); + +VOID MultipathListDelete( + IN PRTMP_ADAPTER pAd, + IN UCHAR LinkIdx); + +PMESH_MULTIPATH_ENTRY MultipathEntryLookUp( + IN PRTMP_ADAPTER pAd, + IN UCHAR LinkIdx, + IN PUCHAR pMac); + +VOID MultipathEntryMaintain( + IN PRTMP_ADAPTER pAd, + IN UCHAR LinkIdx); + +VOID MeshDataPktProcess( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN USHORT MeshLinkIdx, + OUT PNDIS_PACKET *pMeshForwardPacket, + OUT BOOLEAN *pbDirectForward, + OUT BOOLEAN *pbAnnounce); + +ULONG InsertPktMeshHeader( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN PUCHAR *pHeaderBufPtr); + +UINT32 RandomMeshCPI( + IN PRTMP_ADAPTER pAd); + +UINT16 RandomLinkId( + IN PRTMP_ADAPTER pAd); + +UINT8 RandomChSwWaitTime( + IN PRTMP_ADAPTER pAd); + +void rtmp_read_mesh_from_file( + IN PRTMP_ADAPTER pAd, + PSTRING tmpbuf, + PSTRING buffer); + +VOID BMPktSigTabInit( + IN PRTMP_ADAPTER pAd); + +VOID BMPktSigTabExit( + IN PRTMP_ADAPTER pAd); + +PMESH_BMPKTSIG_ENTRY BMPktSigTabLookUp( + IN PRTMP_ADAPTER pAd, + IN PUCHAR MeshSA); + +PMESH_BMPKTSIG_ENTRY BMPktSigTabInsert( + IN PRTMP_ADAPTER pAd, + IN PUCHAR MeshSA); + +VOID BMPktSigTabDelete( + IN PRTMP_ADAPTER pAd, + IN PUCHAR MeshSA); + +BOOLEAN PktSigCheck( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pTA, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN UINT32 MeshSeq, + IN ULONG FrameType); + +VOID LocalMsaIeInit( + IN PRTMP_ADAPTER pAd, + IN INT idx); + +VOID RTMPIoctlQueryMeshSecurityInfo( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +INT RTMPIoctlSetMeshSecurityInfo( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +UCHAR GetMeshSecurity( + IN PRTMP_ADAPTER pAd); + +UCHAR MeshCheckPeerMpCipher( + IN USHORT CapabilityInfo, + IN PUCHAR pVIE, + IN USHORT LenVIE); + +BOOLEAN MeshAllowToSendPacket( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + OUT UCHAR *pWcid); + +VOID PerpareMeshHeader( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + OUT PMESH_FLAG pMeshFlag, + OUT UINT16 *pMeshTTL, + OUT UINT32 *pMeshSeq, + OUT PUCHAR *ppMeshAddr5, + OUT PUCHAR *ppMeshAddr6); + +BOOLEAN MeshChCheck( + IN RTMP_ADAPTER *pAd, + IN PMESH_NEIGHBOR_ENTRY pNeighborEntry); + +VOID MeshMakeBeacon( + IN PRTMP_ADAPTER pAd, + IN UCHAR idx); + +VOID MeshUpdateBeaconFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR idx); + +VOID MeshCleanBeaconFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR idx); + +VOID AsicEnableMESHSync( + IN PRTMP_ADAPTER pAd); + +#ifdef CONFIG_STA_SUPPORT +BOOLEAN MeshWirelessForward( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN ULONG FromWhichBSSID); +#endif /* CONFIG_STA_SUPPORT */ + +UINT32 MeshAirLinkTime( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pMacEntry, + IN HTTRANSMIT_SETTING HTTxMode); + +UINT32 MESH_LinkMetricUpdate( + IN PRTMP_ADAPTER pAd, + IN PCHAR pDestAddr); + +VOID EnqueuePeerLinkMetricReport( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDestAddr, + IN UINT32 Metric); + + +VOID MeshCfgInit( + IN PRTMP_ADAPTER pAd, + IN PSTRING pHostName); + +VOID MeshInit( + IN PRTMP_ADAPTER pAd, + IN RTMP_OS_NETDEV_OP_HOOK *pNetDevOps); + +INT MESH_OpenPre( + IN PNET_DEV pDev); + +INT MESH_OpenPost( + IN PNET_DEV pDev); + +INT MESH_Close( + IN PNET_DEV pDev); + +#endif /* __MESH_H__ */ + diff --git a/mt7620/src/include/mesh_def.h b/mt7620/src/include/mesh_def.h new file mode 100644 index 0000000..dc3eab6 --- /dev/null +++ b/mt7620/src/include/mesh_def.h @@ -0,0 +1,692 @@ +/* + *************************************************************************** + * 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: + mesh_def.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi 2007-06-25 To Support Mesh (802.11s) feature. +*/ + +#ifndef __MESH_DEF_H__ +#define __MESH_DEF_H__ + +#include "rtmp_type.h" +#include "mesh_mlme.h" + +#define MAX_HOST_NAME_LEN MAX_HOST_NAME_LENGTH + 1 +#define MAX_MESH_ID_LEN MAX_MESH_ID_LENGTH + 1 +#define MAX_MESH_LINKS MAX_MESH_LINK_NUM +#define MAX_NEIGHBOR_MP MAX_NEIGHBOR_NUM +#define MAX_HASH_NEIGHBOR_MP (2 * MAX_NEIGHBOR_MP) +#define MAX_BMPKTSIG_TAB_SIZE 64 +/* Size of hash tab must be power of 2. */ +#define MAX_HASH_BMPKTSIG_TAB_SIZE (2 * MAX_BMPKTSIG_TAB_SIZE) +#define MULTIPATH_HASH_TAB_SIZE 256 +#define MULTIPATH_POOL_SIZE 256 +#define MAX_ROUTE_TAB_SIZE 64 +#define MAX_HASH_ROUTE_TAB_SIZE (2 * MAX_ROUTE_TAB_SIZE) +#define MAX_HASH_ENTRY_TAB_SIZE 256 +#define MAX_HASH_PROXY_ENTRY_TAB_SIZE 256 + +#define MESH_BMPKT_RECORD_TIME 500 +#define MESH_MAX_MSAIE_LEN 90 +#define MESH_MAX_PMKID_LEN (2 * LEN_PMKID) +#define MESH_PMK_LEN 32 +#define MESH_PMK_NAME_LEN 16 + +#define MESH_TTL 20 +#define MAX_OPEN_RETRY 7 +#define NEIGHBOR_MP_IDLE_CNT 2 +#define MESH_AGEOUT_TIME (10 * 1000 ) +#define MESH_BMPKT_RECORD_TIME 500 +#define MULTIPATH_AGEOUT (60 * 1000 ) /* 10 seconds. */ +#define MESH_PROXY_AGEOUT (OS_HZ*1800) /*30mins */ + + +#define DEFAULT_MESH_ID "MESH" +#define DEFAULT_MESH_HOST_NAME "RALINK_MESH" + +#define MESH_TU 1 +#define RANDOM_TIME(_pAd) (RandomByte((_pAd)) * 1000) /* 0 ~ 255 seconds */ +#define PLD_TIME (20 * 1000) /* 20 seconds */ +#define TOR_TIME (1 * 1000) /* 1 seconds */ +#define TOC_TIME (1 * 1000) /* 1 seconds */ +#define TOH_TIME (150) /* 150 ms */ + +#define MESH_NEIGHBOR_BEACON_IDLE_TIME (5 * 1000) /* 5 seconds. */ + +#define BMCAST_ROUTE_ID 0xff + +/* Mesh Link Type */ +#define MESH_LINK_DYNAMIC 0 +#define MESH_LINK_STATIC 1 + +/* Mesh Operation Mode */ +#define MESH_MP (1 << 0) +#define MESH_AP (1 << 1) +#define MESH_POTAL (1 << 2) +#define MESH_MKD (1 << 3) + +/* Mesh Direction */ +#define MESH_PROXY 0 +#define MESH_FORWARD 1 + +/* Mesh version */ +#define MESH_VERSION 1 + +#define NULL_PROTOCOL 255 +/* Mesh Path selection protocols. */ +#define MESH_HWMP 0 +#define MESH_OLSR 1 + +/* Mesh Path Metric protocols. */ +#define MESH_AIRTIME 0 + +/* FC Type field. */ +#define BTYPE_MESH BTYPE_MGMT + +/* FC Subtype field. */ +#define SUBTYPE_MULTIHOP 0xf + +/* Mesh Reason Code */ +#define MESH_LINK_CANCELLED 2 +#define MESH_MAX_PEERS 3 +#define MESH_CAPABILITY_POLICY_VIOLATION 4 +#define MESH_CLOSE_RCVD 5 +#define MESH_MAX_RETRIES 6 +#define MESH_CONFIRM_TIMEOUT 7 +#define MESH_SECURITY_ROLE_NEGOTIATION_DIFFERS 8 +#define MESH_SECURITY_AUTHENTICATION_IMPOSSBLE 9 +#define MESH_SECURITY_FAILED_VERIFICATION 10 +#define MESH_INVALID_GTK 11 +#define MESH_MISMATCH_GTK 12 +#define MESH_INCONSISTENT_PARAMETERS 13 + +/* Mesh status codes */ +#define MESH_LINK_ESTABLISHED 14 +#define MESH_LINK_CLOSED 15 +#define MESH_NO_LISTED_KEY_HOLDER_TRANSPORT_TYPE 16 +#define MESH_NO_LISTED_KEY_HOLDER_SECURITY_HANDSHAKE 17 +#define MESH_PEER_LINK_MAX_RETRIES 18 +#define MESH_PEER_LINK_NO_PMK 19 +#define MESH_PEER_LINK_ALT_PMK 20 +#define MESH_PEER_LINK_NO_AKM 21 +#define MESH_PEER_LINK_ALT_AKM 22 +#define MESH_PEER_LINK_NO_KDF 23 +#define MESH_PEER_LINK_SA_ESTABLISHED 24 +#define MESH_AUTH_REJE_AN_ANTI_CLOGGING_TOKEN_REQUIRE 25 + +/* Peer Link Management SubType */ +#define SUBTYPE_PEER_LINK_OPEN 0 +#define SUBTYPE_PEER_LINK_CONFIRM 1 +#define SUBTYPE_PEER_LINK_CLOSE 2 + +/* Category field */ +#define CATEGORY_MESH_PEER_LINK 15 +#define CATEGORY_MESH_LINK_METRIC 16 +#define CATEGORY_MESH_PATH_SELECTION 17 +#define CATEGORY_MESH_INTERWORKING 18 +#define CATEGORY_MESH_RES_COORDINATION 19 +#define CATEGORY_MESH_MSA 20 +#define CATEGORY_MESH_PROXY_FORWARDING 21 + +/* Link Metric Action Code */ +#define ACT_CODE_LINK_METRIC_REQ 0 +#define ACT_CODE_LINK_METRIC_REP 1 + +/* Peer Link Management Action Code */ +#define ACT_CODE_PEER_LINK_OPEN 0 +#define ACT_CODE_PEER_LINK_CONFIRM 1 +#define ACT_CODE_PEER_LINK_CLOSE 2 + +/* Path Selection Action Code */ +#define ACT_CODE_PATH_REQUEST 0 +#define ACT_CODE_PATH_REPLY 1 +#define ACT_CODE_PATH_ERROR 2 +#define ACT_CODE_MULTIPATH_NOTICE 3 + +/* Resource Coordination Action Code */ +#define RESOURCE_CONGESTION_CONTROL_NOTIFICATION 0 +#define RESOURCE_MDA_SETUP_REQUEST 1 +#define RESOURCE_MDA_SETUP_REPLY 2 +#define RESOURCE_MDAOP_ADVERTISEMENT_REQUEST 3 +#define RESOURCE_MDAOP_ADVERTISEMENT 4 +#define RESOURCE_MDAOP_SET_TEARDOWN 5 +#define RESOURCE_BEACON_TIMING_REQUEST 6 +#define RESOURCE_BEACON_TIMING_RESPONSE 7 +/*#define RESOURCE_TBTT_ADJUSTMENT_REQUEST 8 // new add in Version D1.08 */ +#define RESOURCE_CHANNEL_SWITCH_ANNOUNCEMENT 8 /* change to 9 in Version D1.08 */ +#define RESOURCE_CONNECTIVITY_REPORT 9 /* remove from Version D1.08 */ + +/* Proxy Forwarding Action Code */ +#define ACT_CODE_PROXY_UPDATE 0 +#define ACT_CODE_PROXY_UPDATE_CONFIRMATION 1 + +/* HWMP default value */ +#define MESH_MAX_LEN_OF_FORWARD_TABLE MESH_MAX_FORWARD_ENTRY_NUM +#define HWMP_PREQ_REFRESH_PERIOD (15 * 1000) +#define HWMP_PATH_LOSS_THRESHOLD 2 +#define HWMP_ACTIVE_PATH_TIMEOUT (5 * 1000) +#define HWMP_PREQ_RATELIMIT 2 +#define HWMP_NET_DIAMETER 20 +#define HWMP_MP_TRAVERSAL_TIME 40 +#define HWMP_NETDIAMTER_TRAVERSAL_TIME (HWMP_NET_DIAMETER*HWMP_MP_TRAVERSAL_TIME) +#define HWMP_NETDIAMETER_TRAVERSAL_TIME (2 * HWMP_NETDIAMTER_TRAVERSAL_TIME) +#define HWMP_MAX_PREQ_RETRIES 3 +#define HWMP_FORWARD_TABLE_LIFE_TIME 300 + +/* Mesh Element IEs. */ +#define MESH_IE_OFFSET 100 +#define IE_MESH_CONFIGURATION 21 + MESH_IE_OFFSET +#define IE_MESH_ID 22 + MESH_IE_OFFSET +#define IE_MESH_LINK_METRIC_REPORT 23 + MESH_IE_OFFSET +#define IE_MESH_CONGESTION_NOTIFICATION 24 + MESH_IE_OFFSET +#define IE_MESH_PEER_LINK_MANAGEMENT 25 + MESH_IE_OFFSET +#define IE_MESH_CHANNEL_SWITCH_ANNOUNCEMENT 26 + MESH_IE_OFFSET +#define IE_MESH_NEIGHBOR_LIST 27 + MESH_IE_OFFSET +#define IE_MESH_TIM 28 + MESH_IE_OFFSET +#define IE_MESH_ATIM_WINDOW_PARAMETER 29 + MESH_IE_OFFSET +#define IE_MESH_BEACOM_TIMING 30 + MESH_IE_OFFSET +#define IE_MESH_MDAOP_SETUP_REQUEST 31 + MESH_IE_OFFSET +#define IE_MESH_MDAOP_SETUP_REPLY 32 + MESH_IE_OFFSET +#define IE_MESH_MDAOP_ADVERTISEMENTS 33 + MESH_IE_OFFSET +#define IE_MESH_MDAOP_SET_TEARDOWN 34 + MESH_IE_OFFSET +#define IE_MESH_CONNECTIVITY_REPORT 35 + MESH_IE_OFFSET +#define IE_MESH_PANN 36 + MESH_IE_OFFSET +#define IE_MESH_RANN 37 + MESH_IE_OFFSET +#define IE_MESH_PREQ 38 + MESH_IE_OFFSET +#define IE_MESH_PREP 39 + MESH_IE_OFFSET +#define IE_MESH_PERR 40 + MESH_IE_OFFSET +#define IE_MESH_PU 41 + MESH_IE_OFFSET +#define IE_MESH_PUC 42 + MESH_IE_OFFSET +#define IE_MESH_HELLO 43 + MESH_IE_OFFSET +#define IE_MESH_TC 44 + MESH_IE_OFFSET +#define IE_MESH_MID 45 + MESH_IE_OFFSET +#define IE_MESH_LABA 46 + MESH_IE_OFFSET +#define IE_MESH_LABCA 47 + MESH_IE_OFFSET +#define IE_MESH_ABBR 48 + MESH_IE_OFFSET +#define IE_MESH_MSCIE 49 + MESH_IE_OFFSET +#define IE_MESH_MSAIE 50 + MESH_IE_OFFSET +#define IE_MESH_MULITI_PATH_NOTICE_IE 51 + MESH_IE_OFFSET + +/*for mesh proxy */ +#define SignalLinkListInsertHeadQueue(Array,QueueHeader,QueueEntryIndex) \ +{ \ + Array[QueueEntryIndex].Next=(QueueHeader)->Head; \ + (QueueHeader)->Head=QueueEntryIndex; \ + if ((QueueHeader)->Tail==-1) \ + (QueueHeader)->Tail=QueueEntryIndex; \ + (QueueHeader)->Number++; \ +} + +#define SignalLinkListRemoveFromHeadQueue(Array,QueueHeader) \ +(QueueHeader)->Head; \ +{ \ + SHORT Next; \ + if ((QueueHeader)->Head != -1) \ + { \ + Next=Array[(QueueHeader)->Head].Next; \ + (QueueHeader)->Head = Next; \ + if (Next==-1) \ + (QueueHeader)->Tail = -1; \ + (QueueHeader)->Number--; \ + } \ +} + +#define DoubleLinkListInsertTailQueue(Array,QueueHeader,QueueEntryIndex) \ +{ \ + Array[QueueEntryIndex].DLNext=-1; \ + Array[QueueEntryIndex].DLPrev=(QueueHeader)->Tail; \ + if ((QueueHeader)->Tail!=-1) \ + Array[(QueueHeader)->Tail].DLNext=QueueEntryIndex; \ + (QueueHeader)->Tail=QueueEntryIndex; \ + if ((QueueHeader)->Head==-1) \ + (QueueHeader)->Head=QueueEntryIndex; \ + (QueueHeader)->Number++; \ +} + +#define DoubleLinkListRemoveHeadQueue(Array,QueueHeader) \ +(QueueHeader)->Head; \ +{ \ + SHORT Next; \ + if ((QueueHeader)->Head != -1) \ + { \ + Next=Array[(QueueHeader)->Head].DLNext; \ + (QueueHeader)->Head = Next; \ + if (Next==-1) \ + (QueueHeader)->Tail = -1; \ + else \ + Array[(QueueHeader)->Head].DLPrev=-1; \ + (QueueHeader)->Number--; \ + } \ +} + +#define DoubleLinkListRemoveNode(Array,QueueHeader,QueueEntryIndex) \ +{ \ + if (Array[QueueEntryIndex].DLPrev==-1 && (QueueHeader)->Head==QueueEntryIndex) \ + (QueueHeader)->Head =Array[(QueueHeader)->Head].DLNext; \ + else \ + Array[Array[QueueEntryIndex].DLPrev].DLNext=Array[QueueEntryIndex].DLNext; \ + \ + if (Array[QueueEntryIndex].DLNext==-1 && (QueueHeader)->Tail==QueueEntryIndex) \ + (QueueHeader)->Tail =Array[(QueueHeader)->Tail].DLPrev; \ + else \ + Array[Array[QueueEntryIndex].DLNext].DLPrev=Array[QueueEntryIndex].DLPrev; \ + (QueueHeader)->Number--; \ +} +/*for mesh proxy end */ + +typedef union _MESH_FLAG +{ + struct + { +#ifdef RT_BIG_ENDIAN + UINT8 Reserv:6; + UINT8 AE:2; +#else + UINT8 AE:2; + UINT8 Reserv:6; +#endif + }field; + UINT8 word; +} MESH_FLAG, *PMESH_FLAG; + +typedef struct GNU_PACKED _MESH_HEADER +{ + UINT8 MeshFlag; + UINT8 MeshTTL; + UINT32 MeshSeq; +} MESH_HEADER, *PMESH_HEADER; + +typedef union _MESH_PREQ_FLAG +{ + struct + { +#ifdef RT_BIG_ENDIAN + UINT8 Reserv2:1; + UINT8 AE:1; + UINT8 Reserv:3; + UINT8 ProactivePrep:1; + UINT8 AddrType:1; + UINT8 PortalRole:1; +#else + UINT8 PortalRole:1; + UINT8 AddrType:1; + UINT8 ProactivePrep:1; + UINT8 Reserv:3; + UINT8 AE:1; + UINT8 Reserv2:1; +#endif + }field; + UINT8 word; +} MESH_PREQ_FLAG, *PMESH_PREQ_FLAG; + +typedef union _MESH_PREP_FLAG +{ + struct + { +#ifdef RT_BIG_ENDIAN + UINT8 Reserv1:1; + UINT8 AE:1; + UINT8 Reserv:6; +#else + UINT8 Reserv:6; + UINT8 AE:1; + UINT8 Reserv1:1; +#endif + }field; + UINT8 word; +} MESH_PREP_FLAG, *PMESH_PREP_FLAG; + +typedef union _MESH_PER_DEST_FLAG +{ + struct + { +#ifdef RT_BIG_ENDIAN + UINT8 Reserv:6; + UINT8 RF:1; + UINT8 DO:1; +#else + UINT8 DO:1; + UINT8 RF:1; + UINT8 Reserv:6; +#endif + }field; + UINT8 word; +} MESH_PER_DEST_FLAG, *PMESH_PER_DEST_FLAG; + +typedef union GNU_PACKED _MESH_SECURITY_CONFIGURATION +{ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT8 Reserv:5; + UINT8 DefaultRole:1; + UINT8 ConnectedToMKD:1; + UINT8 MeshAuthenticator:1; +#else + UINT8 MeshAuthenticator:1; + UINT8 ConnectedToMKD:1; + UINT8 DefaultRole:1; + UINT8 Reserv:5; +#endif + }field; + UINT8 word; +} MESH_SECURITY_CONFIGURATION, *PMESH_SECURITY_CONFIGURATION; + +typedef union GNU_PACKED _MESH_HANDSHAKE_CONTROL +{ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT8 Reserv:7; + UINT8 RequestAuth:1; +#else + UINT8 RequestAuth:1; + UINT8 Reserv:7; +#endif + }field; + UINT8 word; +} MESH_HANDSHAKE_CONTROL, *PMESH_HANDSHAKE_CONTROL; + +typedef union _MESH_CAPABILITY +{ + struct + { +#ifdef RT_BIG_ENDIAN + UINT16 Reserv:10; + UINT16 PowerSaveLevel:1; + UINT16 TBTTAdjustEnable:1; + UINT16 BeaconTimingReportEnable:1; + UINT16 Forwarding:1; + UINT16 MDAEnable:1; + UINT16 AcceptPeerLinks:1; +#else + UINT16 AcceptPeerLinks:1; + UINT16 MDAEnable:1; + UINT16 Forwarding:1; + UINT16 BeaconTimingReportEnable:1; + UINT16 TBTTAdjustEnable:1; + UINT16 PowerSaveLevel:1; + UINT16 Reserv:10; +#endif + }field; + UINT16 word; +} MESH_CAPABILITY, *PMESH_CAPABILITY; + +typedef struct _MESH_CONFIGURAION_IE +{ + UCHAR Version; + UCHAR PathSelProtocolId; + UCHAR PathSelMetricId; + UINT32 CPI; + MESH_CAPABILITY MeshCapability; +} MESH_CONFIGURAION_IE, *PMESH_CONFIGURAION_IE; + +typedef struct _MESH_MULTIPATH_ENTRY +{ + struct _MESH_MULTIPATH_ENTRY *pNext; + ULONG ReferTime; + UCHAR MeshSA[MAC_ADDR_LEN]; +} MESH_MULTIPATH_ENTRY, *PMESH_MULTIPATH_ENTRY; + +/* MSC_IE */ +typedef struct GNU_PACKED _MESH_SECURITY_CAPABILITY_IE +{ + UCHAR MKDDID[MAC_ADDR_LEN]; + MESH_SECURITY_CONFIGURATION MeshSecurityConfig; +} MESH_SECURITY_CAPABILITY_IE, *PMESH_SECURITY_CAPABILITY_IE; + +/* MSA_IE */ +typedef struct GNU_PACKED _MSA_HANDSHAKE_IE +{ + MESH_HANDSHAKE_CONTROL MeshHSControl; + UCHAR MA_ID[MAC_ADDR_LEN]; + UCHAR SelectedAKM[LEN_OUI_SUITE]; + UCHAR SelectedPairwiseCipher[LEN_OUI_SUITE]; + UCHAR Octet[0]; +} MSA_HANDSHAKE_IE, *PMSA_HANDSHAKE_IE; + +typedef struct _MESH_LINK_ENTRY +{ + UCHAR OneSecBeaconCount; + ULONG OpenRetyCnt; + ULONG LastBeaconTime; + UCHAR LinkType; /* 0: Dynamic, 1: Static. */ + BOOLEAN Valid; /* 1: Candidate MP decided, 0: no candidate MP. */ + + UCHAR PeerMacAddr[MAC_ADDR_LEN]; + USHORT MacTabMatchWCID; /* ASIC */ + UINT16 LocalLinkId; + UINT16 PeerLinkId; + UINT32 Metrics; /* link cost. */ + UINT16 PeerMeshSeq; + LIST_HEADER MultiPathHash[MULTIPATH_HASH_TAB_SIZE]; + + UCHAR LocalMsaIe[MESH_MAX_MSAIE_LEN]; /* Local MP's MSAIE */ + UCHAR LocalMsaIeLen; + + UCHAR RcvdMsaIe[MESH_MAX_MSAIE_LEN]; /* Save the received peer MP's MSAIE */ + UCHAR RcvdMsaIeLen; + + MESH_SECURITY_CAPABILITY_IE RcvdMscIe; /* Save the received peer MP's MSCIE */ + + UINT8 ExtChOffset; /* save ExtChOffset to detect neighbor's change */ + + UCHAR RcvdRSNIE[MAX_LEN_OF_RSNIE]; + UCHAR RcvdRSNIE_Len; + + UCHAR RcvdPMKID[MESH_MAX_PMKID_LEN]; + UCHAR RcvdPMKID_Len; + + BOOLEAN bInitialMsaLink; /* This is an Initial MSA link, no matter local or peer MP */ + BOOLEAN bValidLocalMpAsSelector; + BOOLEAN bValidLocalMpAsAuthenticator; + + MESH_KEY_SELECTION MeshKeySelection; + + UCHAR PMK_MA[MESH_PMK_LEN]; + UCHAR PMK_MA_NAME[MESH_PMK_NAME_LEN]; + +} MESH_LINK_ENTRY, *PMESH_LINK_ENTRY; + +typedef struct _MESH_LINK +{ + MESH_LINK_ENTRY Entry; + MESH_LINK_MNG_STATE CurrentState; + RALINK_TIMER_STRUCT TOR, TOC, TOH; +} MESH_LINK, *PMESH_LINK; + +typedef struct _MESH_NEIGHBOR +{ + struct _MESH_NEIGHBOR *pNext; + BOOLEAN Valid; + /* needed attri flag such as MAP, Portal.. */ + + UCHAR PeerMac[MAC_ADDR_LEN]; + UCHAR HostName[MAX_HOST_NAME_LEN]; + UCHAR MeshId[MAX_MESH_ID_LEN]; + UCHAR MeshIdLen; + UINT8 Version; + UINT32 CPI; + UINT32 Channel; + UINT8 ChBW; + UINT8 ExtChOffset; + UINT8 PathProtocolId; /* 0: mean HWMP. */ + UINT8 PathMetricId; /* 0: airtime. */ + MESH_CAPABILITY MeshCapability; + CHAR RealRssi; + + UINT IdleCnt; + ULONG LastBeaconTime; + MESH_NEIGH_STATE State; + UCHAR MeshLinkIdx; + /*UCHAR MeshEncrypType; */ + USHORT CapabilityInfo; + UCHAR RSNIE[MAX_LEN_OF_RSNIE]; + USHORT RSNIE_Len; +} MESH_NEIGHBOR_ENTRY, *PMESH_NEIGHBOR_ENTRY; + +typedef struct _MESH_NEIGHBOR_TAB +{ + UCHAR NeighborNr; + PMESH_NEIGHBOR_ENTRY Hash[MAX_HASH_NEIGHBOR_MP]; + MESH_NEIGHBOR_ENTRY NeighborMP[MAX_NEIGHBOR_MP]; +} MESH_NEIGHBOR_TAB, *PMESH_NEIGHBOR_TAB; + +typedef struct _MESH_ROUTING_ENTRY +{ + struct _MESH_ROUTING_ENTRY *pNext; + + BOOLEAN Valid; + UCHAR MeshDA[MAC_ADDR_LEN]; + UINT32 Dsn; + UCHAR NextHop[MAC_ADDR_LEN]; + UCHAR NextHopLinkID; + UINT32 PathMetric; + BOOLEAN bPrecursor; + UCHAR Precursor[MAC_ADDR_LEN]; + UINT32 LifeTime; + UCHAR Idx; +} MESH_ROUTING_ENTRY, *PMESH_ROUTING_ENTRY; + +typedef struct _MESH_ROUTING_TABLE { + USHORT Size; + PMESH_ROUTING_ENTRY Hash[MAX_HASH_ENTRY_TAB_SIZE]; + MESH_ROUTING_ENTRY Content[MAX_ROUTE_TAB_SIZE]; +} MESH_ROUTING_TABLE, *PMESH_ROUTING_TABLE; + +typedef struct _PATH_REQ_ENTRY{ + UCHAR RetryCount; + BOOLEAN bProxied; + UCHAR ProxyAddr[MAC_ADDR_LEN]; + UCHAR DestAddr[MAC_ADDR_LEN]; + UINT32 DestDsn; + BOOLEAN PathReqTimerRunning; + RALINK_TIMER_STRUCT PathReqTimer; + PVOID pAdapter; +} PATH_REQ_ENTRY, *PPATH_REQ_ENTRY; + +typedef struct _MESH_ENTRY +{ + struct _MESH_ENTRY *pNext; + + BOOLEAN Valid; + UCHAR Idx; + UCHAR DestAddr[MAC_ADDR_LEN]; + BOOLEAN PathReqTimerRunning; + UINT32 LifeTime; + PATH_REQ_ENTRY *PathReq; +} MESH_ENTRY, *PMESH_ENTRY; + +typedef struct _MESH_ENTRY_TABLE { + USHORT Size; + PMESH_ENTRY Hash[MAX_HASH_ENTRY_TAB_SIZE]; +} MESH_ENTRY_TABLE, *PMESH_ENTRY_TABLE; + +typedef struct _QUEUE_HEADER_FOR_ARRAY { + SHORT Head; + SHORT Tail; + USHORT Number; +} QUEUE_HEADER_FOR_ARRAY, *PQUEUE_HEADER_FOR_ARRAY; + +typedef struct _MESH_PROXY_ENTRY +{ + SHORT Next; /*mac hash link list next */ + SHORT DLNext; /*double link list next */ + SHORT DLPrev; /*doubli link list prev */ + + BOOLEAN isMesh; + BOOLEAN isProxied; + ULONG LastUpdateTime; + UCHAR MacAddr[MAC_ADDR_LEN]; + UCHAR Owner[MAC_ADDR_LEN]; +} MESH_PROXY_ENTRY, *PMESH_PROXY_ENTRY; + +typedef struct _MESH_PROXY_ENTRY_TABLE { + QUEUE_HEADER_FOR_ARRAY AgeList; + QUEUE_HEADER_FOR_ARRAY FreeEntryList; + USHORT Size; + SHORT Hash[MAX_HASH_ENTRY_TAB_SIZE]; + MESH_PROXY_ENTRY Content[MAX_HASH_PROXY_ENTRY_TAB_SIZE]; +} MESH_PROXY_ENTRY_TABLE, *PMESH_PROXY_ENTRY_TABLE; + +typedef struct _MESH_BMPKTSIG_ENTRY +{ + struct _MESH_BMPKTSIG_ENTRY *pNext; + + BOOLEAN Valid; + UCHAR MeshSA[MAC_ADDR_LEN]; + UCHAR Precursor[MAC_ADDR_LEN]; + UINT32 MeshSeqBased; + UINT32 Offset[4]; + /* mesh unicast packet doesn't need to check packet signature. */ + /*UINT32 UcaseMeshSeq;*/ + ULONG LastRefTime; +} MESH_BMPKTSIG_ENTRY, *PMESH_BMPKTSIG_ENTRY; + +typedef struct _MESH_BMPKTSIG_TAB +{ + UCHAR Size; + PMESH_BMPKTSIG_ENTRY Hash[MAX_HASH_BMPKTSIG_TAB_SIZE]; + MESH_BMPKTSIG_ENTRY Content[MAX_BMPKTSIG_TAB_SIZE]; +} MESH_BMPKTSIG_TAB, *PMESH_BMPKTSIG_TAB; + +typedef struct GNU_PACKED _MESH_DEST_ENTRY +{ + UINT8 PerDestFlag; + UCHAR DestAddr[MAC_ADDR_LEN]; + UINT32 Dsn; +} MESH_DEST_ENTRY, *PMESH_DEST_ENTRY; + +typedef struct GNU_PACKED _MESH_PERR_ENTRY +{ + UCHAR DestAddr[MAC_ADDR_LEN]; + UINT32 Dsn; +} MESH_PERR_ENTRY, *PMESH_PERR_ENTRY; + +typedef struct GNU_PACKED _MESH_PERR_TABLE +{ + UCHAR size; + MESH_PERR_ENTRY PerrEntry[MAX_ROUTE_TAB_SIZE]; +} MESH_PERR_TABLE, *PMESH_PERR_TABLE; + +typedef struct GNU_PACKED _MESH_PREP_DEPENDENT_ENTRY +{ + UCHAR DependAddr[MAC_ADDR_LEN]; + UINT32 Dsn; +} MESH_PREP_DEPENDENT_ENTRY, *PMESH_PREP_DEPENDENT_ENTRY; + +typedef struct GNU_PACKED _MESH_PREP_DEPENDENT_TABLE +{ + UCHAR size; + MESH_PREP_DEPENDENT_ENTRY PrepDependEntry[MAX_ROUTE_TAB_SIZE]; +} MESH_PREP_DEPENDENT_TABLE, *PMESH_PREP_DEPENDENT_TABLE; + +typedef struct GNU_PACKED _MESH_DEPENDENT_ENTRY +{ + UCHAR DependAddr[MAC_ADDR_LEN]; + UINT32 Dsn; +} MESH_DEPENDENT_ENTRY, *PMESH_DEPENDENT_ENTRY; + +#endif /* __MESH_DEF_H__ */ + diff --git a/mt7620/src/include/mesh_mlme.h b/mt7620/src/include/mesh_mlme.h new file mode 100644 index 0000000..5fa6918 --- /dev/null +++ b/mt7620/src/include/mesh_mlme.h @@ -0,0 +1,164 @@ +/* + *************************************************************************** + * 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: + mesh_mlme.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi 2007-06-25 To Support Mesh (802.11s) feature. +*/ + +#ifndef __MESH_MLME_H__ +#define __MESH_MLME_H__ + +#include "mesh_def.h" + +#define VALID_MESH_LINK_ID(_idx) ((_idx) < MAX_MESH_LINKS ) +#define MeshMlmeHandler RTMP_MLME_HANDLER + +#define IS_MESH_IF(pObj) (pObj->ioctl_if_type == INT_MESH) + +typedef enum _MESH_NEIGH_STATE +{ + NEIGHBOR_MP, + CANDIDATE_MP, + ASSOCIATION_PENDING, + LINK_UNAVAILABLE, + LINK_AVAILABLE, +} MESH_NEIGH_STATE; + +/* states of mesh ctrl state machine */ +typedef enum _MESH_CTRL_STATE +{ + MESH_CTRL_IDLE, + MESH_CTRL_DISCOVERY, + MESH_CTRL_ACTIVATED, + MESH_CTRL_UCG, + MESH_CTRL_MAX_STATES, +} MESH_CTRL_STATE; + +/* events of mesh ctrl state machine */ +typedef enum _MESH_CTRL_EVENT +{ + /* Events from SME. */ + MESH_CTRL_JOIN, /* join a mesh. */ + MESH_CTRL_DEL_LINK, /* delete a specific link. */ + MESH_CTRL_PLD, /* discovery peer link. */ + MESH_CTRL_DISCONNECT, /* leave the mesh. */ + + /* Internal Events. */ + APMT2_MLME_SCAN_FINISH, + APMT2_MLME_SCAN_ABORT, + MESH_CTRL_UCG_EVT, + MESH_PEER_UCG_EVT, + + /* Timer Events. */ + MESH_CTRL_MCS_TIMEOUT, + MESH_CTRL_MAX_EVENTS, +} MESH_CTRL_EVENT; + +#define MESH_CTRL_FUNC_SIZE (MESH_CTRL_MAX_STATES * MESH_CTRL_MAX_EVENTS) + +/* states of mesh link management state machine */ +typedef enum _MESH_LINK_MNG_STATE +{ + MESH_LINK_MNG_IDLE, + MESH_LINK_MNG_LISTEN, + MESH_LINK_MNG_OPN_SNT, + MESH_LINK_MNG_CFN_RCVD, + MESH_LINK_MNG_OPN_RCVD, + MESH_LINK_MNG_ESTAB, + MESH_LINK_MNG_HOLDING, + MESH_LINK_MNG_MAX_STATES, +} MESH_LINK_MNG_STATE; + +/* events of mesh link management state machine */ +typedef enum _MESH_LINK_MNG_EVENT +{ + /* Events from SME. */ + MESH_LINK_MNG_CNCL, + MESH_LINK_MNG_PASOPN, + MESH_LINK_MNG_ACTOPN, + + /* External Events. */ + MESH_LINK_MNG_CLS_ACPT, + MESH_LINK_MNG_CLS_IGNR, + MESH_LINK_MNG_OPEN_ACPT, + MESH_LINK_MNG_OPEN_RJCT, + MESH_LINK_MNG_OPEN_IGNR, + MESH_LINK_MNG_CFN_ACPT, + MESH_LINK_MNG_CFN_RJCT, + MESH_LINK_MNG_CFN_IGNR, + + /* Timer Events. */ + MESH_LINK_MNG_TOR1, + MESH_LINK_MNG_TOR2, + MESH_LINK_MNG_TOC, + MESH_LINK_MNG_TOH, + MESH_LINK_MNG_MAX_EVENTS, +} MESH_LINK_MNG_EVENT; + +#define MESH_LINK_MNG_FUNC_SIZE (MESH_LINK_MNG_MAX_STATES * MESH_LINK_MNG_MAX_EVENTS) + +typedef struct _MESH_LINK_OPEN_MSG_STRUCT +{ + UINT32 CPI; + UINT16 MeshCapabilty; + UINT16 PeerLinkId; + UINT16 ReasonCode; + UCHAR MaxSupportedRate; + UCHAR SupRateLen; + HT_CAPABILITY_IE HTCapability; + UCHAR HTCapability_Len; + BOOLEAN bWmmCapable; +} MESH_LINK_OPEN_MSG_STRUCT, *PMESH_LINK_OPEN_MSG_STRUCT; + +typedef struct _MESH_LINK_CONFIRM_MSG_STRUCT +{ + UINT32 CPI; + UINT16 StatusCode; + UINT16 Aid; + UINT16 MeshCapabilty; + UINT16 LocalLinkId; + UINT16 PeerLinkId; + UINT16 ReasonCode; +} MESH_LINK_CONFIRM_MSG_STRUCT, *PMESH_LINK_CONFIRM_MSG_STRUCT; + +typedef struct _MESH_LINK_CLOSE_MSG_STRUCT +{ + UINT16 LocalLinkId; + UINT16 PeerLinkId; + UINT16 ReasonCode; +} MESH_LINK_CLOSE_MSG_STRUCT, *PMESH_LINK_CLOSE_MSG_STRUCT; + +typedef struct _MESH_CH_SW_ANN_MSG_STRUCT +{ + UINT32 NewCPI; + UINT32 MeshSeq; + UINT8 MeshTTL; + UINT8 ChSwCnt; + UINT8 NewCh; + UINT8 ChSwMode; + UINT8 LinkId; + UCHAR MeshSA[MAC_ADDR_LEN]; +} MESH_CH_SW_ANN_MSG_STRUCT, *PMESH_CH_SW_ANN_MSG_STRUCT; + +#endif /* __MESH_MLME_H__ */ diff --git a/mt7620/src/include/mesh_sanity.h b/mt7620/src/include/mesh_sanity.h new file mode 100644 index 0000000..4f5f887 --- /dev/null +++ b/mt7620/src/include/mesh_sanity.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: + mesh.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi 2007-07-23 To Support Mesh (802.11s) feature. +*/ +#ifndef __MESH_SANITY_H__ +#define __MESH_SANITY_H__ + +BOOLEAN MeshPeerBeaconAndProbeSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pHostName, + OUT PUCHAR pHostNameLen, + OUT PUCHAR pMeshId, + OUT PUCHAR pMeshIdLen, + OUT PMESH_CONFIGURAION_IE pMeshConfiguration); + +BOOLEAN MeshLinkMngOpenSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT UINT16 *pCapabilityInfo, + OUT UCHAR SupRate[], + OUT PUCHAR pSupRateLen, + OUT PUCHAR pMeshIdLen, + OUT PUCHAR pMeshId, + OUT PUCHAR pMeshSelPathId, + OUT PUCHAR pMeshSelMetricId, + OUT UINT32 *pCPI, + OUT PMESH_CAPABILITY pMeshCapabilty, + OUT UINT16 *pPeerLinkId, + OUT PMESH_SECURITY_CAPABILITY_IE pMscIe, + OUT PUCHAR pMsaIe, + OUT PUCHAR pMsaIeLen, + OUT PUCHAR pRsnIe, + OUT PUCHAR pRsnIeLen, + OUT BOOLEAN *pbWmmCapable, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT UCHAR *pHtCapabilityLen); + +BOOLEAN MeshLinkMngCfnSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT UINT16 *pCapabilityInfo, + OUT UINT16 *pStatusCode, + OUT UINT16 *pAid, + OUT UCHAR SupRate[], + OUT PUCHAR pSupRateLen, + OUT PUCHAR pMeshIdLen, + OUT PUCHAR pMeshId, + OUT PUCHAR pMeshSelPathId, + OUT PUCHAR pMeshSelMetricId, + OUT UINT32 *pCPI, + OUT PMESH_CAPABILITY pMeshCapabilty, + OUT UINT16 *pLocalLinkId, + OUT UINT16 *pPeerLinkId, + OUT PMESH_SECURITY_CAPABILITY_IE pMscIe, + OUT PUCHAR pMsaIe, + OUT PUCHAR pMsaIeLen, + OUT PUCHAR pRsnIe, + OUT PUCHAR pRsnIeLen, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT UCHAR *pHtCapabilityLen); + +BOOLEAN MeshLinkMngClsSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT UINT16 *pLocalLinkId, + OUT UINT16 *pPeerLinkId, + OUT UINT16 *pReasonCode); + +BOOLEAN MeshPathSelMultipathNoticeSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT UINT8 *pFlag, + OUT PUCHAR pMeshSA); + +BOOLEAN MeshChannelSwitchAnnouncementSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT UINT8 *pChSwMode, + OUT UINT8 *pNewCh, + OUT UINT32 *pNewCPI, + OUT UINT8 *pChSwCnt, + OUT PUCHAR pMeshSA); + +BOOLEAN MeshValidateRSNIE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pRsnIe, + IN USHORT peerRsnIeLen, + OUT UCHAR *PureRsnLen, + OUT UCHAR *PmkIdLen); + +BOOLEAN MeshCheckGroupCipher( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN UCHAR Eid); + +BOOLEAN MeshCheckPairwiseCipher( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN UCHAR Eid); + +BOOLEAN MeshCheckAKMSuite( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN UCHAR Eid); + +UINT16 MeshValidateOpenAndCfnPeerLinkMsg( + IN PRTMP_ADAPTER pAd, + IN UCHAR state, + IN PMESH_LINK_ENTRY pMeshLinkEntry, + IN PUCHAR pRcvdMscIe, + IN PUCHAR pRcvdMsaIe, + IN UCHAR RcvdMsaIeLen, + IN PUCHAR pRcvdRsnIe, + IN UCHAR RcvdRsnIeLen, + IN UCHAR pure_rsn_len, + IN UCHAR pmkid_len); + +UINT16 MeshCheckPeerMsaIeCipherValidity( + IN PRTMP_ADAPTER pAd, + IN UCHAR state, + IN PMESH_LINK_ENTRY pMeshLinkEntry, + IN PUCHAR pRcvdMsaIe); + +BOOLEAN MeshPathRequestSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT UINT8 *pFlag, + OUT UINT8 *pHopCount, + OUT UINT8 *pTTL, + OUT UINT32 *pID, + OUT PUCHAR pOrigMac, + OUT UINT32 *pOrigDsn, + OUT PUCHAR pProxyMac, + OUT UINT32 *pLifeTime, + OUT UINT32 *pMetric, + OUT UINT8 *pDestCount, + OUT PMESH_DEST_ENTRY pDestEntry); + +BOOLEAN MeshPathResponseSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT UINT8 *pFlag, + OUT UINT8 *pHopCount, + OUT UINT8 *pTTL, + OUT PUCHAR pDestMac, + OUT UINT32 *pDesDsn, + OUT PUCHAR pProxyMac, + OUT UINT32 *pLifeTime, + OUT UINT32 *pMetric, + OUT PUCHAR pOrigMac, + OUT UINT32 *pOrigDsn, + OUT UINT8 *pDependMPCount, + OUT PMESH_DEPENDENT_ENTRY pDependEntry); + +BOOLEAN MeshPathErrorSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT UINT8 *pFlag, + OUT UINT8 *pDestNum, + OUT PMESH_PERR_ENTRY pErrorEntry); + +BOOLEAN MeshLinkMetricReportSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUINT32 pLinkMetric); +#endif /* __MESH_SANITY_H__ */ diff --git a/mt7620/src/include/misc.h b/mt7620/src/include/misc.h new file mode 100644 index 0000000..2248bd3 --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/misc_cmm.h b/mt7620/src/include/misc_cmm.h new file mode 100644 index 0000000..aa91c80 --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/mlme.h b/mt7620/src/include/mlme.h new file mode 100644 index 0000000..5357c5f --- /dev/null +++ b/mt7620/src/include/mlme.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-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 CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_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 */ +/*#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 + +#define BEACON_LOST_TIME 4 * OS_HZ /* 2048 msec = 2 sec */ + +#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 CW_MIN_IN_BITS 4 /* actual CwMin = 2^CW_MIN_IN_BITS - 1 */ +#define AUTO_CHANNEL_SEL_TIMEOUT 400 /* uint: msec */ +#define LINK_DOWN_TIMEOUT 20000 /* unit: msec */ +#define AUTO_WAKEUP_TIMEOUT 70 /*unit: msec */ + +#ifdef CONFIG_AP_SUPPORT +#ifndef CONFIG_STA_SUPPORT +#define CW_MAX_IN_BITS 6 /* actual CwMax = 2^CW_MAX_IN_BITS - 1 */ +#endif /* CONFIG_STA_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifndef CONFIG_AP_SUPPORT +#define CW_MAX_IN_BITS 10 /* actual CwMax = 2^CW_MAX_IN_BITS - 1 */ +#endif /* CONFIG_AP_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +extern UINT32 CW_MAX_IN_BITS; +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ + +/* 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 PEER_KEY_NOT_USED 0 */ +/*#define PEER_KEY_64_BIT 64 */ +/*#define PEER_KEY_128_BIT 128 */ + +/*#define PEER_KEY_64BIT_LEN 8 */ +/*#define PEER_KEY_128BIT_LEN 16 */ + +#define BSS_NOT_FOUND 0xFFFFFFFF + +#ifdef CONFIG_AP_SUPPORT +#ifndef CONFIG_STA_SUPPORT +#define MAX_LEN_OF_MLME_QUEUE 20 /*10 */ +#endif +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#define MAX_LEN_OF_MLME_QUEUE 40 /*10 */ +#endif /* CONFIG_STA_SUPPORT */ + +#define SCAN_PASSIVE 18 /* scan with no probe request, only wait beacon and probe response */ +#define SCAN_ACTIVE 19 /* scan with probe request, and wait beacon and probe response */ +#define SCAN_CISCO_PASSIVE 20 /* Single channel passive scan */ +#define SCAN_CISCO_ACTIVE 21 /* Single channel active scan */ +#define SCAN_CISCO_NOISE 22 /* Single channel passive scan for noise histogram collection */ +#define SCAN_CISCO_CHANNEL_LOAD 23 /* Single channel passive scan for channel load collection */ +#define FAST_SCAN_ACTIVE 24 /* scan with probe request, and wait beacon and probe response */ +#ifdef WSC_INCLUDED +#define SCAN_WSC_ACTIVE 25 +#endif /* WSC_INCLUDED */ + +#ifdef DOT11N_DRAFT3 +#define SCAN_2040_BSS_COEXIST 26 +#endif /* DOT11N_DRAFT3 */ + +#ifdef P2P_SUPPORT +#define SCAN_P2P 28 +#define SCAN_P2P_SEARCH 29 +#endif /* P2P_SUPPORT */ + +/*#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)) + +/* LED Control */ +/* assoiation ON. one LED ON. another blinking when TX, OFF when idle */ +/* no association, both LED off */ +#define ASIC_LED_ACT_ON(pAd) RTMP_IO_WRITE32(pAd, MAC_CSR14, 0x00031e46) +#define ASIC_LED_ACT_OFF(pAd) RTMP_IO_WRITE32(pAd, MAC_CSR14, 0x00001e46) + +/* 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 */ +/* */ +/* HT Capability INFO field in HT Cap IE . */ +typedef struct GNU_PACKED { +#ifdef RT_BIG_ENDIAN + USHORT LSIGTxopProSup:1; + USHORT Forty_Mhz_Intolerant:1; + USHORT PSMP:1; + USHORT CCKmodein40:1; + USHORT AMsduSize:1; + USHORT DelayedBA:1; /*rt2860c not support */ + USHORT RxSTBC:2; + USHORT TxSTBC:1; + USHORT ShortGIfor40:1; /*for40MHz */ + USHORT ShortGIfor20:1; + USHORT GF:1; /*green field */ + USHORT MimoPs:2;/*momi power safe */ + USHORT ChannelWidth:1; + USHORT AdvCoding:1; +#else + USHORT AdvCoding:1; + USHORT ChannelWidth:1; + USHORT MimoPs:2;/*momi power safe */ + USHORT GF:1; /*green field */ + USHORT ShortGIfor20:1; + USHORT ShortGIfor40:1; /*for40MHz */ + USHORT TxSTBC:1; + USHORT RxSTBC:2; + USHORT DelayedBA:1; /*rt2860c not support */ + USHORT AMsduSize:1; /* only support as zero */ + USHORT CCKmodein40:1; + USHORT PSMP:1; + USHORT Forty_Mhz_Intolerant:1; + USHORT LSIGTxopProSup:1; +#endif /* !RT_BIG_ENDIAN */ +} HT_CAP_INFO, *PHT_CAP_INFO; + +/* HT Capability INFO field in HT Cap IE . */ +typedef struct GNU_PACKED { +#ifdef RT_BIG_ENDIAN + UCHAR rsv:3;/*momi power safe */ + UCHAR MpduDensity:3; + UCHAR MaxRAmpduFactor:2; +#else + UCHAR MaxRAmpduFactor:2; + UCHAR MpduDensity:3; + UCHAR rsv:3;/*momi power safe */ +#endif /* !RT_BIG_ENDIAN */ +} HT_CAP_PARM, *PHT_CAP_PARM; + + +typedef struct GNU_PACKED { +#ifdef RT_BIG_ENDIAN + UCHAR TxMCSSetDefined:1; + UCHAR TxRxNotEqual:1; + UCHAR TxMaxStream:2; + UCHAR TxUnqualModulation:1; + UCHAR rsv:3; +#else + UCHAR rsv:3; + UCHAR TxUnqualModulation:1; + UCHAR TxMaxStream:2; + UCHAR TxRxNotEqual:1; + UCHAR 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 { + UCHAR MCSSet[10]; + UCHAR SupRate[2]; /* unit : 1Mbps */ +#ifdef RT_BIG_ENDIAN + UCHAR rsv:3; + UCHAR MpduDensity:1; + UCHAR TxStream:2; + UCHAR TxRxNotEqual:1; + UCHAR TxMCSSetDefined:1; +#else + UCHAR TxMCSSetDefined:1; + UCHAR TxRxNotEqual:1; + UCHAR TxStream:2; + UCHAR MpduDensity:1; + UCHAR rsv:3; +#endif /* RT_BIG_ENDIAN */ + UCHAR rsv3[3]; +} HT_MCS_SET, *PHT_MCS_SET; + +/* HT Capability INFO field in HT Cap IE . */ +typedef struct GNU_PACKED { +#ifdef RT_BIG_ENDIAN + USHORT rsv2:4; + USHORT RDGSupport:1; /*reverse Direction Grant support */ + USHORT PlusHTC:1; /*+HTC control field support */ + USHORT MCSFeedback:2; /*0:no MCS feedback, 2:unsolicited MCS feedback, 3:Full MCS feedback, 1:rsv. */ + USHORT rsv:5;/*momi power safe */ + USHORT TranTime:2; + USHORT Pco:1; +#else + USHORT Pco:1; + USHORT TranTime:2; + USHORT rsv:5;/*momi power safe */ + USHORT MCSFeedback:2; /*0:no MCS feedback, 2:unsolicited MCS feedback, 3:Full MCS feedback, 1:rsv. */ + USHORT PlusHTC:1; /*+HTC control field support */ + USHORT RDGSupport:1; /*reverse Direction Grant support */ + USHORT 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 + ULONG rsv:3; + ULONG ChanEstimation:2; + ULONG CSIRowBFSup:2; + ULONG ComSteerBFAntSup:2; + ULONG NoComSteerBFAntSup:2; + ULONG CSIBFAntSup:2; + ULONG MinGrouping:2; + ULONG ExpComBF:2; + ULONG ExpNoComBF:2; + ULONG ExpCSIFbk:2; + ULONG ExpComSteerCapable:1; + ULONG ExpNoComSteerCapable:1; + ULONG ExpCSICapable:1; + ULONG Calibration:2; + ULONG ImpTxBFCapable:1; + ULONG TxNDPCapable:1; + ULONG RxNDPCapable:1; + ULONG TxSoundCapable:1; + ULONG RxSoundCapable:1; + ULONG TxBFRecCapable:1; +#else + ULONG TxBFRecCapable:1; + ULONG RxSoundCapable:1; + ULONG TxSoundCapable:1; + ULONG RxNDPCapable:1; + ULONG TxNDPCapable:1; + ULONG ImpTxBFCapable:1; + ULONG Calibration:2; + ULONG ExpCSICapable:1; + ULONG ExpNoComSteerCapable:1; + ULONG ExpComSteerCapable:1; + ULONG ExpCSIFbk:2; + ULONG ExpNoComBF:2; + ULONG ExpComBF:2; + ULONG MinGrouping:2; + ULONG CSIBFAntSup:2; + ULONG NoComSteerBFAntSup:2; + ULONG ComSteerBFAntSup:2; + ULONG CSIRowBFSup:2; + ULONG ChanEstimation:2; + ULONG 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 + UCHAR rsv:1; + UCHAR TxSoundPPDU:1; + UCHAR RxASel:1; + UCHAR AntIndFbk:1; + UCHAR ExpCSIFbk:1; + UCHAR AntIndFbkTxASEL:1; + UCHAR ExpCSIFbkTxASEL:1; + UCHAR AntSelect:1; +#else + UCHAR AntSelect:1; + UCHAR ExpCSIFbkTxASEL:1; + UCHAR AntIndFbkTxASEL:1; + UCHAR ExpCSIFbk:1; + UCHAR AntIndFbk:1; + UCHAR RxASel:1; + UCHAR TxSoundPPDU:1; + UCHAR 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; + + +/* 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; + + +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; + +/* 7.3.27 20/40 Bss Coexistence Mgmt capability used in extended capabilities information IE( ID = 127 = IE_EXT_CAPABILITY). */ +/* This is the first octet and was defined in 802.11n D3.03 and 802.11yD9.0 */ +typedef struct GNU_PACKED _EXT_CAP_INFO_ELEMENT{ +#ifdef RT_BIG_ENDIAN +#if defined(DOT11V_WNM_SUPPORT) || defined(DOT11Z_TDLS_SUPPORT) + UINT32 rsv7: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 rsv6:1; + UINT32 DMSSupport:1; + UINT32 rsv5:6; + UINT32 BssTransitionManmt:1; + UINT32 rsv4:1; + UINT32 WNMSleepSupport:1;/*bit 17*/ + UINT32 TFSSupport:1;/*bit 16*/ + UINT32 rsv3:4; + UINT32 FMSSupport:1;/*bit 11*/ + UINT32 rsv2:8; + UINT32 ExtendChannelSwitch:1; + UINT32 rsv:1; + UINT32 BssCoexistMgmtSupport:1; +#else /* defined(DOT11V_WNM_SUPPORT) || defined(DOT11Z_TDLS_SUPPORT) */ + UCHAR rsv2:5; + UCHAR ExtendChannelSwitch:1; + UCHAR rsv:1; + UCHAR BssCoexistMgmtSupport:1; +#endif /* defined(DOT11V_WNM_SUPPORT) || defined(DOT11Z_TDLS_SUPPORT) */ +#else +#if defined(DOT11V_WNM_SUPPORT) || defined(DOT11Z_TDLS_SUPPORT) + UINT32 BssCoexistMgmtSupport:1; + UINT32 rsv:1; + UINT32 ExtendChannelSwitch:1; + UINT32 rsv2:8; + UINT32 FMSSupport:1;/*bit 11*/ + UINT32 rsv3:4; + UINT32 TFSSupport:1;/*bit 16*/ + UINT32 WNMSleepSupport:1;/*bit 17*/ + UINT32 rsv4:1; + UINT32 BssTransitionManmt:1; + UINT32 rsv5:6; + UINT32 DMSSupport:1; + UINT32 rsv6: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 rsv7:1; +#else /* defined(DOT11V_WNM_SUPPORT) || defined(DOT11Z_TDLS_SUPPORT) */ + UCHAR BssCoexistMgmtSupport:1; + UCHAR rsv:1; + UCHAR ExtendChannelSwitch:1; + UCHAR rsv2:5; +#endif /* defined(DOT11V_WNM_SUPPORT) || defined(DOT11Z_TDLS_SUPPORT) */ +#endif /* RT_BIG_ENDIAN */ + +#ifdef DOT11Z_TDLS_SUPPORT +#ifdef RT_BIG_ENDIAN + UINT8 TDLSChSwitchProhibited:1; /* bit39: TDLS Channel Switching Prohibited */ + UINT8 TDLSProhibited:1; /* bit38: TDLS Prohibited */ + UINT8 TDLSSupport:1; /* bit37: TDLS Support */ + UINT8 rsv8:5; +#else + UINT8 rsv8:5; + UINT8 TDLSSupport:1; /* bit37: TDLS Support */ + UINT8 TDLSProhibited:1; /* bit38: TDLS Prohibited */ + UINT8 TDLSChSwitchProhibited:1; /* bit39: TDLS Channel Switching Prohibited */ +#endif // RT_BIG_ENDIAN // +#endif /* DOT11Z_TDLS_SUPPORT */ +}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 */ +typedef struct { + BOOLEAN bHtEnable; /* If we should use ht rate. */ + BOOLEAN bPreNHt; /* If we should use ht rate. */ + /*Substract from HT Capability IE */ + UCHAR MCSSet[16]; +} RT_HT_PHY_INFO, *PRT_HT_PHY_INFO; + +/*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; /* 2 bits */ + 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; /*for40MHz */ + USHORT TxSTBC:1; + 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; + +/* field in Addtional HT Information IE . */ +typedef struct GNU_PACKED { +#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{ +#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{ +#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{ + 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; + +typedef struct GNU_PACKED{ + 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{ +#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 { +#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 { + 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 { +#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 { +#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 { +#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 { +#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_PSMP_ACTION { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + UCHAR Psmp; /* 7.3.1.25 */ +} FRAME_PSMP_ACTION, *PFRAME_PSMP_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 { + 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 { + 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 { +#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 { +#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 { + 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. */ + UCHAR BssType; + USHORT AtimWin; + USHORT BeaconPeriod; + + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRateLen; + 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 WAC_SUPPORT + /* SAMSUNG DMC */ + CHAR Threshold_Offset1; + CHAR Threshold_Offset2; + UCHAR Antenna_Type; + UCHAR Device_Type; + UCHAR Application_List; +#endif /* WAC_SUPPORT */ + + 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; + + /* 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 WAC_QOS_PRIORITY + UCHAR DeviceType; + BOOLEAN bForcePriority; +#endif /* WAC_QOS_PRIORITY */ + +#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 */ + + UCHAR MacAddr[MAC_ADDR_LEN]; + ULONG ClientStatusFlags; +} BSS_ENTRY, *PBSS_ENTRY; + +typedef struct { + UCHAR BssNr; + UCHAR BssOverlapNr; + BSS_ENTRY BssEntry[MAX_LEN_OF_BSS_TABLE]; +} BSS_TABLE, *PBSS_TABLE; + + +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; + UCHAR Signal; + UCHAR Channel; + UCHAR Wcid; + BOOLEAN Occupied; + UCHAR OpMode; + ULONG Priv; +} MLME_QUEUE_ELEM, *PMLME_QUEUE_ELEM; + +typedef struct _MLME_QUEUE { + ULONG Num; + ULONG Head; + ULONG Tail; + NDIS_SPIN_LOCK Lock; + MLME_QUEUE_ELEM Entry[MAX_LEN_OF_MLME_QUEUE]; +} MLME_QUEUE, *PMLME_QUEUE; + +typedef VOID (*STATE_MACHINE_FUNC)(VOID *Adaptor, 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 *Adaptor, 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; + 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; */ + + /* 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; + + 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 +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef WAC_QOS_PRIORITY + BOOLEAN bForcePriority; +#endif /* WAC_QOS_PRIORITY */ +#ifdef P2P_SUPPORT + BOOLEAN bBwFallBack; + UCHAR ConCurrentCentralChannel; +#endif /* P2P_SUPPORT */ +} 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]; +#ifdef MAC_REPEATER_SUPPORT + UCHAR Addr2[MAC_ADDR_LEN]; +#endif /* MAC_REPEATER_SUPPORT */ + 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]; +#ifdef MAC_REPEATER_SUPPORT + UCHAR Addr2[MAC_ADDR_LEN]; +#endif /* MAC_REPEATER_SUPPORT */ + 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]; +} 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 { + 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; + +/* ====================== end of AP mlme.h ============================ */ + + +#endif /* MLME_H__ */ diff --git a/mt7620/src/include/netif_block.h b/mt7620/src/include/netif_block.h new file mode 100644 index 0000000..3714bf0 --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/oid.h b/mt7620/src/include/oid.h new file mode 100644 index 0000000..4b1383e --- /dev/null +++ b/mt7620/src/include/oid.h @@ -0,0 +1,1802 @@ +/* + *************************************************************************** + * 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_BOTH 2 +#define BAND_WIDTH_10 3 /* 802.11j has 10MHz. This definition is for internal usage. doesn't fill in the IE or other field. */ +/* 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 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 MAC_ADDR_LENGTH 6 +/*#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 */ +#define MAX_NUMBER_OF_MAC 32 /* if MAX_MBSSID_NUM is 8, this value can't be larger than 211 */ + +#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 + +#ifdef MESH_SUPPORT +#define MAX_NEIGHBOR_NUM 64 +#define MAX_MESH_LINK_NUM 4 +#define MAX_HOST_NAME_LENGTH 64 +#define MAX_MESH_ID_LENGTH 32 +#define MESH_MAX_FORWARD_ENTRY_NUM 48 +#endif /* MESH_SUPPORT */ + +#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 +/* */ +/* 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 , kathy */ +#define RT_OID_802_11_RSSI_1 0x0109 /*rt2860 only , kathy */ +#define RT_OID_802_11_RSSI_2 0x010A /*rt2860 only , kathy */ +#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 +#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 +#if defined(RT2883) || defined(RT3883) +#define RT_OID_802_11_STREAM_SNR 0x067B +#endif + +#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 */ + +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_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; +#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 APCLI_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/* APCLI_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]; + +#ifdef WAC_SUPPORT + /* SAMSUNG DMC */ + CHAR Threshold_Offset1; + CHAR Threshold_Offset2; + UCHAR Antenna_Type; + UCHAR Device_Type; + UCHAR Application_List; +#endif /* WAC_SUPPORT */ +} 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_11Encryption2Enabled, + Ndis802_11Encryption2KeyAbsent, + Ndis802_11Encryption3Enabled, + Ndis802_11Encryption3KeyAbsent, + Ndis802_11Encryption4Enabled, /* 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(APCLI_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(APCLI_WPA_SUPPLICANT_SUPPORT) */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_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/*APCLI_WPA_SUPPLICANT_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; + + + +#ifdef DBG +/* + 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 MESH_SUPPORT +/* mesh extension OID */ +#define OID_802_11_MESH_SECURITY_INFO 0x0651 +#define OID_802_11_MESH_ID 0x0652 +#define OID_802_11_MESH_AUTO_LINK 0x0653 +#define OID_802_11_MESH_LINK_STATUS 0x0654 +#define OID_802_11_MESH_LIST 0x0655 +#define OID_802_11_MESH_ROUTE_LIST 0x0656 +#define OID_802_11_MESH_ADD_LINK 0x0657 +#define OID_802_11_MESH_DEL_LINK 0x0658 +#define OID_802_11_MESH_MAX_TX_RATE 0x0659 +#define OID_802_11_MESH_CHANNEL 0x065A +#define OID_802_11_MESH_HOSTNAME 0x065B +#define OID_802_11_MESH_ONLY_MODE 0x065C +#define OID_802_11_MESH_DEVICENAME 0x065d +#define OID_802_11_MESH_CHANNEL_BW 0x065e +#define OID_802_11_MESH_CHANNEL_OFFSET 0x065f +#define OID_802_11_MESH_FORWARD 0x0660 + +#define RT_OID_802_11_MESH_SECURITY_INFO (OID_GET_SET_TOGGLE + OID_802_11_MESH_SECURITY_INFO) +#define RT_OID_802_11_MESH_ID (OID_GET_SET_TOGGLE + OID_802_11_MESH_ID) +#define RT_OID_802_11_MESH_AUTO_LINK (OID_GET_SET_TOGGLE + OID_802_11_MESH_AUTO_LINK) +#define RT_OID_802_11_MESH_ADD_LINK (OID_GET_SET_TOGGLE + OID_802_11_MESH_ADD_LINK) +#define RT_OID_802_11_MESH_DEL_LINK (OID_GET_SET_TOGGLE + OID_802_11_MESH_DEL_LINK) +#define RT_OID_802_11_MESH_MAX_TX_RATE (OID_GET_SET_TOGGLE + OID_802_11_MESH_MAX_TX_RATE) +#define RT_OID_802_11_MESH_CHANNEL (OID_GET_SET_TOGGLE + OID_802_11_MESH_CHANNEL) +#define RT_OID_802_11_MESH_HOSTNAME (OID_GET_SET_TOGGLE + OID_802_11_MESH_HOSTNAME) +#define RT_OID_802_11_MESH_ONLY_MODE (OID_GET_SET_TOGGLE + OID_802_11_MESH_ONLY_MODE) +#define RT_OID_802_11_MESH_DEVICENAME (OID_GET_SET_TOGGLE + OID_802_11_MESH_DEVICENAME) +#define RT_OID_802_11_MESH_FORWARD (OID_GET_SET_TOGGLE + 0x0660) +#endif /* MESH_SUPPORT */ + +#ifdef SNMP_SUPPORT +/*SNMP ieee 802dot11, kathy , 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 + +#endif /* SNMP_SUPPORT */ + +/* //dot11Phy(4) */ +#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 CON_WPS +#define RT_OID_WSC_SET_CON_WPS_STOP 0x0764 +#endif /* CON_WPS */ + +#ifdef NINTENDO_AP +/*#define RT_OID_NINTENDO 0x0D010770 */ +#define RT_OID_802_11_NINTENDO_GET_TABLE 0x0771 /*((RT_OID_NINTENDO + 0x01) & 0xffff) */ +#define RT_OID_802_11_NINTENDO_SET_TABLE 0x0772 /*((RT_OID_NINTENDO + 0x02) & 0xffff) */ +#define RT_OID_802_11_NINTENDO_CAPABLE 0x0773 /*((RT_OID_NINTENDO + 0x03) & 0xffff) */ +#endif /* NINTENDO_AP */ + + +#ifdef EASY_CONFIG_SETUP +#define OID_PIN_OF_ENROLLEE 0x0800 +#endif /* EASY_CONFIG_SETUP */ + +/* 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:2; /* Use definition MODE_xxx. */ + USHORT iTxBF:1; + USHORT rsv:1; + USHORT eTxBF:1; + USHORT STBC:2; /* SPACE */ + USHORT ShortGI:1; + USHORT BW:1; /* channel bandwidth 20MHz or 40 MHz */ + USHORT MCS:7; /* MCS */ + } field; +#else + struct { + USHORT MCS:7; /* MCS */ + USHORT BW:1; /* channel bandwidth 20MHz or 40 MHz */ + USHORT ShortGI:1; + USHORT STBC:2; /* SPACE */ + USHORT eTxBF:1; + USHORT rsv:1; + USHORT iTxBF:1; + USHORT MODE:2; /* Use definition MODE_xxx. */ + } 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, + PHY_11A, + PHY_11ABG_MIXED, + PHY_11G, +#ifdef DOT11_N_SUPPORT + PHY_11ABGN_MIXED, /* both band 5 */ + PHY_11N_2_4G, /* 11n-only with 2.4G band 6 */ + PHY_11GN_MIXED, /* 2.4G band 7 */ + PHY_11AN_MIXED, /* 5G band 8 */ + PHY_11BGN_MIXED, /* if check 802.11b. 9 */ + PHY_11AGN_MIXED, /* if check 802.11b. 10 */ + PHY_11N_5G, /* 11n-only with 5G band 11 */ +#endif /* DOT11_N_SUPPORT */ +} RT_802_11_PHY_MODE; + +#ifdef 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_LENGTH]; + 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 { + struct { + USHORT MCS:7; /* MCS */ + USHORT BW:1; /*channel bandwidth 20MHz or 40 MHz */ + USHORT ShortGI:1; + USHORT STBC:2; /*SPACE */ + USHORT rsv:3; + USHORT MODE:2; /* Use definition MODE_xxx. */ + } field; + USHORT word; +} MACHTTRANSMIT_SETTING, *PMACHTTRANSMIT_SETTING; + +typedef struct _RT_802_11_MAC_ENTRY { + UCHAR ApIdx; + UCHAR Addr[MAC_ADDR_LENGTH]; + 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; +#ifdef DPA_S //yiwei + UCHAR DeviceName[OID_P2P_DEVICE_NAME_LEN]; + UINT32 DeviceNameLen; +#endif /* DPA_S */ +//sync with other driver + UINT32 LastRxRate; + SHORT StreamSnr[3]; /* BF SNR from RXWI. Units=0.25 dB. 22 dB offset removed */ + SHORT SoundingRespSnr[3]; /* SNR from Sounding Response. Units=0.25 dB. 22 dB offset removed */ +/* SHORT TxPER; */ /* TX PER over the last second. Percent */ +/* SHORT reserved;*/ +} 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_LENGTH]; + 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 */ + UCHAR 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 NINTENDO_AP +#define NINTENDO_MAX_ENTRY 16 +#define NINTENDO_SSID_NAME_LN 8 +#define NINTENDO_SSID_NAME "NWCUSBAP" +#define NINTENDO_PROBE_REQ_FLAG_MASK 0x03 +#define NINTENDO_PROBE_REQ_ON 0x01 +#define NINTENDO_PROBE_REQ_SIGNAL 0x02 +#define NINTENDO_PROBE_RSP_ON 0x01 +#define NINTENDO_SSID_NICKNAME_LN 20 + +#define NINTENDO_WEPKEY_LN 13 + +typedef struct _NINTENDO_SSID { + UCHAR NINTENDOFixChar[NINTENDO_SSID_NAME_LN]; + UCHAR zero1; + UCHAR registe; + UCHAR ID; + UCHAR zero2; + UCHAR NICKname[NINTENDO_SSID_NICKNAME_LN]; +} RT_NINTENDO_SSID, *PRT_NINTENDO_SSID; + +typedef struct _NINTENDO_ENTRY { + UCHAR NICKname[NINTENDO_SSID_NICKNAME_LN]; + UCHAR DS_Addr[ETH_LENGTH_OF_ADDRESS]; + UCHAR registe; + UCHAR UserSpaceAck; +} RT_NINTENDO_ENTRY, *PRT_NINTENDO_ENTRY; + +/*RTPRIV_IOCTL_NINTENDO_GET_TABLE */ +/*RTPRIV_IOCTL_NINTENDO_SET_TABLE */ +typedef struct _NINTENDO_TABLE { + UINT number; + RT_NINTENDO_ENTRY entry[NINTENDO_MAX_ENTRY]; +} RT_NINTENDO_TABLE, *PRT_NINTENDO_TABLE; + +/*RTPRIV_IOCTL_NINTENDO_SEED_WEPKEY */ +typedef struct _NINTENDO_SEED_WEPKEY { + UCHAR seed[NINTENDO_SSID_NICKNAME_LN]; + UCHAR wepkey[16]; /*use 13 for 104 bits wep key */ +} RT_NINTENDO_SEED_WEPKEY, *PRT_NINTENDO_SEED_WEPKEY; +#endif /* NINTENDO_AP */ + +#ifdef LLTD_SUPPORT +typedef struct _RT_LLTD_ASSOICATION_ENTRY { + UCHAR Addr[ETH_LENGTH_OF_ADDRESS]; + 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[MAX_NUMBER_OF_MAC]; +} RT_LLTD_ASSOICATION_TABLE, *PRT_LLTD_ASSOICATION_TABLE; +#endif /* LLTD_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT +/*rt2860, kathy 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 */ + + +#ifdef MESH_SUPPORT +typedef enum _MESH_KEY_SELECTION { + MESH_KEY_NONE, + MESH_KEY_PMKMA_PEER, + MESH_KEY_PMKMA_LOCAL +} MESH_KEY_SELECTION, *PMESH_KEY_SELECTION; + +typedef enum _MESH_SECURITY_TYPE { + ENCRYPT_OPEN_NONE, + ENCRYPT_OPEN_WEP, + ENCRYPT_WPANONE_TKIP, + ENCRYPT_WPANONE_AES +} MESH_SECURITY_TYPE, *PMESH_SECURITY_TYPE; + +typedef struct GNU_PACKED _MESH_SECURITY_INFO { + ULONG Length; /* Length of this structure */ + UCHAR EncrypType; /* indicate Encryption Type */ + UCHAR KeyIndex; /* Default Key Index */ + UCHAR KeyLength; /* length of key in bytes */ + UCHAR KeyMaterial[64]; /* the key Material */ +} MESH_SECURITY_INFO, *PMESH_SECURITY_INFO; + +typedef struct _MESH_LINK_ENTRY_INFO { + UCHAR Status; + UCHAR LinkType; + CHAR Rssi; + HTTRANSMIT_SETTING CurTxRate; + UCHAR PeerMacAddr[MAC_ADDR_LENGTH]; +} MESH_LINK_ENTRY_INFO, *PMESH_LINK_ENTRY_INFO; + +typedef struct _MESH_LINK_INFO { + MESH_LINK_ENTRY_INFO Entry[MAX_MESH_LINK_NUM]; +} MESH_LINK_INFO, *PMESH_LINK_INFO; + +typedef struct _MESH_NEIGHBOR_ENTRY_INFO { + char Rssi; + UCHAR HostName[MAX_HOST_NAME_LENGTH + 1]; + UCHAR MacAddr[MAC_ADDR_LENGTH]; + UCHAR MeshId[MAX_MESH_ID_LENGTH + 1]; + UCHAR Channel; + UCHAR Status; /*0:idle, 1:connected. */ + UCHAR MeshEncrypType; +} MESH_NEIGHBOR_ENTRY_INFO, *PMESH_NEIGHBOR_ENTRY_INFO; + +typedef struct _MESH_NEIGHBOR_INFO { + MESH_NEIGHBOR_ENTRY_INFO Entry[MAX_NEIGHBOR_NUM]; + UCHAR num; +} MESH_NEIGHBOR_INFO, *PMESH_NEIGHBOR_INFO; + +typedef struct _RT_MESH_ROUTE_ENTRY { + UCHAR MeshDA[MAC_ADDR_LENGTH]; + ULONG Dsn; + UCHAR NextHop[MAC_ADDR_LENGTH]; + ULONG Metric; +} RT_MESH_ROUTE_ENTRY, *PRT_MESH_ROUTE_ENTRY; + +typedef struct _RT_MESH_ROUTE_TABLE { + UCHAR Num; + RT_MESH_ROUTE_ENTRY Entry[MESH_MAX_FORWARD_ENTRY_NUM]; +} RT_MESH_ROUTE_TABLE, *PRT_MESH_ROUTE_TABLE; +#endif /* MESH_SUPPORT */ + +/*#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]; /* mandatory, Maximum 64 byte */ + USHORT KeyLength; + UCHAR MacAddr[MAC_ADDR_LENGTH]; /* 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_LENGTH]; + USHORT state; +} WAPI_PORT_SECURE_STRUCT, *PWAPI_PORT_SECURE_STRUCT; + +typedef struct _WAPI_UCAST_KEY_STRUCT { + UCHAR Addr[MAC_ADDR_LENGTH]; + 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 APCLI_SUPPORT +#ifdef APCLI_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 /* APCLI_WPA_SUPPLICANT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + + +#ifdef P2P_SUPPORT +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT +#define RT_P2P_DEVICE_FIND 0x010A +#define RT_P2P_RECV_PROV_REQ 0x010B +#define RT_P2P_RECV_PROV_RSP 0x010C +#define RT_P2P_RECV_INVITE_REQ 0x010D +#define RT_P2P_RECV_INVITE_RSP 0x010E +#define RT_P2P_RECV_GO_NEGO_REQ 0x010F +#define RT_P2P_RECV_GO_NEGO_RSP 0x0110 +#define RT_P2P_GO_NEG_COMPLETED 0x0111 +#define RT_P2P_GO_NEG_FAIL 0x0112 +#define RT_P2P_WPS_COMPLETED 0x0113 +#define RT_P2P_CONNECTED 0x0114 +#define RT_P2P_DISCONNECTED 0x0115 +#define RT_P2P_CONNECT_FAIL 0x0116 +#define RT_P2P_LEGACY_CONNECTED 0x0117 +#define RT_P2P_LEGACY_DISCONNECTED 0x0118 +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ + +#define OID_802_11_P2P_MODE 0x0801 +#define OID_802_11_P2P_DEVICE_NAME 0x0802 +#define OID_802_11_P2P_LISTEN_CHANNEL 0x0803 +#define OID_802_11_P2P_OPERATION_CHANNEL 0x0804 +#define OID_802_11_P2P_DEV_ADDR 0x0805 +#define OID_802_11_P2P_SCAN_LIST 0x0806 +#define OID_802_11_P2P_GO_INT 0x080c + +#define OID_802_11_P2P_CTRL_STATUS 0x0807 +#define OID_802_11_P2P_DISC_STATUS 0x0808 +#define OID_802_11_P2P_GOFORM_STATUS 0x0809 +#define OID_P2P_WSC_PIN_CODE 0x080a +#define OID_802_11_P2P_CLEAN_TABLE 0x080b +#define OID_802_11_P2P_SCAN 0x080d +#define OID_802_11_P2P_WscMode 0x080e +#define OID_802_11_P2P_WscConf 0x080f +/* 0x0810 ~ 0x0814 Reserved for iNIC USERDEF_GPIO_SUPPORT */ +/* 0x0820 ~ 0x0822 Reserved for iNIC USERDEF_GPIO_SUPPORT */ +#define OID_802_11_P2P_Link 0x0830 +#define OID_802_11_P2P_Connected_MAC 0x0831 +#define OID_P2P_OFFSET 0x0000 +#define OID_802_11_P2P_RESET (0x0832 + OID_P2P_OFFSET) +#define OID_802_11_P2P_SIGMA_ENABLE (0x0833 + OID_P2P_OFFSET) +#define OID_802_11_P2P_SSID (0x0834 + OID_P2P_OFFSET) +#define OID_802_11_P2P_CONNECT_ADDR (0x0835 + OID_P2P_OFFSET) +#define OID_802_11_P2P_CONNECT_STATUS (0x0836 + OID_P2P_OFFSET) +#define OID_802_11_P2P_PEER_GROUP_ID (0x0837 + OID_P2P_OFFSET) +#define OID_802_11_P2P_ENTER_PIN (0x0838 + OID_P2P_OFFSET) +#define OID_802_11_P2P_PROVISION (0x0839 + OID_P2P_OFFSET) +#define OID_802_11_P2P_PASSPHRASE (0x0840 + OID_P2P_OFFSET) +#define OID_802_11_P2P_ASSOCIATE_TAB (0x0841 + OID_P2P_OFFSET) +#define OID_802_11_P2P_PROVISION_MAC (0x0842 + OID_P2P_OFFSET) +#define OID_802_11_P2P_LINK_DOWN (0x0843 + OID_P2P_OFFSET) +#define OID_802_11_P2P_PRI_DEVICE_TYPE (0x0844 + OID_P2P_OFFSET) + +#define RT_OID_802_11_P2P_MODE (OID_GET_SET_TOGGLE + OID_802_11_P2P_MODE) +#define RT_OID_802_11_P2P_DEVICE_NAME (OID_GET_SET_TOGGLE + OID_802_11_P2P_DEVICE_NAME) +#define RT_OID_802_11_P2P_LISTEN_CHANNEL (OID_GET_SET_TOGGLE + OID_802_11_P2P_LISTEN_CHANNEL) +#define RT_OID_802_11_P2P_OPERATION_CHANNEL (OID_GET_SET_TOGGLE + OID_802_11_P2P_OPERATION_CHANNEL) +#define RT_OID_802_11_P2P_DEV_ADDR (OID_GET_SET_TOGGLE + OID_802_11_P2P_DEV_ADDR) +#define RT_OID_802_11_P2P_SCAN_LIST (OID_GET_SET_TOGGLE + OID_802_11_P2P_SCAN_LIST) +#define RT_OID_802_11_P2P_CTRL_STATUS (OID_GET_SET_TOGGLE + OID_802_11_P2P_CTRL_STATUS) +#define RT_OID_802_11_P2P_DISC_STATUS (OID_GET_SET_TOGGLE + OID_802_11_P2P_DISC_STATUS) +#define RT_OID_802_11_P2P_GOFORM_STATUS (OID_GET_SET_TOGGLE + OID_802_11_P2P_GOFORM_STATUS) +#define RT_OID_P2P_WSC_PIN_CODE (OID_GET_SET_TOGGLE + OID_P2P_WSC_PIN_CODE) +#define RT_OID_802_11_P2P_CLEAN_TABLE (OID_GET_SET_TOGGLE + OID_802_11_P2P_CLEAN_TABLE) +#define RT_OID_802_11_P2P_GO_INT (OID_GET_SET_TOGGLE + OID_802_11_P2P_GO_INT) +#define RT_OID_802_11_P2P_SCAN (OID_GET_SET_TOGGLE + OID_802_11_P2P_SCAN) +#define RT_OID_802_11_P2P_WscMode (OID_GET_SET_TOGGLE + OID_802_11_P2P_WscMode) +#define RT_OID_802_11_P2P_WscConf (OID_GET_SET_TOGGLE + OID_802_11_P2P_WscConf) +#define RT_OID_802_11_P2P_Link (OID_GET_SET_TOGGLE + OID_802_11_P2P_Link) +#define RT_OID_802_11_P2P_Connected_MAC (OID_GET_SET_TOGGLE + OID_802_11_P2P_Connected_MAC) +#define RT_OID_802_11_P2P_RESET (OID_GET_SET_TOGGLE + OID_802_11_P2P_RESET) + + +#define IWEVP2PSHOWPIN 0x8C05 +#define IWEVP2PKEYPIN 0x8C06 + +#ifdef DPA_S +/* + P2P Status related with all events or status +*/ +typedef enum { + P2P_NOTIF_NONE = 0, + /* ---------- Discovery --------------------------------------------- */ + /* Started the initial 802.11 scan phase */ + P2P_NOTIF_DISCOVER_START_80211_SCAN = 0x1001, + + /* Started the subsequent search-listen phase */ + P2P_NOTIF_DISCOVER_START_SEARCH_LISTEN, + + /* Sent on each iteration of the search-listen phase. */ + P2P_NOTIF_DISCOVER_SEARCH_LISTEN_ITERATION, + + /* Have results from the initial 802.11 scan */ + P2P_NOTIF_DISCOVER_FOUND_P2P_GROUPS, + + /* Have results from subsequent search-listen phase */ + P2P_NOTIF_DISCOVER_FOUND_PEERS, + P2P_NOTIF_DISCOVER_CANCEL, + P2P_NOTIF_DISCOVER_FAIL, + P2P_NOTIF_DISCOVER_COMPLETE, + + /* Discovery suspended due to start of GO Negotiation */ + P2P_NOTIF_DISCOVER_SUSPENDED, + + /** Discovery resumed after GO Negotiation failure */ + P2P_NOTIF_DISCOVER_RESUMED, + + /** Started discovery in listen-only state */ + P2P_NOTIF_DISCOVER_START_LISTEN_ONLY, + + /* ---------- Provision Discovery ----------------------------------- */ + P2P_NOTIF_PROVISION_DISCOVERY_REQUEST = 0x2101, + P2P_NOTIF_PROVISION_DISCOVERY_RESPONSE, + P2P_NOTIF_PROVISION_DISCOVERY_TIMEOUT, + + /* ---------- Group Owner Negotiation ------------------------------- */ + /** Sent GON request pNotificationData: NULL */ + P2P_NOTIF_GROUP_OWNER_NEGOTIATION_START = 0x2201, + + /** pNotificationData: PP2P_DISCOVER_ENTRY */ + P2P_NOTIF_GROUP_OWNER_NEGOTIATION_AP_ACK, + + /** pNotificationData: PP2P_DISCOVER_ENTRY */ + P2P_NOTIF_GROUP_OWNER_NEGOTIATION_STA_ACK, + + /** pNotificationData: NULL */ + P2P_NOTIF_GROUP_OWNER_NEGOTIATION_COMPLETE, + + /** pNotificationData: NULL */ + P2P_NOTIF_GROUP_OWNER_NEGOTIATION_FAIL, + + /** pNotificationData: PP2P_DISCOVER_ENTRY */ + /* Deprecated, use P2P_NOTIF_GROUP_OWNER_NEGOTIATION_NO_PROV_INFO. */ + P2P_NOTIF_GROUP_OWNER_NEGOTIATION_NO_PIN, + + /** Peer has no provisioning info. pNotificationData: PP2P_DISCOVER_ENTRY */ + P2P_NOTIF_GROUP_OWNER_NEGOTIATION_INFO_UNAVAIL, + + /** pNotificationData: NULL */ + P2P_NOTIF_GROUP_OWNER_NEGOTIATION_FAIL_INTENT, + + /** We have no provisioning info. pNotificationData: PP2P_DISCOVER_ENTRY */ + P2P_NOTIF_GROUP_OWNER_NEGOTIATION_NO_PROV_INFO, + + /** We are already in an existing P2P connection. pNotificationData: NULL */ + P2P_NOTIF_GROUP_OWNER_NEGOTIATION_ALREADY_CONNECTED, + + /** Received GON request pNotificationData: PP2P_DISCOVER_ENTRY */ + P2P_NOTIF_GROUP_OWNER_NEGOTIATION_REQUEST_RECEIVED, + + /* ---------- P2P Invite -------------------------------------------- */ + /** pNotificationData: PP2P_INVITE_PARAM */ + P2P_NOTIF_P2P_INVITE_REQ = 0x2301, + P2P_NOTIF_P2P_INVITE_RSP, + + /* ---------- P2P Presence------------------------------------------- */ + P2P_NOTIF_P2P_PRESENCE_REQ = 0x2401, + P2P_NOTIF_P2P_PRESENCE_RSP, + + /* ---------- P2P Device Discoverability ---------------------------- */ + P2P_NOTIF_DEV_DISCOVERABILITY_REQ = 0x2501, + P2P_NOTIF_GO_DISCOVERABILITY_REQ, + P2P_NOTIF_DEV_DISCOVERABILITY_RSP, + + /* ---------- Link Creation ------------------------------------------ */ + P2P_NOTIF_CREATE_LINK_START = 0x3001, + P2P_NOTIF_CREATE_LINK_CANCEL, + P2P_NOTIF_CREATE_LINK_TIMEOUT, + P2P_NOTIF_CREATE_LINK_AUTH_FAIL, + P2P_NOTIF_CREATE_LINK_FAIL, + + /* ---------- SoftAP ------------------------------------------ */ + /** SoftAP-creation process starts */ + P2P_NOTIF_SOFTAP_START, + + /** SoftAP is ready to provide the service */ + P2P_NOTIF_SOFTAP_READY, + + /** SoftAP has stopped */ + P2P_NOTIF_SOFTAP_STOP, + + /** SoftAP-creation failed */ + P2P_NOTIF_SOFTAP_FAIL, + P2P_NOTIF_DHCP_START, + P2P_NOTIF_DHCP_STOP, + + /** Successful P2P connection - pNotificationData: P2P_PERSISTENT */ + P2P_NOTIF_CREATE_LINK_COMPLETE, + P2P_NOTIF_SOFTAP_STA_ASSOC, + P2P_NOTIF_SOFTAP_STA_DISASSOC, + + /** P2P GC loss of link */ + P2P_NOTIF_LINK_LOSS, +/** add by woody */ + P2P_NOTIF_CONNECT_TIMEOUT, + + /* ---------- WPS status -------------------------------------------- */ + P2P_NOTIF_WPS_START = 0x4001, + P2P_NOTIF_WPS_STATUS_SCANNING, + P2P_NOTIF_WPS_STATUS_SCANNING_OVER, + P2P_NOTIF_WPS_STATUS_ASSOCIATING, + P2P_NOTIF_WPS_STATUS_ASSOCIATED, + P2P_NOTIF_WPS_STATUS_WPS_MSG_EXCHANGE, + P2P_NOTIF_WPS_STATUS_DISCONNECTING, + P2P_NOTIF_WPS_COMPLETE, + P2P_NOTIF_WPS_PROTOCOL_FAIL, + P2P_NOTIF_WPS_WRONG_PIN, + P2P_NOTIF_WPS_TIMEOUT, + P2P_NOTIF_WPS_SESSION_OVERLAP, + P2P_NOTIF_WPS_FAIL, + + /* generic errors */ + /* ---------- Service Discovery-------------------------------------- */ + /** Service Response received - pNotificationData: PP2P_SVC_LIST */ + P2P_NOTIF_SVC_RESP_RECEIVED = 0x5001, + + /** Service Request received. */ + P2P_NOTIF_SVC_REQ_RECEIVED, + + /** Failed to decode service frame */ + P2P_NOTIF_SVC_FAIL_TO_DECODE, + + /** Service Comeback Response received. */ + P2P_NOTIF_SVC_COMEBACK_RESP_RECEIVED, + + /** Service Comeback Request received. */ + P2P_NOTIF_SVC_COMEBACK_REQ_RECEIVED, + + /** Session to request service completed */ + P2P_NOTIF_SVC_REQ_COMPLETED, + + /** Session to respond service completed */ + P2P_NOTIF_SVC_RSP_COMPLETED, + + /* ---------- Miscellaneous ----------------------------------------- */ + /* Primary Interface disconnected */ + P2P_NOTIF_PRIMARY_IF_DISCONNECTED = 0x6001 + +}P2PNotificationStatus; +#endif /* DPA_S */ +#endif /* P2P_SUPPORT */ + +#ifdef WAC_QOS_PRIORITY +#define WAC_DEVICE_TYPE_TV 0x0 +#define WAC_DEVICE_TYPE_PHONE 0x1 +#define WAC_DEVICE_TYPE_PC 0x2 +#define WAC_DEVICE_TYPE_CAMERA 0x3 +#define WAC_DEVICE_TYPE_CAMCORDER 0x4 +#define WAC_DEVICE_TYPE_PRINTER 0x5 +#define WAC_DEVICE_TYPE_TC 0x6 +#define WAC_DEVICE_TYPE_AP 0x7 +#define WAC_DEVICE_TYPE_BD 0x8 +#endif /* WAC_QOS_PRIORITY */ + + +#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 // + +#endif /* _OID_H_ */ diff --git a/mt7620/src/include/os/rt_drv.h b/mt7620/src/include/os/rt_drv.h new file mode 100644 index 0000000..993e0de --- /dev/null +++ b/mt7620/src/include/os/rt_drv.h @@ -0,0 +1,1130 @@ +/**************************************************************************** + * 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_NIC_DEVICE_NAME "RT2860AP" +#define AP_DRIVER_VERSION "2.7.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 "2.6.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 +#ifdef RTMP_RBUS_SUPPORT +#define SINGLE_SKU_TABLE_FILE_NAME "/etc_ro/Wireless/RT2860AP/SingleSKU.dat" +#endif /* RTMP_RBUS_SUPPORT */ +#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 ETH_LENGTH_OF_ADDRESS 6 + +#define NDIS_STATUS_SUCCESS 0x00 +#define NDIS_STATUS_FAILURE 0x01 +#define NDIS_STATUS_INVALID_DATA 0x02 +#define NDIS_STATUS_RESOURCES 0x03 + +#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 + ***********************************************************************************/ +#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 +#ifdef CONFIG_STA_SUPPORT +#define MIN_NET_DEVICE_FOR_DLS 0x40 +#define MIN_NET_DEVICE_FOR_TDLS 0x50 +#ifdef MESH_SUPPORT +#undef MIN_NET_DEVICE_FOR_DLS +#undef MIN_NET_DEVICE_FOR_TDLS +#define MIN_NET_DEVICE_FOR_DLS (MIN_NET_DEVICE_FOR_MESH + 0x10) +#define MIN_NET_DEVICE_FOR_TDLS (MIN_NET_DEVICE_FOR_MESH + 0x20) +#endif /* MESH_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ +#ifdef P2P_SUPPORT +#define MIN_NET_DEVICE_FOR_P2P_CLI (MIN_NET_DEVICE_FOR_TDLS + 0x10) +#define MIN_NET_DEVICE_FOR_P2P_GO (MIN_NET_DEVICE_FOR_TDLS + 0x20) +#endif /* P2P_SUPPORT */ + +#define NET_DEVICE_REAL_IDX_MASK 0x0f /* for each operation mode, we maximum support 15 entities. */ + + +#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 */ + + +/*********************************************************************************** + * 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; +/* ra_dma_addr_t pAd_pa; */ +#endif /* RTMP_MAC_PCI */ + + +#ifdef WORKQUEUE_BH + UINT32 pAd_va; + + RTMP_NET_TASK_STRUCT rx_done_work; + RTMP_NET_TASK_STRUCT mgmt_dma_done_work; + RTMP_NET_TASK_STRUCT ac0_dma_done_work; + RTMP_NET_TASK_STRUCT ac1_dma_done_work; + RTMP_NET_TASK_STRUCT ac2_dma_done_work; + RTMP_NET_TASK_STRUCT ac3_dma_done_work; + RTMP_NET_TASK_STRUCT hcca_dma_done_work; + + RTMP_NET_TASK_STRUCT tbtt_work; + +#else + RTMP_NET_TASK_STRUCT rx_done_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; +#endif /* WORKQUEUE_BH */ + +#ifdef RTMP_MAC_PCI +#ifdef WORKQUEUE_BH + RTMP_NET_TASK_STRUCT fifo_statistic_full_work; +#else + RTMP_NET_TASK_STRUCT fifo_statistic_full_task; +#endif /* WORKQUEUE_BH */ +#endif /* RTMP_MAC_PCI */ + +#ifdef UAPSD_SUPPORT +#ifdef WORKQUEUE_BH + RTMP_NET_TASK_STRUCT uapsd_eosp_sent_work; +#else + RTMP_NET_TASK_STRUCT uapsd_eosp_sent_task; +#endif /* WORKQUEUE_BH */ +#endif /* UAPSD_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef DFS_SUPPORT +#ifdef DFS_SOFTWARE_SUPPORT +#ifdef WORKQUEUE_BH + RTMP_NET_TASK_STRUCT pulse_radar_detect_work; + RTMP_NET_TASK_STRUCT width_radar_detect_work; +#else + RTMP_NET_TASK_STRUCT pulse_radar_detect_task; + RTMP_NET_TASK_STRUCT width_radar_detect_task; +#endif /* WORKQUEUE_BH */ +#endif /* DFS_SOFTWARE_SUPPORT */ +#endif /* DFS_SUPPORT */ + +#ifdef CARRIER_DETECTION_SUPPORT +#ifdef WORKQUEUE_BH + RTMP_NET_TASK_STRUCT carrier_sense_work; +#else + RTMP_NET_TASK_STRUCT carrier_sense_task; +#endif /* WORKQUEUE_BH */ +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef DFS_SUPPORT +#ifdef WORKQUEUE_BH + RTMP_NET_TASK_STRUCT dfs_work; +#else + RTMP_NET_TASK_STRUCT dfs_task; +#endif /* WORKQUEUE_BH */ +#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)>>8) & 0xffffff;\ + 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) +#define DBGPRINT_RAW(Level, Fmt) +#define DBGPRINT_S(Status, Fmt) +#define DBGPRINT_ERR(Fmt) +#endif + +#undef ASSERT +#ifdef DBG +#define ASSERT(x) \ +{ \ + if (!(x)) \ + { \ + printk(__FILE__ ":%d assert " #x "failed\n", __LINE__); \ + } \ +} +#else +#define ASSERT(x) +#endif /* DBG */ + +void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen); + + +/********************************************************************************************************* + 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(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. + **********************************************************************************/ +#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) \ + { \ + writel((_V), (void *)((_A)->CSRBaseAddress + (_R))); \ + } \ +} + +#define RTMP_IO_FORCE_WRITE32(_A, _R, _V) \ +{ \ + 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) +#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)) + +/* User Priority */ +#define RTMP_SET_PACKET_UP(_p, _prio) (PACKET_CB(_p, 0) = _prio) +#define RTMP_GET_PACKET_UP(_p) (PACKET_CB(_p, 0)) + +/* Fragment # */ +#define RTMP_SET_PACKET_FRAGMENTS(_p, _num) (PACKET_CB(_p, 1) = _num) +#define RTMP_GET_PACKET_FRAGMENTS(_p) (PACKET_CB(_p, 1)) + +/* 0x0 ~0x7f: TX to AP's own BSS which has the specified AID. if AID>127, set bit 7 in RTMP_SET_PACKET_EMACTAB too. */ +/*(this value also as MAC(on-chip WCID) table index) */ +/* 0x80~0xff: TX to a WDS link. b0~6: WDS index */ +#define RTMP_SET_PACKET_WCID(_p, _wdsidx) (PACKET_CB(_p, 2) = _wdsidx) +#define RTMP_GET_PACKET_WCID(_p) (PACKET_CB(_p, 2)) + +/* 0xff: PKTSRC_NDIS, others: local TX buffer index. This value affects how to a packet */ +#define RTMP_SET_PACKET_SOURCE(_p, _pktsrc) (PACKET_CB(_p, 3) = _pktsrc) +#define RTMP_GET_PACKET_SOURCE(_p) (PACKET_CB(_p, 3)) + +/* RTS/CTS-to-self protection method */ +#define RTMP_SET_PACKET_RTS(_p, _num) (PACKET_CB(_p, 4) = _num) +#define RTMP_GET_PACKET_RTS(_p) (PACKET_CB(_p, 4)) +/* see RTMP_S(G)ET_PACKET_EMACTAB */ + +/* TX rate index */ +#define RTMP_SET_PACKET_TXRATE(_p, _rate) (PACKET_CB(_p, 5) = _rate) +#define RTMP_GET_PACKET_TXRATE(_p) (PACKET_CB(_p, 5)) + +/* From which Interface */ +#define RTMP_SET_PACKET_IF(_p, _ifdx) (PACKET_CB(_p, 6) = _ifdx) +#define RTMP_GET_PACKET_IF(_p) (PACKET_CB(_p, 6)) +#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)) + +#define RTMP_SET_PACKET_MOREDATA(_p, _morebit) (PACKET_CB(_p, 7) = _morebit) +#define RTMP_GET_PACKET_MOREDATA(_p) (PACKET_CB(_p, 7)) + + + +#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, 9) = ((_flg_uapsd<<7) | _que_id)) + +#define RTMP_SET_PACKET_QOS_NULL(_p) (PACKET_CB(_p, 9) = 0xff) +#define RTMP_GET_PACKET_QOS_NULL(_p) (PACKET_CB(_p, 9)) +#define RTMP_SET_PACKET_NON_QOS_NULL(_p) (PACKET_CB(_p, 9) = 0x00) +#define RTMP_GET_PACKET_UAPSD_Flag(_p) ((PACKET_CB(_p, 9) & 0x80) >> 7) +#define RTMP_GET_PACKET_UAPSD_QUE_ID(_p) (PACKET_CB(_p, 9) & 0x7f) + +#define RTMP_SET_PACKET_EOSP(_p, _flg) (PACKET_CB(_p, 10) = _flg) +#define RTMP_GET_PACKET_EOSP(_p) (PACKET_CB(_p, 10)) +#endif /* UAPSD_SUPPORT */ + + +/* */ +/* Sepcific Pakcet Type definition */ +/* */ +#define RTMP_PACKET_SPECIFIC_CB_OFFSET 11 + +#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 + +/*Specific */ +#define RTMP_SET_PACKET_SPECIFIC(_p, _flg) (PACKET_CB(_p, 11) = _flg) + +/*DHCP */ +#define RTMP_SET_PACKET_DHCP(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 11) |= (RTMP_PACKET_SPECIFIC_DHCP); \ + else \ + PACKET_CB(_p, 11) &= (~RTMP_PACKET_SPECIFIC_DHCP); \ + }while(0) +#define RTMP_GET_PACKET_DHCP(_p) (PACKET_CB(_p, 11) & RTMP_PACKET_SPECIFIC_DHCP) + +/*EAPOL */ +#define RTMP_SET_PACKET_EAPOL(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 11) |= (RTMP_PACKET_SPECIFIC_EAPOL); \ + else \ + PACKET_CB(_p, 11) &= (~RTMP_PACKET_SPECIFIC_EAPOL); \ + }while(0) +#define RTMP_GET_PACKET_EAPOL(_p) (PACKET_CB(_p, 11) & RTMP_PACKET_SPECIFIC_EAPOL) + +/*WAI */ +#define RTMP_SET_PACKET_WAI(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 11) |= (RTMP_PACKET_SPECIFIC_WAI); \ + else \ + PACKET_CB(_p, 11) &= (~RTMP_PACKET_SPECIFIC_WAI); \ + }while(0) +#define RTMP_GET_PACKET_WAI(_p) (PACKET_CB(_p, 11) & RTMP_PACKET_SPECIFIC_WAI) + +#define RTMP_GET_PACKET_LOWRATE(_p) (PACKET_CB(_p, 11) & (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, 11) |= (RTMP_PACKET_SPECIFIC_VLAN); \ + else \ + PACKET_CB(_p, 11) &= (~RTMP_PACKET_SPECIFIC_VLAN); \ + }while(0) +#define RTMP_GET_PACKET_VLAN(_p) (PACKET_CB(_p, 11) & RTMP_PACKET_SPECIFIC_VLAN) + +/*LLC/SNAP */ +#define RTMP_SET_PACKET_LLCSNAP(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 11) |= (RTMP_PACKET_SPECIFIC_LLCSNAP); \ + else \ + PACKET_CB(_p, 11) &= (~RTMP_PACKET_SPECIFIC_LLCSNAP); \ + }while(0) + +#define RTMP_GET_PACKET_LLCSNAP(_p) (PACKET_CB(_p, 11) & RTMP_PACKET_SPECIFIC_LLCSNAP) + +/* IP */ +#define RTMP_SET_PACKET_IPV4(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 11) |= (RTMP_PACKET_SPECIFIC_IPV4); \ + else \ + PACKET_CB(_p, 11) &= (~RTMP_PACKET_SPECIFIC_IPV4); \ + }while(0) + +#define RTMP_GET_PACKET_IPV4(_p) (PACKET_CB(_p, 11) & RTMP_PACKET_SPECIFIC_IPV4) + +/* TDLS */ +#define RTMP_SET_PACKET_TDLS(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_TDLS); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (~RTMP_PACKET_SPECIFIC_TDLS); \ + }while(0) + +#define RTMP_GET_PACKET_TDLS(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_TDLS) + +/* 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, 12) = _flg) +#define RTMP_GET_PACKET_CLEAR_EAP_FRAME(_p) (PACKET_CB(_p, 12)) + +#ifdef MESH_SUPPORT +#define RTMP_SET_MESH_ROUTE_ID(_p, _flg) (PACKET_CB(_p, 13) = _flg) +#define RTMP_GET_MESH_ROUTE_ID(_p) (PACKET_CB(_p, 13)) +#define RTMP_SET_MESH_SOURCE(_p, _flg) (PACKET_CB(_p, 14) = _flg) +#define RTMP_GET_MESH_SOURCE(_p) (PACKET_CB(_p, 14)) +#endif /* MESH_SUPPORT */ + +#define MAX_PACKETS_IN_QUEUE (512) + + +/* 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) + +#define RTMP_SET_PACKET_5VT(_p, _flg) (PACKET_CB(_p, 22) = _flg) +#define RTMP_GET_PACKET_5VT(_p) (PACKET_CB(_p, 22)) + +#define RTMP_SET_PACKET_PROTOCOL(_p, _protocol) {\ + (PACKET_CB(_p, 23) = (UINT8)((_protocol) & 0x00ff)); \ + (PACKET_CB(_p, 24) = (UINT8)(((_protocol) & 0xff00) >> 8)); \ +} + +#define RTMP_GET_PACKET_PROTOCOL(_p) \ + ((((UINT16)PACKET_CB(_p, 23)) << 8) \ + | ((UINT16)PACKET_CB(_p, 24))) + +#ifdef INF_AMAZON_SE +/* [CB_OFF+28], 1B, Iverson patch for WMM A5-T07 ,WirelessStaToWirelessSta do not bulk out aggregate */ +#define RTMP_SET_PACKET_NOBULKOUT(_p, _morebit) (PACKET_CB(_p, 28) = _morebit) +#define RTMP_GET_PACKET_NOBULKOUT(_p) (PACKET_CB(_p, 28)) +#endif /* INF_AMAZON_SE */ +/* Max skb->cb = 48B = [CB_OFF+38] */ + + + +#ifdef P2P_SUPPORT +#define RTMP_SET_PACKET_OPMODE(_p, _flg) (PACKET_CB(_p, 26) = _flg) +#define RTMP_GET_PACKET_OPMODE(_p) (PACKET_CB(_p, 26)) +#endif /* P2P_SUPPORT */ + + + + +/*********************************************************************************** + * 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 + +#endif /* __RT_LINUX_H__ */ diff --git a/mt7620/src/include/os/rt_linux.h b/mt7620/src/include/os/rt_linux.h new file mode 100644 index 0000000..a824d3d --- /dev/null +++ b/mt7620/src/include/os/rt_linux.h @@ -0,0 +1,1783 @@ +/**************************************************************************** + + 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 */ + +#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 "/etc/Wireless/RT2860AP/RT2860AP.dat" +#define AP_RTMP_FIRMWARE_FILE_NAME "/etc/Wireless/RT2860AP/RT2860AP.bin" +#define AP_NIC_DEVICE_NAME "RT2860AP" +#define AP_DRIVER_VERSION "2.7.1.6" +#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. */ +#ifndef P2P_SUPPORT +#define RTMP_FIRMWARE_FILE_NAME "/etc_ro/Wireless/RT2860AP/RT2860AP.bin" +#define PROFILE_PATH "/etc/Wireless/RT2860i.dat" +#endif /* P2P_SUPPORT */ +#if defined(CONFIG_SUPPORT_OPENWRT) +#define AP_PROFILE_PATH_RBUS "/etc/wireless/mt7620/mt7620.dat" +#else +#define AP_PROFILE_PATH_RBUS "/etc/Wireless/RT2860/RT2860.dat" +#endif /* CONFIG_SUPPORT_OPENWRT */ +#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 "2.6.1.6" +#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 */ + +extern const struct iw_handler_def rt28xx_iw_handler_def; +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef SINGLE_SKU_V2 +#ifdef RTMP_RBUS_SUPPORT +#if defined(CONFIG_SUPPORT_OPENWRT) +#define SINGLE_SKU_TABLE_FILE_NAME "/etc/wireless/mt7620/SingleSKU.dat" +#else +#define SINGLE_SKU_TABLE_FILE_NAME "/etc_ro/Wireless/RT2860AP/SingleSKU.dat" +#endif +#endif /* RTMP_RBUS_SUPPORT */ +#endif /* SINGLE_SKU_V2 */ + +#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 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 ETH_LENGTH_OF_ADDRESS 6 + +#define NDIS_STATUS_SUCCESS 0x00 +#define NDIS_STATUS_FAILURE 0x01 +#define NDIS_STATUS_INVALID_DATA 0x02 +#define NDIS_STATUS_RESOURCES 0x03 + +#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 + ***********************************************************************************/ +#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 +#ifdef CONFIG_STA_SUPPORT +#define MIN_NET_DEVICE_FOR_DLS 0x40 +#define MIN_NET_DEVICE_FOR_TDLS 0x50 +#ifdef MESH_SUPPORT +#undef MIN_NET_DEVICE_FOR_DLS +#undef MIN_NET_DEVICE_FOR_TDLS +#define MIN_NET_DEVICE_FOR_DLS (MIN_NET_DEVICE_FOR_MESH + 0x10) +#define MIN_NET_DEVICE_FOR_TDLS (MIN_NET_DEVICE_FOR_MESH + 0x20) +#endif /* MESH_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ +#ifdef P2P_SUPPORT +#define MIN_NET_DEVICE_FOR_P2P_CLI (MIN_NET_DEVICE_FOR_TDLS + 0x10) +#define MIN_NET_DEVICE_FOR_P2P_GO (MIN_NET_DEVICE_FOR_TDLS + 0x20) +#endif /* P2P_SUPPORT */ + +#define NET_DEVICE_REAL_IDX_MASK 0x0f /* for each operation mode, we maximum support 15 entities. */ + + +#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 */ + + +/*********************************************************************************** + * OS signaling related constant definitions + ***********************************************************************************/ + + +/*********************************************************************************** + * OS file operation related data structure definitions + ***********************************************************************************/ +typedef struct file* RTMP_OS_FD; + +typedef struct _OS_FS_INFO_ +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) + kuid_t fsuid; + kgid_t fsgid; +#else + int fsuid; + int fsgid; +#endif + 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; \ + 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; \ + 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=(RTMP_OS_PID)current->pids[PIDTYPE_PID].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 +#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); +typedef struct tasklet_struct OS_NET_TASK_STRUCT; +typedef struct tasklet_struct *POS_NET_TASK_STRUCT; + + +/*********************************************************************************** + * 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)(unsigned long); + + +#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; +/* ra_dma_addr_t pAd_pa; */ +#endif /* RTMP_MAC_PCI */ + + +#ifdef WORKQUEUE_BH + UINT32 pAd_va; + + struct work_struct rx_done_work; + struct work_struct mgmt_dma_done_work; + struct work_struct ac0_dma_done_work; + struct work_struct ac1_dma_done_work; + struct work_struct ac2_dma_done_work; + struct work_struct ac3_dma_done_work; + struct work_struct hcca_dma_done_work; + + struct work_struct tbtt_work; + +#else + RTMP_NET_TASK_STRUCT rx_done_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; +#endif /* WORKQUEUE_BH */ + +#ifdef RTMP_MAC_PCI +#ifdef WORKQUEUE_BH + struct work_struct fifo_statistic_full_work; +#else + RTMP_NET_TASK_STRUCT fifo_statistic_full_task; +#endif /* WORKQUEUE_BH */ +#endif /* RTMP_MAC_PCI */ + +#ifdef UAPSD_SUPPORT +#ifdef WORKQUEUE_BH + struct work_struct uapsd_eosp_sent_work; +#else + RTMP_NET_TASK_STRUCT uapsd_eosp_sent_task; +#endif /* WORKQUEUE_BH */ +#endif /* UAPSD_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef DFS_SUPPORT +#ifdef DFS_SOFTWARE_SUPPORT +#ifdef WORKQUEUE_BH + struct work_struct pulse_radar_detect_work; + struct work_struct width_radar_detect_work; +#else + RTMP_NET_TASK_STRUCT pulse_radar_detect_task; + RTMP_NET_TASK_STRUCT width_radar_detect_task; +#endif /* WORKQUEUE_BH */ +#endif /* DFS_SOFTWARE_SUPPORT */ +#endif /* DFS_SUPPORT */ + +#ifdef CARRIER_DETECTION_SUPPORT +#ifdef WORKQUEUE_BH + struct work_struct carrier_sense_work; +#else + RTMP_NET_TASK_STRUCT carrier_sense_task; +#endif /* WORKQUEUE_BH */ +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef DFS_SUPPORT +#ifdef WORKQUEUE_BH + struct work_struct dfs_work; +#else + struct tasklet_struct dfs_task; +#endif /* WORKQUEUE_BH */ +#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)>>8) & 0xffffff;\ + 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) +#define DBGPRINT_RAW(Level, Fmt) +#define DBGPRINT_S(Status, Fmt) +#define DBGPRINT_ERR(Fmt) +#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 */ + +void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen); + + +/********************************************************************************************************* + 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) \ +{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + writel((_V), (void *)((_A)->CSRBaseAddress + (_R))); \ + } \ +} + +#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) +#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) ((_pNetDev)->ml_priv) +#define _RTMP_OS_NETDEV_SET_PRIV(_pNetDev, _pPriv) ((_pNetDev)->ml_priv = (_pPriv)) +#else +#define _RTMP_OS_NETDEV_GET_PRIV(_pNetDev) ((_pNetDev)->priv) +#define _RTMP_OS_NETDEV_SET_PRIV(_pNetDev, _pPriv) ((_pNetDev)->priv = (_pPriv)) +#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 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) + +/* User Priority */ +#define RTMP_SET_PACKET_UP(_p, _prio) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+0] = _prio) +#define RTMP_GET_PACKET_UP(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+0]) + +/* Fragment # */ +#define RTMP_SET_PACKET_FRAGMENTS(_p, _num) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+1] = _num) +#define RTMP_GET_PACKET_FRAGMENTS(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+1]) + +/* 0x0 ~0x7f: TX to AP's own BSS which has the specified AID. if AID>127, set bit 7 in RTMP_SET_PACKET_EMACTAB too. */ +/*(this value also as MAC(on-chip WCID) table index) */ +/* 0x80~0xff: TX to a WDS link. b0~6: WDS index */ +#define RTMP_SET_PACKET_WCID(_p, _wdsidx) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+2] = _wdsidx) +#define RTMP_GET_PACKET_WCID(_p) ((UCHAR)(RTPKT_TO_OSPKT(_p)->cb[CB_OFF+2])) + +/* 0xff: PKTSRC_NDIS, others: local TX buffer index. This value affects how to a packet */ +#define RTMP_SET_PACKET_SOURCE(_p, _pktsrc) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+3] = _pktsrc) +#define RTMP_GET_PACKET_SOURCE(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+3]) + +/* RTS/CTS-to-self protection method */ +#define RTMP_SET_PACKET_RTS(_p, _num) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+4] = _num) +#define RTMP_GET_PACKET_RTS(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+4]) +/* see RTMP_S(G)ET_PACKET_EMACTAB */ + +/* TX rate index */ +#define RTMP_SET_PACKET_TXRATE(_p, _rate) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+5] = _rate) +#define RTMP_GET_PACKET_TXRATE(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+5]) + +/* From which Interface */ +#define RTMP_SET_PACKET_IF(_p, _ifdx) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+6] = _ifdx) +#define RTMP_GET_PACKET_IF(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+6]) +#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)) + +#define RTMP_SET_PACKET_MOREDATA(_p, _morebit) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+7] = _morebit) +#define RTMP_GET_PACKET_MOREDATA(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+7]) + + + +#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) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+9] = ((_flg_uapsd<<7) | _que_id)) + +#define RTMP_SET_PACKET_QOS_NULL(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+9] = 0xff) +#define RTMP_GET_PACKET_QOS_NULL(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+9]) +#define RTMP_SET_PACKET_NON_QOS_NULL(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+9] = 0x00) +#define RTMP_GET_PACKET_UAPSD_Flag(_p) (((RTPKT_TO_OSPKT(_p)->cb[CB_OFF+9]) & 0x80) >> 7) +#define RTMP_GET_PACKET_UAPSD_QUE_ID(_p) ((RTPKT_TO_OSPKT(_p)->cb[CB_OFF+9]) & 0x7f) + +#define RTMP_SET_PACKET_EOSP(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+10] = _flg) +#define RTMP_GET_PACKET_EOSP(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+10]) +#endif /* UAPSD_SUPPORT */ + +/* */ +/* Sepcific Pakcet Type definition */ +/* */ +#define RTMP_PACKET_SPECIFIC_CB_OFFSET 11 + +#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 + +/*Specific */ +#define RTMP_SET_PACKET_SPECIFIC(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] = _flg) + +/*DHCP */ +#define RTMP_SET_PACKET_DHCP(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_DHCP); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (~RTMP_PACKET_SPECIFIC_DHCP); \ + }while(0) +#define RTMP_GET_PACKET_DHCP(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_DHCP) + +/*EAPOL */ +#define RTMP_SET_PACKET_EAPOL(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_EAPOL); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (~RTMP_PACKET_SPECIFIC_EAPOL); \ + }while(0) +#define RTMP_GET_PACKET_EAPOL(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_EAPOL) + +/*WAI */ +#define RTMP_SET_PACKET_WAI(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_WAI); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (~RTMP_PACKET_SPECIFIC_WAI); \ + }while(0) +#define RTMP_GET_PACKET_WAI(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_WAI) + +#define RTMP_GET_PACKET_LOWRATE(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & (RTMP_PACKET_SPECIFIC_EAPOL | RTMP_PACKET_SPECIFIC_DHCP | RTMP_PACKET_SPECIFIC_WAI)) + +/*VLAN */ +#define RTMP_SET_PACKET_VLAN(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_VLAN); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (~RTMP_PACKET_SPECIFIC_VLAN); \ + }while(0) +#define RTMP_GET_PACKET_VLAN(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_VLAN) + +/*LLC/SNAP */ +#define RTMP_SET_PACKET_LLCSNAP(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_LLCSNAP); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (~RTMP_PACKET_SPECIFIC_LLCSNAP); \ + }while(0) + +#define RTMP_GET_PACKET_LLCSNAP(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_LLCSNAP) + +/* IP */ +#define RTMP_SET_PACKET_IPV4(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_IPV4); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (~RTMP_PACKET_SPECIFIC_IPV4); \ + }while(0) + +#define RTMP_GET_PACKET_IPV4(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_IPV4) + +// TDLS +#define RTMP_SET_PACKET_TDLS(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_TDLS); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (~RTMP_PACKET_SPECIFIC_TDLS); \ + }while(0) + +#define RTMP_GET_PACKET_TDLS(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_TDLS) + +/* If this flag is set, it indicates that this EAPoL frame MUST be clear. */ +#define RTMP_SET_PACKET_CLEAR_EAP_FRAME(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+12] = _flg) +#define RTMP_GET_PACKET_CLEAR_EAP_FRAME(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+12]) + +#ifdef MESH_SUPPORT +#define RTMP_SET_MESH_ROUTE_ID(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+13] = _flg) +#define RTMP_GET_MESH_ROUTE_ID(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+13]) +#define RTMP_SET_MESH_SOURCE(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+14] = _flg) +#define RTMP_GET_MESH_SOURCE(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+14]) +#endif /* MESH_SUPPORT */ + +#define MAX_PACKETS_IN_QUEUE (512) + + +/* use bit3 of cb[CB_OFF+16] */ +#define RTMP_SET_PACKET_MGMT_PKT(_p, _flg) \ + RTPKT_TO_OSPKT(_p)->cb[CB_OFF+16] = (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+16] & 0xF7) | ((_flg & 0x01) << 3); +#define RTMP_GET_PACKET_MGMT_PKT(_p) \ + ((RTPKT_TO_OSPKT(_p)->cb[CB_OFF+16] & 0x08) >> 3) + +/* use bit0 of cb[CB_OFF+20] */ +#define RTMP_SET_PACKET_MGMT_PKT_DATA_QUE(_p, _flg) \ + RTPKT_TO_OSPKT(_p)->cb[CB_OFF+20] = (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+20] & 0xFE) | (_flg & 0x01); +#define RTMP_GET_PACKET_MGMT_PKT_DATA_QUE(_p) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+20] & 0x01) + +#define RTMP_SET_PACKET_5VT(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+22] = _flg) +#define RTMP_GET_PACKET_5VT(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+22]) + +#define RTMP_SET_PACKET_PROTOCOL(_p, _protocol) {\ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+23] = (UINT8)((_protocol) & 0x00ff)); \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+24] = (UINT8)(((_protocol) & 0xff00) >> 8)); \ +} + +#define RTMP_GET_PACKET_PROTOCOL(_p) \ + ((((UINT16)(RTPKT_TO_OSPKT(_p)->cb[CB_OFF+24]) & 0x00ff) << 8) \ + | ((UINT16)(RTPKT_TO_OSPKT(_p)->cb[CB_OFF+23]) & 0x00ff)) + +#ifdef INF_AMAZON_SE +/* [CB_OFF+28], 1B, Iverson patch for WMM A5-T07 ,WirelessStaToWirelessSta do not bulk out aggregate */ +#define RTMP_SET_PACKET_NOBULKOUT(_p, _morebit) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+28] = _morebit) +#define RTMP_GET_PACKET_NOBULKOUT(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+28]) +#endif /* INF_AMAZON_SE */ + + +#ifdef P2P_SUPPORT +#define RTMP_SET_PACKET_OPMODE(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+26] = _flg) +#define RTMP_GET_PACKET_OPMODE(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+26]) +#endif /* P2P_SUPPORT */ + + +/* Max skb->cb = 48B = [CB_OFF+38] */ + + + +/*********************************************************************************** + * Other function prototypes definitions + ***********************************************************************************/ +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( + IN PNET_DEV net_dev, + IN OUT struct ifreq *rq, + IN INT cmd); + +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); + +#if !defined(CONFIG_RA_NAT_NONE) +extern int (*ra_sw_nat_hook_tx)(VOID *skb); +extern int (*ra_sw_nat_hook_rx)(VOID *skb); +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#define _GET_PAD_FROM_NET_DEV(_pAd, _net_dev) (_pAd) = (_net_dev)->ml_priv; +#else +#define _GET_PAD_FROM_NET_DEV(_pAd, _net_dev) (_pAd) = (_net_dev)->priv; +#endif + +#define GET_PAD_FROM_NET_DEV(_pAd, _net_dev) \ + _pAd = RTMP_OS_NETDEV_GET_PRIV(_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; \ + RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(__pNetPkt), PKTSRC_NDIS); \ +} + +typedef struct usb_device_id USB_DEVICE_ID; + +#ifdef INF_AMAZON_SE +#define BULKAGGRE_SIZE 30 +#else +#define BULKAGGRE_SIZE 60 /* 100 */ +#endif /* INF_AMAZON_SE */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + +#ifndef OS_ABL_SUPPORT +/*#define RT28XX_PUT_DEVICE usb_put_dev */ +#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, 5, 0) +#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 +#else +#define RTUSB_URB_ALLOC_BUFFER(_dev, _size, _dma) kmalloc(_size, GFP_ATOMIC) +#define RTUSB_URB_FREE_BUFFER(_dev, _size, _addr, _dma) kfree(_addr) +#endif + +#else + +/*#define RT28XX_PUT_DEVICE rausb_put_dev */ +#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 + +#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 + +#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) +#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) +#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); + +/* 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) +#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) + +#endif + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,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) +#else +#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) +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,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; */ +#else +#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) +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define RTUSB_URB_DMA_MAPPING(pUrb) \ + { \ + pUrb->transfer_dma = 0; \ + pUrb->transfer_flags &= (~URB_NO_TRANSFER_DMA_MAP); \ + } +#else +#define RTUSB_URB_DMA_MAPPING(pUrb) +#endif + +#define RTUSB_CONTROL_MSG(pUsb_Dev, uEndpointAddress, Request, RequestType, Value,Index, tmpBuf, TransferBufferLength, timeout, ret) \ + do{ \ + if (RequestType == DEVICE_VENDOR_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 */ + + + +#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" + +#endif /* __RT_LINUX_H__ */ diff --git a/mt7620/src/include/os/rt_linux_cmm.h b/mt7620/src/include/os/rt_linux_cmm.h new file mode 100644 index 0000000..1dc05a4 --- /dev/null +++ b/mt7620/src/include/os/rt_linux_cmm.h @@ -0,0 +1,420 @@ +/**************************************************************************** + * 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 "rt2860" + +#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_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 RTUSBMlmeUp OS_RTUSBMlmeUp + +#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 RTUSBMlmeUp 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); \ +} + +/* sample, use semaphore lock to replace IRQ lock, 2007/11/15 */ +#ifdef MULTI_CORE_SUPPORT + +#define RTMP_IRQ_LOCK(__lock, __irqflags) \ +{ \ + __irqflags = 0; \ + 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; \ + 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 + +#ifdef WORKQUEUE_BH +#define RTMP_OS_TASKLET_SCHE(__pTasklet) \ + schedule_work(__pTasklet) +#define RTMP_OS_TASKLET_INIT(__pAd, __pTasklet, __pFunc) \ + INIT_WORK(__pTasklet, __pFunc) +#define RTMP_OS_TASKLET_KILL(__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; + +#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 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)].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 +#define TX_RING_SIZE 64 /*64*/ +#define MGMT_RING_SIZE 128 +#define RX_RING_SIZE 128 /*64 */ +#endif +#define MAX_TX_PROCESS TX_RING_SIZE /*8 */ +#define MAX_DMA_DONE_PROCESS TX_RING_SIZE +#define MAX_TX_DONE_PROCESS TX_RING_SIZE /*8 */ +#define LOCAL_TXBUF_SIZE 2 +#endif /* RTMP_MAC_PCI */ + +#define RTMP_OS_NETDEV_SET_PRIV RtmpOsSetNetDevPriv +#define RTMP_OS_NETDEV_GET_PRIV RtmpOsGetNetDevPriv +#define RT_DEV_PRIV_FLAGS_GET RtmpDevPrivFlagsGet +#define RT_DEV_PRIV_FLAGS_SET RtmpDevPrivFlagsSet + +#endif /* __RT_LINUX_CMM_H__ */ + +/* End of rt_linux_cmm.h */ diff --git a/mt7620/src/include/os/rt_os.h b/mt7620/src/include/os/rt_os.h new file mode 100644 index 0000000..29adb78 --- /dev/null +++ b/mt7620/src/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) + +#ifdef DBG +#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) */ +#ifdef DBG +#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) +#ifdef INF_AR9 +#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/mt7620/src/include/p2p.h b/mt7620/src/include/p2p.h new file mode 100644 index 0000000..91f9d64 --- /dev/null +++ b/mt7620/src/include/p2p.h @@ -0,0 +1,1240 @@ +/* + *************************************************************************** + * 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: + p2p.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + +*/ + +#ifndef __P2P_H__ +#define __P2P_H__ + +#include "p2p_cmm.h" +#include "rtmp.h" + +/* + * New is here + */ + +/* Macro */ +#define P2P_DISABLE 0x00000000 +#define P2P_GO_UP 0x00000001 +#define P2P_CLI_UP 0x00000002 +#define P2P_FIXED_MODE 0x80000000 + +#define P2P_GO_ON(_pAd) \ + (((_pAd)->flg_p2p_init) \ + && (((_pAd)->flg_p2p_OpStatusFlags & P2P_GO_UP) == P2P_GO_UP)) + +#define P2P_CLI_ON(_pAd) \ + (((_pAd)->flg_p2p_init) \ + && ((_pAd)->flg_p2p_OpStatusFlags == P2P_CLI_UP)) + +/* ASCII to Integer */ + +/* atoi & atoh */ + +/* event */ + +/* general */ + + + + +typedef struct _RTMP_OID_SET_P2P_CONFIG +{ + UCHAR ConfigMode; /* Disable, activate p2p, or activate WPSE, or delete p2p profile. */ + ULONG WscMode; /* Method : PIN or PBC or SMPBC */ + UCHAR PinCode[8]; + UCHAR DeviceName[32]; + ULONG DeviceNameLen; + UCHAR SSID[32]; + UCHAR SSIDLen; + UCHAR P2PGroupMode; /* temporary or persistent. See definition. */ + UCHAR GoIntentIdx; /* Value = 0~15. Intent to be a GO in P2P */ + UCHAR ConnectingMAC[MAX_P2P_GROUP_SIZE][6]; /* Specify MAC address want to connect. Set to all 0xff or all 0x0 if not specified. */ + UCHAR ConnectingDeviceName[MAX_P2P_GROUP_SIZE][32]; /* Specify the Device Name that want to connect. Set to all 0xff or all 0x0 if not specified. */ + UCHAR ListenChannel; + UCHAR OperatinChannel; +} RT_OID_SET_P2P_STRUCT, *PRT_OID_SET_P2P_STRUCT; + +typedef struct _RALINKIP_IE +{ + UCHAR ElementID; /* 0xDD */ + UCHAR Length; /* limited by 256 */ + UCHAR OUI[3]; /* should be SSIDL_OUI {00-0c-43-} */ + UCHAR OUIMode; /* See definition RALINKOUIMODE_xxxx */ + UCHAR Octet[1]; /* Set bit position according to Aid. (Like DTIM) */ +} RALINKIP_IE, *PRALINKIP_IE; + +typedef struct _RALINKMBRIP_ELEM +{ + UCHAR Addr[MAC_ADDR_LEN]; + ULONG Memberip; +} RALINKMBRIP_ELEM, *PRALINKMBRIP_ELEM; + +/* global function prototype for non-p2p modules */ + + +INT Set_P2P_Enable( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Listen_Channel( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Operation_Channel( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_GO_Intent( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Device_Name( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_WSC_Mode( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_WSC_ConfMethod( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_NoA_Count( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_NoA_Duration( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_NoA_Interval( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Extend_Listen( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Extend_Listen_Interval( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Extend_Listen_Periodic( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Intra_Bss( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Print_Cfg( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Scan( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Print_GroupTable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Print_PersistentTable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Provision_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Invite_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Device_Discoverability_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Connect_GoIndex_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Connect_Dev_Addr_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Provision_Dev_Addr_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_State_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Reset_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Link_Down_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Sigma_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_QoS_NULL_Legacy_Rate_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_CLIENT_PM_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Persistent_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Enter_WSC_PIN_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Dev_Discoverability_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Default_Config_Method_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_DelDevByAddr_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_DevDiscPeriod_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_PriDeviceType_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_SecDevTypeList_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_P2P_Cancel_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +VOID P2PStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID MlmeGASIntialReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeGASIntialRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeGASComebackReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeGASComebackRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeP2pNoaAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeP2pPresRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeP2pGoDiscoverAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeP2pPresReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerP2pNoaAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerP2pPresRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerP2pGoDiscoverAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerP2pPresReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pSendServiceReqCmd( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr, + IN UCHAR p2pindex); + +VOID P2pSendPresenceReqCmd( + IN PRTMP_ADAPTER pAd, + IN UCHAR p2pindex); + +VOID P2pGOStartNoA( + IN PRTMP_ADAPTER pAd); + +VOID P2pStopNoA( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pMacClient); + +VOID P2pStartOpPS( + IN PRTMP_ADAPTER pAd); + +VOID P2pStopOpPS( + IN PRTMP_ADAPTER pAd); + +VOID P2pPreAbsenTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID P2pSwNoATimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID P2pWscTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID P2pReSendTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID P2pCliReConnectTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +BOOLEAN P2pHandleNoAAttri( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pMacClient, + IN PUCHAR pData); + +BOOLEAN P2pResetNoATimer( + IN PRTMP_ADAPTER pAd, + IN ULONG DiffTimeInus); + +BOOLEAN P2pSetGP( + IN PRTMP_ADAPTER pAd, + IN ULONG DiffTimeInus); + +VOID P2pGPTimeOutHandle( + IN PRTMP_ADAPTER pAd); + +VOID PeerGASIntialReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerGASIntialRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2PPublicAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pCopyPerstParmToCfg( + IN PRTMP_ADAPTER pAd, + IN UCHAR Perstindex); + +VOID P2pGetRandomSSID( + IN PRTMP_ADAPTER pAd, + OUT PSTRING pSSID, + OUT PUCHAR pSSIDLen); + +INT P2P_GoSetCommonHT( + IN PRTMP_ADAPTER pAd); + +VOID P2pSetPerstTable( + IN PRTMP_ADAPTER pAd, + IN PVOID pInformationBuffer); + +VOID P2pEnable( + IN PRTMP_ADAPTER pAd); + +VOID P2pCfgInit( + IN PRTMP_ADAPTER pAd); + +VOID P2pLinkDown( + IN PRTMP_ADAPTER pAd, + IN INT32 type); + +VOID P2pScanChannelDefault( + IN PRTMP_ADAPTER pAd); + +VOID P2pPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID P2pStopConnectThis( + IN PRTMP_ADAPTER pAd); + +VOID P2pScan( + IN PRTMP_ADAPTER pAd); + +VOID P2pStopScan( + IN PRTMP_ADAPTER pAd); + +VOID P2pCheckInviteReq( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bIAmGO, + IN UCHAR index, + IN PUCHAR ChannelList, + IN PUCHAR BssidAddr, + IN UCHAR OpChannel, + IN PUCHAR Ssid, + IN UCHAR SsidLen, + IN UCHAR *pRspStatus); + +VOID P2pCheckInviteReqFromExisting( + IN PRTMP_ADAPTER pAd, + IN PUCHAR ChannelList, + IN PUCHAR BssidAddr, + IN UCHAR OpChannel, + IN PUCHAR Ssid, + IN UCHAR SsidLen, + IN PUCHAR pRspStatus); + + +BOOLEAN P2pCheckChannelList( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pChannelList); + +VOID P2PMakeFakeNoATlv( + IN PRTMP_ADAPTER pAd, + IN ULONG StartTime, + IN PUCHAR pOutBuffer); + +ULONG InsertP2PGroupInfoTlv( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pOutBuffer); + +ULONG InsertP2PSubelmtTlv( + IN PRTMP_ADAPTER pAd, + IN UCHAR SubId, + IN PUCHAR pInBuffer, + IN PUCHAR pOutBuffer); + +VOID InsertP2pChannelList( + IN PRTMP_ADAPTER pAd, + IN UCHAR OpChannel, + OUT ULONG *ChannelListLen, + OUT PUCHAR pDest); + +BOOLEAN P2pParseGroupInfoAttribute( + IN PRTMP_ADAPTER pAd, + IN UCHAR P2pindex, + IN VOID *Msg, + IN ULONG MsgLen); + +VOID P2pParseNoASubElmt( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN UCHAR wcidindex, + IN UINT32 Sequence); + +VOID P2pParseExtListenSubElmt( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT USHORT *ExtListenPeriod, + OUT USHORT *ExtListenInterval); + +VOID P2pParseManageSubElmt( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *pChannel, + OUT UCHAR *pNumOfP2pOtherAttribute, + OUT UCHAR *pTotalNumOfP2pAttribute, + OUT UCHAR *pMamageablity, + OUT UCHAR *pMinorReason); + +VOID P2pParseSubElmt( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN BOOLEAN bBeacon, + OUT USHORT *pDpid, + OUT UCHAR *pGroupCap, + OUT UCHAR *pDeviceCap, + OUT UCHAR *pDeviceName, + OUT UCHAR *pDeviceNameLen, + OUT UCHAR *pDevAddr, + OUT UCHAR *pInterFAddr, + OUT UCHAR *pBssidAddr, + OUT UCHAR *pSsidLen, + OUT UCHAR *pSsid, + OUT USHORT *pConfigMethod, + OUT USHORT *pWpsConfigMethod, + OUT UCHAR *pDevType, + OUT UCHAR *pListenChannel, + OUT UCHAR *pOpChannel, + OUT UCHAR *pChannelList, + OUT UCHAR *pIntent, + OUT UCHAR *pStatusCode, + OUT UCHAR *pInviteFlag); + +VOID P2pReceGoNegoConfirmAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pReceGoNegoRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pSendProbeReq( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel); + +VOID P2pReceGoNegoReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pReceDevDisReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pReceDevDisRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pReceInviteRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pReceInviteReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pReceProvisionReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID P2pReceProvisionRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + + +VOID P2PMakeGoNegoConfirm( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr1, + IN UCHAR Token, + IN PUCHAR pOutBuffer, + OUT PULONG pTotalFrameLen); + +VOID P2PSendGoNegoConfirm( + IN PRTMP_ADAPTER pAd, + IN UCHAR Token, + IN UCHAR idx, + IN PUCHAR Addr1); + +VOID P2PSendDevDisReq( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr1, + IN PUCHAR Bssid, + IN PUCHAR ClientAddr1, + OUT PULONG pTotalFrameLen); + +VOID P2PSendDevDisRsp( + IN PRTMP_ADAPTER pAd, + IN UCHAR RspStatus, + IN UCHAR Token, + IN PUCHAR Addr1, + OUT PULONG pTotalFrameLen); + +VOID P2PSendProvisionReq( + IN PRTMP_ADAPTER pAd, + IN USHORT ConfigMethod, + IN UCHAR Token, + IN PUCHAR Addr1, + OUT PULONG pTotalFrameLen); + +VOID P2PSendProvisionRsp( + IN PRTMP_ADAPTER pAd, + IN USHORT ConfigMethod, + IN UCHAR Token, + IN PUCHAR Addr1, + OUT PULONG pTotalFrameLen); + +VOID P2PMakeGoNegoRsp( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr1, + IN USHORT ReceDpid, + IN UCHAR Token, + IN UCHAR TempIntent, + IN UCHAR Channel, + IN UCHAR Status, + IN PUCHAR pOutBuffer, + OUT PULONG pTotalFrameLen); + +VOID P2PMakeGoNegoReq( + IN PRTMP_ADAPTER pAd, + IN UCHAR index, + IN PUCHAR Addr1, + IN PUCHAR pOutBuffer, + OUT PULONG pTotalFrameLen); + +VOID P2PMakeInviteReq( + IN PRTMP_ADAPTER pAd, + IN UCHAR MyRule, + IN UCHAR InviteFlag, + IN PUCHAR Addr1, + IN PUCHAR Bssid, + OUT PULONG pTotalFrameLen); + +VOID P2PMakeInviteRsp( + IN PRTMP_ADAPTER pAd, + IN UCHAR MyRule, + IN UCHAR Token, + IN PUCHAR Addr1, + IN PUCHAR Bssid, + IN PUCHAR OpChannel, + IN PUCHAR Status, + OUT PULONG pTotalFrameLen); + +VOID P2pAckRequiredCheck( + IN PRTMP_ADAPTER pAd, + IN PP2P_PUBLIC_FRAME pFrame, + OUT UCHAR *TempPid); + +BOOLEAN IsP2pFirstMacSmaller( + IN PUCHAR Firststaddr, + IN PUCHAR SecondAddr); + +VOID P2pSetListenIntBias( + IN PRTMP_ADAPTER pAd, + IN UCHAR Bias); + +VOID P2pSetRule( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index, + IN PUCHAR PeerBssid, + IN UCHAR PeerGOIntent, + IN UCHAR Channel); + +VOID P2pGroupMaintain( + IN PRTMP_ADAPTER pAd); + +VOID P2pCopyP2PTabtoMacTab( + IN PRTMP_ADAPTER pAd, + IN UCHAR P2pindex, + IN UCHAR Macindex); + +VOID P2pGroupTabInit( + IN PRTMP_ADAPTER pAd); + +VOID P2pGroupTabDisconnect( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bSendDeAuth); + +UCHAR P2pGroupTabInsert( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr, + IN P2P_CLIENT_STATE State, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR DevCap, + IN UCHAR GrpCap); + +UCHAR P2pGroupTabDelete( + IN PRTMP_ADAPTER pAd, + IN UCHAR p2pindex, + IN PUCHAR Addr); + +UCHAR P2pGroupTabSearch( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr); + +VOID P2pPerstTabClean( + IN PRTMP_ADAPTER pAd); + +UCHAR P2pPerstTabInsert( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN PWSC_CREDENTIAL pProfile); + +UCHAR P2pPerstTabDelete( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pMacList); + +UCHAR P2pPerstTabSearch( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr, + IN PUCHAR Bssid, + IN PUCHAR InfAddr); + +VOID P2pCrednTabClean( + IN PRTMP_ADAPTER pAd); + +VOID P2pCrednTabInsert( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN WSC_CREDENTIAL *pProfile); + +VOID P2pCrednTabDelete( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pAddr); + +BOOLEAN P2pCrednEntrySearch( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr, + IN PUCHAR ResultIndex); + +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT +VOID P2pSendWirelessEvent( + IN PRTMP_ADAPTER pAd, + IN INT MsgType, + IN PRT_P2P_CLIENT_ENTRY pP2pEntry, + IN PUCHAR Addr); +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ + +#ifdef DPA_S +VOID P2pSendDevFoundEvent( + IN PRTMP_ADAPTER pAd, + IN INT flags, + IN CHAR Rssi, + IN PUCHAR pPeerDeviceName, + IN UCHAR DeviceNameLen, + IN PUCHAR P2PSubelement, + IN ULONG P2PSubelementLen); + +VOID P2pSendPeerNegoReqEvent( + IN PRTMP_ADAPTER pAd, + IN INT flags, + IN USHORT PeerDPID, + IN PUCHAR pPeerAddr, + IN UCHAR RspStatus, + IN PUCHAR pPeerDeviceName, + IN UCHAR DeviceNameLen); + +VOID P2pSendSamsungEvent( + IN PRTMP_ADAPTER pAd, + IN INT flags, + IN PUCHAR pPeerAddr, + IN PUCHAR pPeerDeviceName, + IN UCHAR DeviceNameLen); + +VOID P2pMaintainGroupTable( + IN PRTMP_ADAPTER pAd, + IN ULONG MaxRxTimeDiff, + IN UCHAR MaxSameRxTimeCount); +#endif /* DPA_S */ + +BOOLEAN P2pStartGroupForm( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr, + IN UCHAR idx); + +BOOLEAN P2pProvision( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr); + +BOOLEAN P2pConnect( + IN PRTMP_ADAPTER pAd); + +VOID P2pConnectPrepare( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr, + IN UINT32 ConnType); + +BOOLEAN P2pConnectAfterScan( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bBeacon, + IN UCHAR idx); + +VOID P2pConnectAction( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bBeacon, + IN UCHAR index); + +VOID P2pConnectP2pClient( + IN PRTMP_ADAPTER pAd, + IN UCHAR GrpIndex); + +BOOLEAN P2pConnectP2pGo( + IN PRTMP_ADAPTER pAd, + IN UCHAR idx); + +BOOLEAN P2pClientDiscovery( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr, + IN UCHAR GoP2pTabIdx); + +BOOLEAN P2pInviteAsRule( + IN PRTMP_ADAPTER pAd, + IN UCHAR MyRule, + IN UCHAR P2pTabIdx); + +BOOLEAN P2pInvite( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr, + IN UCHAR PersistentTabIdx, + IN UCHAR P2pTabIdx); + +BOOLEAN PeerP2pProbeReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen, + OUT ULONG *Peerip, +/* OUT RALINKIP_IE *RequestIp, */ + OUT ULONG *P2PSubelementLen, + OUT PUCHAR pP2pSubelement, +/* OUT USHORT *WSCInfoAtBeaconsLen, */ +/* OUT PUCHAR WSCInfoAtBeacons, */ +/* OUT USHORT *WSCInfoAtProbeRspLen, */ +/* OUT PUCHAR WSCInfoAtProbeRsp, */ + OUT ULONG *WpsIELen, + OUT PUCHAR pWpsIE); + +BOOLEAN PeerP2pBeaconSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen, + OUT ULONG *Peerip, + OUT ULONG *P2PSubelementLen, + OUT PUCHAR pP2pSubelement); + +BOOLEAN PeerP2pProbeRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen, + OUT ULONG *Peerip, + OUT ULONG *P2PSubelementLen, + OUT PUCHAR pP2pSubelement); + +VOID P2pPeerBeaconAtJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem, + IN PUCHAR Bssid); + +VOID PeerP2pBeaconProbeRspAtScan( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +/* IN USHORT CapabilityInfo, */ +/* IN UCHAR WorkingChannel); */ +/* IN USHORT WSCInfoAtBeaconsLen, + IN PUCHAR WSCInfoAtBeacons, + IN USHORT WSCInfoAtProbeRspLen, + IN PUCHAR WSCInfoAtProbeRsp);*/ + +VOID PeerP2pBeacon( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr2, + IN MLME_QUEUE_ELEM *Elem, + IN LARGE_INTEGER TimeStamp); + +BOOLEAN PeerBeaconParseRalinkIE( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT RALINKIP_IE *pRalinkIE, + OUT RALINKMBRIP_ELEM *pMemberip, + OUT ULONG *pPeerip); + +VOID PeerP2pProbeReq( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +/* IN BOOLEAN bSendRsp); */ + +VOID P2PParseWPSIE( + IN PUCHAR pWpsData, + IN USHORT WpsLen, + OUT PUSHORT Dpid, + OUT PUSHORT ConfigMethod, + OUT PUCHAR DeviceName, + OUT UCHAR *DeviceNameLen); + +BOOLEAN P2PDeviceMatch( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr, + IN PUCHAR DeviceName, + IN ULONG DeviceNameLen); + +VOID P2PMakeProbe( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem, + IN UCHAR DsChannel, + IN USHORT SubType, + OUT PUCHAR pDest, + OUT ULONG *pFrameLen); + +VOID P2pMakeP2pIE( + IN PRTMP_ADAPTER pAd, + IN UCHAR PacketType, + OUT PUCHAR pOutBuf, + OUT PULONG pIeLen); + +VOID P2pSetWps( + IN PRTMP_ADAPTER pAd, + IN PRT_P2P_CLIENT_ENTRY pP2pEntry); + +VOID P2pGotoIdle( + IN PRTMP_ADAPTER pAd); + +VOID P2pGotoScan( + IN PRTMP_ADAPTER pAd); + +VOID P2pGoNegoDone( + IN PRTMP_ADAPTER pAd, + IN PRT_P2P_CLIENT_ENTRY pP2pEntry); + +VOID P2pWpsDone( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +VOID P2pCopyMacTabtoP2PTab( + IN PRTMP_ADAPTER pAd, + IN UCHAR P2pindex, + IN UCHAR Macindex); + +VOID P2pReceiveEapNack( + IN PRTMP_ADAPTER pAd, + IN PMLME_QUEUE_ELEM pElem); + +VOID P2pMakeProbeRspWSCIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pOutBuf, + OUT PULONG pIeLen); + +VOID P2pMakeProbeReqIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pOutBuf, + OUT PUCHAR pIeLen); + +VOID P2pStartAutoGo( + IN PRTMP_ADAPTER pAd); + +VOID P2pStartGo( + IN PRTMP_ADAPTER pAd); + +VOID P2pPauseBssSync( + IN PRTMP_ADAPTER pAd); + +VOID P2pResumeBssSync( + IN PRTMP_ADAPTER pAd); + +VOID P2PCTWindowTimer( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID GoPeerDisassocReq( + IN PRTMP_ADAPTER pAd, + IN PUCHAR Addr2); + +ULONG P2pUpdateGroupBeacon( + IN PRTMP_ADAPTER pAd, + IN ULONG StartPosition); + +ULONG P2pUpdateNoABeacon( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx, +/* IN ULONG StartPosition); */ + IN PUCHAR pDest); + +ULONG P2pUpdateNoAProbeRsp( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pInbuffer); + +VOID P2pUpdateBssBeacon( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pCapability, + IN PUCHAR pIpReq); + +VOID P2pMakeBssBeacon( + IN PRTMP_ADAPTER pAd); + +VOID P2PInitListenTimer( + IN PRTMP_ADAPTER pAd, + UINT32 value); + +VOID P2PSetListenTimer( + IN PRTMP_ADAPTER pAd, + UINT32 value); + +VOID P2PListenTimerExec( + IN PRTMP_ADAPTER pAd, + UINT32 value); + +VOID P2PInitNextScanTimer( + IN PRTMP_ADAPTER pAd, + UINT32 value); + +VOID P2PSetNextScanTimer( + IN PRTMP_ADAPTER pAd, + UINT32 value); + +VOID P2PNextScanTimerExec( + IN PRTMP_ADAPTER pAd, + UINT32 value); + +VOID P2PInitDevDiscTimer( + IN PRTMP_ADAPTER pAd, + UINT32 value); + +VOID P2PSetDevDiscTimer( + IN PRTMP_ADAPTER pAd, + UINT32 value); + +VOID P2PDevDiscTimerExec( + IN PRTMP_ADAPTER pAd, + UINT32 value); + +VOID P2P_SetWscRule( + IN PRTMP_ADAPTER pAd, + UCHAR index, + PUSHORT PeerWscMethod); + +VOID GOUpdateBeaconFrame( + IN PRTMP_ADAPTER pAd); + +UCHAR ChannelToClass( + IN UCHAR Channel, + IN UCHAR Country); + +VOID P2PCtrlStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID P2PDiscoveryStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID P2PGoFormationStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID P2PStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID P2PInitChannelRelatedValue( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS P2PAPInitialize( + IN PRTMP_ADAPTER pAd); + +VOID P2PAPShutdown( + IN PRTMP_ADAPTER pAd); + +VOID P2PUserCfgInit( + IN PRTMP_ADAPTER pAd); + +PSTRING decodeDpid (USHORT dpid); +PSTRING decodeConfigMethod (USHORT ConfigMethos); +PSTRING decodeP2PState (UCHAR P2pState); +PSTRING decodeP2PClientState (P2P_CLIENT_STATE P2pClientState); +PSTRING decodeMyRule (USHORT Rule); +PSTRING decodeCtrlState (UCHAR State); +PSTRING decodeDiscoveryState (UCHAR State); +PSTRING decodeGroupFormationState (UCHAR State); +VOID decodeDeviceCap (UCHAR State); +VOID decodeGroupCap (UCHAR State); + + +VOID P2PPrintMac( + IN PRTMP_ADAPTER pAd, + IN UCHAR macindex); + +VOID P2PPrintP2PEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR p2pindex); + +VOID P2PPrintP2PPerstEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR p2pindex); + +VOID P2P_GoStartUp( + IN PRTMP_ADAPTER pAd, + IN INT bssidx); + +VOID P2P_GoStop( + IN PRTMP_ADAPTER pAd); + +VOID P2P_CliStartUp( + IN PRTMP_ADAPTER pAd); + +VOID P2P_CliStop( + IN PRTMP_ADAPTER pAd); + +VOID AsicEnableP2PGoSync( + IN PRTMP_ADAPTER pAd); + +VOID MgtMacP2PHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN PUCHAR pDA, + IN PUCHAR pBssid); + +VOID P2PMacTableReset( + IN PRTMP_ADAPTER pAd); + +VOID P2PMacTableMaintenance( + IN PRTMP_ADAPTER pAd); + +VOID P2PChannelInit( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex); + +VOID P2PCfgInit( + IN PRTMP_ADAPTER pAd); + +VOID P2PUpdateMlmeRate( + IN PRTMP_ADAPTER pAd, + USHORT ifIndex); + +VOID P2pInit( + IN PRTMP_ADAPTER pAd, + IN RTMP_OS_NETDEV_OP_HOOK *pNetDevOps); + +INT P2P_OpenPre( + IN PNET_DEV pDev); + +INT P2P_OpenPost( + IN PNET_DEV pDev); + +INT P2P_Close( + IN PNET_DEV pDev); + +VOID P2P_Remove( + IN PRTMP_ADAPTER pAd); + + +/* ******************************************************************** */ +/* WiFi Direct control */ + +#define P2P_INC_CHA_INDEX(_idx, _RingSize) \ +{ \ + (_idx)++; \ + if ((_idx) >= (_RingSize)) _idx=0; \ +} +/* channel 1, 6, 11 is listen channel. */ +#define P2P_LISTEN_CHA_SIZE 3 + + +#define ICS_STATUS_ENABLED 1 +#define ICS_STATUS_DISABLED 0 + + + +#define P2PMANAGED_ENABLE_BIT 0x1 +#define P2PMANAGED_ICS_ENABLE_BIT 0x2 +#define P2PMANAGED_COEXIST_OPT_BIT 0x4 + +#define P2P_OPPS_BIT 0x80 + +/* + * Macros for bit check +*/ + +#define P2P_TEST_BIT(_M, _F) (((_M) & (_F)) != 0) + + + +/* Packet Format. */ +#define IE_P2P 0xdd + +typedef struct { + UCHAR OUI[3]; + UCHAR OUIType; + UCHAR Octet[1]; +} P2P_IE, *PP2P_IE; + +#define SIZE_OF_FIXED_CLIENT_INFO_DESC 25 + + + + +typedef struct _OID_P2P_PERSISTENT_TABLE +{ + UCHAR PerstNumber; /* What persistent profile is set ? */ + RT_P2P_PERSISTENT_ENTRY PerstEntry[MAX_P2P_TABLE_SIZE]; /* Save persistent profile for auto reconnect */ +} OID_P2P_PERSISTENT_TABLE, *POID_P2P_PERSISTENT_TABLE; + + + + + + +typedef struct { + UCHAR Eid; + UCHAR Len[2]; + CHAR Octet[1]; +} P2PEID_STRUCT,*PP2PEID_STRUCT; + + +#endif /* __P2P_H__ */ + + diff --git a/mt7620/src/include/p2p_cmm.h b/mt7620/src/include/p2p_cmm.h new file mode 100644 index 0000000..3c80720 --- /dev/null +++ b/mt7620/src/include/p2p_cmm.h @@ -0,0 +1,902 @@ +/**************************************************************************** + * 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 P2P_SUPPORT + + +#ifndef __P2P_CMM_H__ +#define __P2P_CMM_H__ + +#include "wfa_p2p.h" + +#ifndef GNU_PACKED +#define GNU_PACKED __attribute__ ((packed)) +#endif /* GNU_PACKED */ + + +/* Marco for interna use */ +#define P2P_INF_ON(_pAd) \ + (((_pAd)->flg_p2p_init) \ + && ((_pAd)->p2p_dev) \ + && (RtmpOSNetDevIsUp((_pAd)->p2p_dev) == TRUE)) + +#define IS_P2P_GO_NEG(_A) (((_A)->P2pCfg.P2PConnectState == P2P_ANY_IN_FORMATION_AS_CLIENT) || ((_A)->P2pCfg.P2PConnectState == P2P_ANY_IN_FORMATION_AS_GO)) + +#define IS_P2P_REGISTRA(_A) (((_A)->P2pCfg.P2PConnectState == P2P_WPS_REGISTRA)) +#define IS_P2P_ENROLLEE(_A) (((_A)->P2pCfg.P2PConnectState == P2P_DO_WPS_ENROLLEE)) +#define IS_P2P_PROVISIONING(_A) (IS_P2P_ENROLLEE(_A) || IS_P2P_REGISTRA(_A)) +/*#define IS_P2P_GO_WPA2PSKING(_A) ((_A)->P2pCfg.P2PConnectState == P2P_GO_ASSOC_AUTH) */ +/*#define IS_P2P_CLIENT_WPA2PSKING(_A) ((_A)->P2pCfg.P2PConnectState == P2P_I_AM_CLIENT_ASSOC_AUTH) */ + +/*#define IS_P2P_GO_OP(_A) (((_A)->P2pCfg.P2PConnectState >= P2P_I_AM_GO_OP)) */ +/*#define IS_P2P_CLIENT_OP(_A) (((_A)->P2pCfg.P2PConnectState == P2P_I_AM_CLIENT_OP)) */ +/*#define IS_P2P_OP(_A) (IS_P2P_GO_OP(_A) || IS_P2P_CLIENT_OP(_A)) */ + +#define IS_P2P_CONNECT_IDLE(_A) (((_A)->P2pCfg.P2PConnectState) == P2P_CONNECT_IDLE) +#define IS_P2P_CONNECTING(_A) (((_A)->P2pCfg.P2PConnectState) > P2P_CONNECT_IDLE) +#define IS_P2P_GO_NEGOING(_A) (((_A)->P2pCfg.P2PConnectState < P2P_DO_GO_SCAN_BEGIN) && ((_A)->P2pCfg.P2PConnectState > P2P_CONNECT_IDLE)) +#define IS_P2P_GROUP_FORMING(_A) (((_A)->P2pCfg.P2PConnectState <= P2P_WPS_REGISTRA) && ((_A)->P2pCfg.P2PConnectState > P2P_CONNECT_IDLE)) +#define IS_P2P_INVITING(_A) (((_A)->P2pCfg.P2PConnectState == P2P_INVITE)) +/* Check for Peer's State. */ +#define IS_P2P_PEER_CLIENT_OP(_C) (((_C)->P2pClientState <= P2PSTATE_CLIENT_FIND)&& ((_C)->P2pClientState >= P2PSTATE_CLIENT_OPERATING)) +#define IS_P2P_PEER_PROVISIONING(_C) (((_C)->P2pClientState == P2PSTATE_CLIENT_WPS)&& ((_C)->P2pClientState == P2PSTATE_GO_WPS)) +#define IS_P2P_PEER_WPAPSK(_C) (((_C)->P2pClientState <= P2PSTATE_CLIENT_ASSOC)&& ((_C)->P2pClientState >= P2PSTATE_CLIENT_AUTH)) +#define IS_P2P_PEER_GO_OP(_C) (((_C)->P2pClientState <= P2PSTATE_GO_FIND)&& ((_C)->P2pClientState >= P2PSTATE_GO_OPERATING)) +#define IS_P2P_PEER_OP(_C) ((IS_P2P_PEER_CLIENT_OP(_C)) || (IS_P2P_PEER_GO_OP(_C))) +#define IS_P2P_PEER_DISCOVERY(_C) (((_C)->P2pClientState <= P2PSTATE_DISCOVERY_CLIENT)&& ((_C)->P2pClientState >= P2PSTATE_DISCOVERY)) +#define IS_P2PPEER_CLIENT_GO_FORM(_C) (((_C)->P2pClientState <= P2PSTATE_GO_COMFIRM_ACK_SUCCESS)&& ((_C)->P2pClientState >= P2PSTATE_DISCOVERY)) + +/* P2P Control Reg. */ +#define IS_MANAGED_ON(_A) ((_A->P2pCfg.P2pControl.word & P2P_CONTROL_REG_MANAGED) != 0) +#define IS_PERSISTENT_ON(_A) ((_A->P2pCfg.P2pControl.word & P2P_CONTROL_REG_PERSISTENT) != 0) +#define IS_INVITE_ON(_A) ((_A->P2pCfg.P2pControl.word & P2P_CONTROL_REG_INVITE) != 0) +#define IS_INTRA_BSS_ON(_A) ((_A->P2pCfg.P2pControl.word & P2P_CONTROL_REG_INTRA_BSS) != 0) +#define IS_CLIENT_DISCOVERY_ON(_A) ((_A->P2pCfg.P2pControl.word & P2P_CONTROL_REG_CLI_DISCOVERY) != 0) +#define IS_EXT_LISTEN_ON(_A) ((_A->P2pCfg.P2pControl.word & P2P_CONTROL_REG_EXT_LISTEN) != 0) +#define IS_SERVICE_DISCOVERY_ON(_A) ((_A->P2pCfg.P2pControl.word & P2P_CONTROL_REG_SERVICE_DISCOVERY) != 0) +#define IS_OPPS_ON(_A) ((_A->P2pCfg.P2pControl.word & P2P_CONTROL_REG_OPPS) != 0) +#define IS_SW_NOA_TIMER(_A) ((_A->P2pCfg.P2pControl.word & P2P_CONTROL_REG_SW_NOA) != 0) +#define IS_P2P_SUPPORT_EXT_LISTEN(_A) (((_A)->P2pCfg.ExtListenInterval != 0) && ((_A)->P2pCfg.ExtListenPeriod != 0) && ((_A)->P2pCfg.P2pControl.field.ExtendListen == 1)) +#define IS_P2P_ABSENCE(_A) (((_A)->P2pCfg.bPreKeepSlient) || ((_A)->P2pCfg.bKeepSlient)) + +/* P2P Discovery State Machine. */ +#define IS_P2P_LISTEN(_pAd) \ + (_pAd->P2pCfg.DiscCurrentState == P2P_DISC_LISTEN) +#define IS_P2P_SEARCH(_pAd) \ + (_pAd->P2pCfg.DiscCurrentState == P2P_DISC_SEARCH) +#define IS_P2P_SCAN(_pAd) \ + (_pAd->P2pCfg.DiscCurrentState == P2P_DISC_SCAN) +#define IS_P2P_DEVICE_DISCOVERING(_pAd) \ + (_pAd->P2pCfg.CtrlCurrentState == P2P_CTRL_DISCOVERY) + +/* Definition */ +#define P2P_WSC_CONF_MTHD_DEFAULT(_pAd) \ + _pAd->P2pCfg.WscMode = WSC_PIN_MODE; \ + _pAd->P2pCfg.ConfigMethod = 0x188; \ + _pAd->P2pCfg.Dpid = DEV_PASS_ID_NOSPEC; + +/* + * P2P CTRL State machine: states, events, total function + */ +typedef enum _P2P_CTRL_STATE +{ + P2P_CTRL_IDLE, + P2P_CTRL_DISCOVERY, + P2P_CTRL_GROUP_FORMATION, + P2P_CTRL_DONE, + P2P_CTRL_MAX_STATES, +} P2P_CTRL_STATE; + +typedef enum _P2P_CTRL_EVENT +{ + P2P_CTRL_DISC_EVT, + P2P_CTRL_DISC_CANL_EVT, + P2P_CTRL_DISC_DONE_EVT, + P2P_CTRL_GO_BACK_TO_OP_CH_EVT, + P2P_CTRL_GO_NEGO_EVT, + P2P_CTRL_GO_NEGO_CANL_EVT, + P2P_CTRL_GO_NEGO_DONE_EVT, + P2P_CTRL_MAX_EVENTS, +} P2P_CTRL_EVENT; + +#define P2P_CTRL_FUNC_SIZE (P2P_CTRL_MAX_STATES * P2P_CTRL_MAX_EVENTS) + + +/* + * P2P DISC state machine: states, evvents, total function + */ +typedef enum _P2P_DISC_STATE +{ + P2P_DISC_IDLE, + P2P_DISC_SCAN, + P2P_DISC_LISTEN, + P2P_DISC_SEARCH, + P2P_DISC_MAX_STATES, +} P2P_DISC_STATE; + +typedef enum _P2P_DISC_EVENT +{ + P2P_DISC_SCAN_CMD_EVT, + P2P_DISC_LISTEN_CMD_EVT, + P2P_DISC_SEARCH_CMD_EVT, + P2P_DISC_CANL_CMD_EVT, + P2P_DISC_PEER_PROB_REQ, + P2P_DISC_PEER_PROB_RSP, + P2P_DISC_MAX_EVENTS, +} P2P_DISC_EVENT; + +#define P2P_DISC_FUNC_SIZE (P2P_DISC_MAX_STATES * P2P_DISC_MAX_EVENTS) + +/* + * P2P GO_FORM state machine: states, evvents, total function + */ +typedef enum _P2P_GO_FORM_STATE +{ + P2P_GO_FORM_IDLE, + P2P_WAIT_GO_FORM_RSP, + P2P_WAIT_GO_FORM_CONF, + P2P_GO_FORM_DONE, + P2P_GO_FORM_PROV, + P2P_WAIT_GO_FORM_PROV_RSP, + P2P_GO_FORM_INVITE, + P2P_WAIT_GO_FORM_INVITE_RSP, + P2P_WAIT_GO_FORM_DEV_DISC_RSP, + P2P_WAIT_GO_FORM_SRV_DISC_RSP, + P2P_GO_FORM_MAX_STATES, +} P2P_GO_FORM_STATE; + +typedef enum _P2P_GO_FORM_EVENT +{ + P2P_GO_NEGO_REQ_CMD_EVT, + P2P_PEER_GO_NEGO_REQ_EVT, + P2P_GO_NEGO_RSP_EVT, + P2P_PEER_GO_NEGO_RSP_EVT, + P2P_GO_NEGO_CONFIRM_EVT, + P2P_PEER_GO_NEGO_CONFIRM_EVT, + P2P_GO_NEGO_PROV_REQ_CMD_EVT, + P2P_PEER_GO_NEGO_PROV_REQ_EVT, + P2P_GO_NEGO_PROV_RSP_EVT, + P2P_PEER_GO_NEGO_PROV_RSP_EVT, + P2P_GO_NEGO_CANCEL_EVT, + P2P_PEER_INVITE_REQ_EVT, + P2P_PEER_INVITE_RSP_EVT, + P2P_DEV_DISC_REQ_CMD_EVT, + P2P_PEER_DEV_DISC_REQ_EVT, + P2P_DEV_DISC_RSP_EVT, + P2P_PEER_DEV_DISC_RSP_EVT, + P2P_START_COMMUNICATE_CMD_EVT, + P2P_SEND_PASSED_CMD_EVT, + P2P_GO_NEGO_MAX_EVENTS, +} P2P_GO_FORM_EVENT; + +typedef enum _P2P_LINK_DOWN_TYPE +{ + P2P_DISCONNECTED, + P2P_CONNECT_FAIL, +} P2P_LINK_DOWN_TYPE; + +#define P2P_GO_FORM_FUNC_SIZE (P2P_GO_FORM_MAX_STATES * P2P_GO_NEGO_MAX_EVENTS) + +/* + * P2P state machine: states, events, total function # + */ +#define MT2_MAX_PEER_SUPPORT 3 +typedef enum _P2P_ACTION_STATE +{ + P2P_IDLE_STATE, + MAX_P2P_STATE, +} P2P_ACTION_STATE; + +typedef enum _P2P_ACTION_EVENT +{ + MT2_PEER_P2P_NOA, + MT2_PEER_P2P_PRESENCE_REQ, + MT2_PEER_P2P_PRESENCE_RSP, + MT2_PEER_P2P_GO_DIS_REQ, + MT2_MLME_P2P_NOA, + MT2_MLME_P2P_PRESENCE_REQ, + MT2_MLME_P2P_PRESENCE_RSP, + MT2_MLME_P2P_GO_DIS_REQ, + MT2_MLME_P2P_GAS_INT_REQ, + MT2_MLME_P2P_GAS_INT_RSP, + MT2_MLME_P2P_GAS_CB_REQ, + MT2_MLME_P2P_GAS_CB_RSP, + MAX_P2P_MSG, +} P2P_ACTION_EVENT; + +#define P2P_ACTION_FUNC_SIZE (MAX_P2P_STATE * MAX_P2P_MSG) + + +/* ----- General ----- */ + +/* P2P Oprtation Mode */ +#define P2P_ONLY (1<<0) /* STA or P2P in single interface */ +#define P2P_CONCURRENT (1<<1) /* STA and P2P in different interface */ + +#define P2P_IS_GO 1 +#define P2P_IS_CLIENT 2 +#define P2P_IS_DEVICE 3 +#define P2P_IS_CLIENT_IN_GROUP 4 + +#define P2P_SET_FLAG(_M, _F) ((_M)->P2pFlag |= (_F)) +#define P2P_CLEAR_FLAG(_M, _F) ((_M)->P2pFlag &= ~(_F)) +#define P2P_TEST_FLAG(_M, _F) (((_M)->P2pFlag & (_F)) != 0) +#define P2P_TEST_FLAGS(_M, _F) (((_M)->P2pFlag & (_F)) == (_F)) + + +#define P2PFLAG_PROVISIONED 0x01 +#define P2PFLAG_INVITE_ENABLED 0x02 +#define P2PFLAG_DEVICE_DISCOVERABLE 0x04 + +#define P2P_OUI 0x099a6f50 /* spec. P2P OUI */ +#define P2P_RANDOM_BASE 35 /*; 3 second. */ +#define P2P_RANDOM_WPS_BASE 10 /*; 5 second. */ +#define P2P_RANDOM_BIAS 10 /*; 2 second. */ +#define P2P_RANDOM_PERST_BIAS 60 /*; 2 second. */ +#define P2P_SCAN_CHANNEL_STEP 11 +#define P2P_SCAN_PERIOD 1800 /* unit : 100ms. Scan period how long ? 2min ? */ +#define P2P_SCAN_SHORTPERIOD 100 /* unit : 100ms. Scan period how long ? 2min ? */ +#define P2P_EXT_LISTEN_INTERVAL 4000 /* unit is 1ms */ +#define P2P_EXT_LISTEN_PERIOD 1000 /* unit is 1ms */ + +#define P2P_CHECK_GO_TIMER 300000 /* 3 minutes */ +#define P2P_CHECK_CLIENT_TIMER 30000 /* 30 seconds */ +#define P2P_WSC_TIMER 120000 /* 120 seconds */ +#define P2P_TRANSMIT_TIMER 500 /* 500 ms */ + + +#define ONETU 100 + +/* P2P Tab index */ +#define P2P_NOT_FOUND 0xFF + +#define MINOR_REASON_SUCCESS 0 +#define MINOR_REASON_CROSS_CONNECT 1 +#define MINOR_REASON_MANAGED_BIT_ZERO 2 +#define MINOR_REASON_COEXIST_PARM_BAD 3 +#define MINOR_REASON_MANAGED_BIT_ONE 4 + + +/* Invittion Flags */ +#define P2P_INVITE_FLAG_REINVOKE 1 + + +#define GROUP_MODE_TEMP 1 +#define GROUP_MODE_PERSISTENT 2 +#define MAX_P2P_GROUP_SIZE 30 /* Max mactab size(32) - 2 */ +#define MAX_P2P_TABLE_SIZE 8 /* Save Presistent entry */ +#define PROFILE_P2P 1 +#define PROFILE_WPSE 2 +#define P2P_DEVICE_TYPE_LEN 8 +#define P2P_DEVICE_NAME_LEN 32 + +/* Describe the peer's state when I am performing P2P Operation with the peer. */ +typedef enum _P2pClientState +{ + P2PSTATE_NONE, + P2PSTATE_DISCOVERY, /* Not associated. Because need to get SSID from Probe Response. So add this state. */ + P2PSTATE_DISCOVERY_GO, /* this device is a GO. has beacon */ + P2PSTATE_DISCOVERY_CLIENT, /* this device is a client that associates with a GO. (in a p2p group.) */ + P2PSTATE_DISCOVERY_UNKNOWN, /* Need to scan to decide this peer's rule is GO or Client or Device. */ + P2PSTATE_CLIENT_DISCO_COMMAND, /* Do Client Discovery. */ + P2PSTATE_WAIT_GO_DISCO_ACK, /* Do Client Discovery. */ + P2PSTATE_WAIT_GO_DISCO_ACK_SUCCESS, /* Do Client Discovery. */ + P2PSTATE_GO_DISCO_COMMAND, /* Need to send to this GO when doing Client Discovery */ + P2PSTATE_INVITE_COMMAND, /* Wait to send Invite Req. */ + P2PSTATE_CONNECT_COMMAND, /* wait to send Go Nego Req. */ + P2PSTATE_PROVISION_COMMAND, /* Provision first, then connect. */ + P2PSTATE_SERVICE_DISCO_COMMAND, /* Do Service Discovery. */ + P2PSTATE_SERVICE_COMEBACK_COMMAND, /* Do Service Discovery. */ + P2PSTATE_SENT_INVITE_REQ, + P2PSTATE_SENT_PROVISION_REQ, + P2PSTATE_SENT_PROVISION_RSP, + P2PSTATE_WAIT_REVOKEINVITE_RSP_ACK, /* 15 */ + P2PSTATE_REVOKEINVITE_RSP_ACK_SUCCESS, + P2PSTATE_SENT_GO_NEG_REQ, + P2PSTATE_GOT_GO_RSP_INFO_UNAVAI, /* got GO Nego Rsp with Status : information unavailable. Still need 120 sec more to time out. */ + P2PSTATE_WAIT_GO_COMFIRM, + P2PSTATE_WAIT_GO_COMFIRM_ACK, + P2PSTATE_GOT_GO_COMFIRM, + P2PSTATE_GO_COMFIRM_ACK_SUCCESS, + P2PSTATE_REINVOKEINVITE_TILLCONFIGTIME, + P2PSTATE_GO_DONE, + P2PSTATE_GO_WPS, /* Internal registra */ + P2PSTATE_GO_AUTH, + P2PSTATE_GO_ASSOC, /*30 */ + P2PSTATE_CLIENT_WPS, /* Enrollee */ + P2PSTATE_CLIENT_WPS_DONE, /* Enrollee */ + P2PSTATE_CLIENT_AUTH, + P2PSTATE_CLIENT_ASSOC, + P2PSTATE_CLIENT_OPERATING, /* 35 */ + P2PSTATE_CLIENT_ABSENCE, + P2PSTATE_CLIENT_SCAN, /* Already in P2P group, but go to scan phase. */ + P2PSTATE_CLIENT_FIND, /* Already in P2P group, but go to find phase. */ + P2PSTATE_GO_OPERATING, + P2PSTATE_GO_ABSENCE, /*During absence period. */ + P2PSTATE_GO_SCAN, /* Already in P2P group, but go to scan phase. */ + P2PSTATE_GO_FIND, /* Already in P2P group, but go to find phase. */ + /* Go can support legacy station not use WiFi Direct Spec to connect to. Assign following 2 states to such client. */ + P2PSTATE_NONP2P_PSK, /* legacy client that uses WPA2PSK-AES to connect to GO(me). */ + P2PSTATE_NONP2P_WPS, /* Legacy client that uses WPS to connect to GO(me). */ + P2PSTATE_MAX_STATE, +} P2P_CLIENT_STATE; + +typedef VOID (*p2p_cmd_handler) (VOID *pAD, VOID *pElem); +typedef struct _P2P_CMD_STRUCT +{ + UCHAR Addr[MAC_ADDR_LEN]; + UCHAR Idx; + /*USHORT ConfigMethod; */ + +} P2P_CMD_STRUCT, *PP2P_CMD_STRUCT; + +/* Describe the current discovery state and provistioning state if WifI direct is enabled. */ +typedef enum _P2pDiscoProvState +{ + P2P_DISABLE, + P2P_ENABLE_LISTEN_ONLY, /* In this state, only reponse to P2P Probe req. that has P2P IE. enable listen mode. */ +/* P2P_IDLE, */ +/* P2P_SEARCH_COMMAND, */ /* 5 */ + P2P_SCAN, + P2P_SEARCH, /* 6 */ +/* P2P_SEARCH_COMPLETE, */ +/* P2P_LISTEN_COMMAND, */ + P2P_LISTEN, /* 9 */ +/* P2P_LISTEN_COMPLETE, */ +/* P2PGO_SEARCH, */ /* I am alreayd an GO, But go to other listen channel perform search */ +/* P2PGO_SEARCH_COMMAND, */ /* go to other listen channel perform search */ + P2P_MAX_DISC_STATE, +} P2P_DISCOPROV_STATE; + +/* Describe the current state when performing P2P Operation. */ +typedef enum _P2pConnectState +{ + P2P_CONNECT_NOUSE, + P2P_CONNECT_IDLE = 13, /* Set to bigger number, so don't overlap with P2P_DISCOPROV_STATE */ + P2P_INVITE, + P2P_ANY_IN_FORMATION_AS_GO, /* 15 */ + P2P_ANY_IN_FORMATION_AS_CLIENT, + P2P_DO_GO_NEG_DONE_CLIENT, /* 17 */ + P2P_DO_GO_SCAN_OP_BEGIN, /* 18 */ + P2P_DO_GO_SCAN_OP_DONE, /* 19 */ + P2P_DO_GO_SCAN_BEGIN, + P2P_DO_GO_SCAN_DONE, + P2P_WPS_REGISTRA, /* 22 */ + P2P_DO_WPS_ENROLLEE, +/* P2P_DO_WPS_ENROLLEE_DONE, */ +/* P2P_GO_ASSOC_AUTH, */ +/* P2P_I_AM_CLIENT_ASSOC_AUTH, */ +/* P2P_I_AM_CLIENT_OP, */ /* 27 I am operating as client */ +/* P2P_I_AM_GO_OP, */ /* 28 I am operatin as Go. */ +/* P2PGO_DO_WPS_REGISTRA, */ /* 29 */ +/* P2PGO_I_AM_GO_ASSOC_AUTH, */ +} P2P_CONNECT_STATE; + + + +#define CONFIG_MODE_DISABLE_P2P_WPSE 0 /* Uncheck "enable WFD feature" #define CONFIG_MODE_DISABLE_WIFI_DIRECT_WPSE 0 */ +#define CONFIG_MODE_ENABLE_P2P 1 /* set device name to driver when check "enable WFD feature" */ +#define CONFIG_MODE_P2P_SCAN 2 /* set device name to driver when press "Scan" */ +#define CONFIG_MODE_CONNECT_P2P 3 /* set all config (RTMP_WIFI_DIRECT_CONFIG) to driver #define CONFIG_MODE_ACTIVATE_WIFI_DIRECT 1 */ +#define CONFIG_MODE_ACTIVATE_WPSE 4 /* #define CONFIG_MODE_ACTIVATE_WPSE 2 */ +#define CONFIG_MODE_DELETE_ACTIVE_P2P 5 /* set to actived config (RTMP_WIFI_DIRECT_CONFIG) to driver (driver will send disconnect event and clean persistent table ) #define CONFIG_MODE_DELETE_ACTIVED_WIFI_DIRECT 3 */ +#define CONFIG_MODE_DISCONNECT_P2P 6 /* do nothing in UI when press "Disconnect" #define CONFIG_MODE_DISCONNECT_WIFI_DIRECT 4 */ +#define CONFIG_MODE_DELETE_PERST_P2P 7 /* set inactive but persistent config (RTMP_WIFI_DIRECT_CONFIG) to driver when delete perseistent profile from profile list #define CONFIG_MODE_DELETE_PERST_WIFI_DIRECT 5 */ +#define CONFIG_MODE_PROVISION_THIS 8 /* */ +#define CONFIG_MODE_SET_GO_WPS 9 /* When I am GO. Set WPS for indivial client. */ +#define CONFIG_MODE_SERVICE_DISCOVERY 10 /* Start SErvice Discovery */ + +#define P2P_PHYMODE_LEGACY_ONLY 0 +#define P2P_PHYMODE_ENABLE_11N_20 1 +#define P2P_PHYMODE_ENABLE_11N_40 2 + +#define P2P_GROUP_MODE_TEMP 1 +#define P2P_GROUP_MODE_PERSISTENT 2 + +#define P2P_WPSE_PIN_METHOD 0x10000000 +#define P2P_WPSE_PBC_METHOD 0x20000000 +#define P2P_WPSE_SMPBC_METHOD 0x30000000 + +#define RALINKOUIMODE_IPREQ 0x30 +#define RALINKOUIMODE_IPRSP 0x31 +#define RALINKOUIMODE_MBRIPRSP 0x32 /* Group Member ip notify */ + +/*define P2P_REG_CM_LABEL 1 */ /* Default I broadcast my config method is label. (DefaultConfigMethod:2) */ +#define P2P_REG_CM_DISPLAY 1 /* Default I broadcast my config method is display. */ +#define P2P_REG_CM_KEYPAD 2 /* Default I broadcast my config method is keypad. */ +#define P2P_REG_CM_PBC 3 /* Default I broadcast my config method is pbc. (DefaultConfigMethod:2) */ + +/* WSC connection mode */ +/*define WSC_PIN_MODE 0x10000000 */ /* Default PIN */ +/*define WSC_PBC_MODE 0x20000000 */ +#define WSC_PIN_MODE_USER_SPEC 0x40000000 +#define WSC_PIN_MODE_REGISTRA_SPEC 0x80000000 + +#define P2P_CONTROL_REG_ENABLE 0x00000001 +#define P2P_CONTROL_REG_MANAGED 0x00000002 +#define P2P_CONTROL_REG_PERSISTENT 0x00000004 +#define P2P_CONTROL_REG_INVITE 0x00000008 +#define P2P_CONTROL_REG_INTENT 0x000000F0 +#define P2P_CONTROL_REG_LISTEN_CHANNEL 0x00000F00 +#define P2P_CONTROL_REG_CONFIG_MHD 0x00007000 +#define P2P_CONTROL_REG_INTRA_BSS 0x00008000 +#define P2P_CONTROL_REG_OP_CHANNEL 0x000F0000 +#define P2P_CONTROL_REG_CLI_DISCOVERY 0x00100000 +#define P2P_CONTROL_REG_EXT_LISTEN 0x00200000 +#define P2P_CONTROL_REG_SERVICE_DISCOVERY 0x00400000 +#define P2P_CONTROL_REG_OPPS 0x00800000 +#define P2P_CONTROL_REG_GROUP_LIMIT 0x01000000 +#define P2P_CONTROL_REG_DISABLE_CRS_CONN 0x02000000 +#define P2P_CONTROL_REG_SW_NOA 0x80000000 + +/* key information */ +typedef union { + struct { + /* 1 */ + ULONG Enable:1; /* Enable WiFi Direct. */ + ULONG Managed:1; /* Support Managed AP */ + ULONG EnablePresistent:1; /* Enable persistent */ + ULONG EnableInvite:1; /* For invitation Test Case. */ + /* 2 */ + ULONG DefaultIntentIndex:4; /* the default intent index GUI used when first editing a profile. */ + /* 3 */ + ULONG ListenChannel:4; /* Listen Channel */ + /* 4 */ + ULONG DefaultConfigMethod:3; /* Default Config Method that is set in Probe Rsp when P2P On. */ + ULONG EnableIntraBss:1; /* 1: Enable Intra BSS function when I am GO */ + /* 5 */ + ULONG OpChannel:4; /* default use 2.4GHz channel */ + /* 6 */ + ULONG ClientDiscovery:1; /* Client Discoverbility */ + ULONG ExtendListen:1; /* Extended Listening */ + ULONG ServiceDiscovery:1; /* Service Discovery */ + ULONG OpPSAlwaysOn:1; /* Service Discovery */ + /* 7 */ + ULONG P2PGroupLimit:1; /* When Limit == 1. GO only support ONE device in my group.. */ + ULONG ForceDisableCrossConnect:1; + ULONG Rsvd:5; /* Not Used */ + ULONG SwBasedNoA:1; /* Software Based NoA implementation */ + } field; + UINT32 word; +} P2P_CONTROL, *PP2P_CONTROL; + + +/* + * The miniport PORT structure + */ +typedef struct _PORT_COMMON_CONFIG +{ + ULONG OpStatusFlags; + ULONG OperationMode; /* DOT11_OPERATION_MODE_EXTENSIBLE_STATION or DOT11_OPERATION_MODE_NETWORK_MONITOR */ + UCHAR Bssid[MAC_ADDR_LEN]; + 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 Channel; */ + /*UCHAR CentralChannel; */ /* Central Channel when using 40MHz is indicating. not real channel. */ + + ULONG AuthMode; /* This should match to whatever microsoft defined, use ULONG Intead of DOT11_AUTH_ALGORITHM. */ + ULONG WepStatus; /*use ULONG intead of DOT11_CIPHER_ALGORITHM, */ + UCHAR DefaultKeyId; + + ULONG OrigWepStatus; /* Original wep status set from OID */ + /* Add to support different cipher suite for WPA2/WPA mode */ + ULONG GroupCipher; /* Multicast cipher suite */ + ULONG PairCipher; /* Unicast cipher suite */ + UCHAR CipherAlg; + NDIS_802_11_WEP_STATUS GroupKeyWepStatus; +/* RT_802_11_CIPHER_SUITE_TYPE MixedModeGroupCipher; */ /* for WPA+WEP mixed mode, and CCKM WEP */ + BOOLEAN bMixCipher; /* Indicate current Pair & Group use different cipher suites */ + USHORT RsnCapability; + ULONG MulticastCipherAlgorithmCount; + ULONG PacketFilter; /* Packet filter for receiving */ + + UINT MCAddressCount; +/* UCHAR MCAddressList[HW_MAX_MCAST_LIST_SIZE][DOT11_ADDRESS_SIZE]; */ + + BOOLEAN bHiddenNetworkEnabled; + BOOLEAN ExcludeUnencrypted; + + ULONG OperatingPhyId; /* ID of currently operating PHY */ + ULONG SelectedPhyId; /* index of PHY that any PHY specific OID is applied to */ + ULONG DefaultPhyId; +}PORT_COMMON_CONFIG,*PPORT_COMMON_CONFIG; + +typedef struct _P2P_COUNTER_STRUCT +{ + ULONG ManageAPEnReconCounter; /* right after shutdown, */ + ULONG ClientConnectedCounter; /* If I am P2P Client and is connected, */ + ULONG DisableRetryGrpFormCounter; /* If Group Nego is rejected because both intent is 15. can't retry in a short time. */ + ULONG Counter100ms; /* plus 1 every 100ms */ + ULONG GoScanBeginCounter100ms; + ULONG Wpa2pskCounter100ms; + ULONG NextScanRound; /* Unit : 100 TU */ + UCHAR ListenInterval; /* Unit : 100 TU */ + UCHAR ListenIntervalBias; /* for some important action that need more dwell time in scan channel, add this Bias. Unit : 100 TU */ + ULONG CounterAftrScanButton; /* Unit 100ms. Counter for After Pressing "Apply" Profile button. */ + ULONG CounterAftrSetEvent; /* Unit 100ms. Counter for Driver called KeSetEvent. */ + BOOLEAN bListen; + BOOLEAN bStartScan; + BOOLEAN bNextScan; + ULONG UserAccept; +} P2P_COUNTER_STRUCT, *PP2P_COUNTER_STRUCT; + +typedef struct _P2P_RALINK_STRUCT +{ + UCHAR ListenChanel[3]; + UCHAR ListenChanelIndex; + UCHAR ListenChanelCount; +} P2P_RALINK_STRUCT, *PP2P_RALINK_STRUCT; + +/* often need to change beacon content. So save the offset. */ +typedef struct _P2P_BEACONOFFSET_STRUCT +{ + ULONG IpBitmapBcnOffset; /* USed as GO */ + ULONG P2pCapOffset; +} P2P_BEACONOFFSET_STRUCT, *PP2P_BEACONOFFSET_STRUCT; + +typedef struct _P2P_SAVED_PUBLIC_FRAME { + HEADER_802_11 p80211Header; + UCHAR Category; + UCHAR Action; + UCHAR OUI[3]; + UCHAR OUIType; + UCHAR Subtype; + UCHAR Token; +} P2P_SAVED_PUBLIC_FRAME, *PP2P_SAVED_PUBLIC_FRAME; + +typedef struct _P2P_MANAGED_STRUCT +{ + UCHAR ManageAPBSsid[MAC_ADDR_LEN]; /* Store the AP's BSSID that is the managed AP and is the latest one that I recently connected to.. */ + UCHAR ManageAPSsid[32]; /* Store the AP's BSSID that is the managed AP and is the latest one that I recently connected to.. */ + UCHAR ManageAPSsidLen; /* Store the AP's BSSID that is the managed AP and is the latest one that I recently connected to.. */ + UCHAR APP2pManageability; /* Store the AP's P2P Manageability byte that currently I want to associate. */ + UCHAR APP2pMinorReason; /* Store the AP's minorreason byte that recently being deauthed */ + UCHAR ICSStatus; /* */ + UCHAR APUsageChannel; /* The suggest channel from AP's IE=0x61 */ + UCHAR TotalNumOfP2pAttribute; +} P2P_MANAGED_STRUCT, *PP2P_MANAGED_STRUCT; + +typedef struct _P2PCLIENT_NOA_SCHEDULE { + BOOLEAN bValid; + BOOLEAN bInAwake; + BOOLEAN bNeedResumeNoA; /* Set to TRUE if need to restart infinite NoA */ + BOOLEAN bWMMPSInAbsent; /* Set to TRUE if enter GO absent period by supported UAPSD GO */ + 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; + ULONG NextTimePointForWMMPSCounting; /* fro counting WMM PS EOSP bit. Not used for NoA implementation. */ + 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 TsfHighByte; + ULONG ThreToWrapAround; + ULONG LastBeaconTimeStamp; +} P2PCLIENT_NOA_SCHEDULE, *PP2PCLIENT_NOA_SCHEDULE; + +typedef struct { + UCHAR Length; + UCHAR DevAddr[MAC_ADDR_LEN]; + UCHAR InterfaceAddr[MAC_ADDR_LEN]; + UCHAR Capability; + UCHAR ConfigMethod[2]; + UCHAR PrimaryDevType[P2P_DEVICE_TYPE_LEN]; + UCHAR NumSecondaryType; + UCHAR Octet[1]; +} P2P_CLIENT_INFO_DESC, *PP2P_CLIENT_INFO_DESC; + +/* Save for "Persistent" P2P table. Temporary P2P doesn't need to save in the table. */ +typedef struct _RT_P2P_PERSISTENT_ENTRY +{ + BOOLEAN bValid; + UCHAR MyRule; /* My rule is GO or Client */ + UCHAR Addr[MAC_ADDR_LEN]; /* this addr is to distinguish this persistent entry is for which mac addr */ + WSC_CREDENTIAL Profile; /* profile's bssid is always the GO's bssid. */ +} RT_P2P_PERSISTENT_ENTRY, *PRT_P2P_PERSISTENT_ENTRY; + +typedef struct _P2P_ETHER_ADDR +{ + UCHAR octet[MAC_ADDR_LEN]; +} P2P_ETHER_ADDR, *PP2P_ETHER_ADDR; + +typedef struct _P2P_PEER_SSID +{ + UCHAR ssid[32+1]; +} P2P_PEER_SSID, *PP2P_PEER_SSID; + +typedef struct _P2P_PEER_DEV_TYPE +{ + UCHAR dev_type; +} P2P_PEER_DEV_TYPE, *PP2P_PEER_DEV_TYPE; + +typedef struct _P2P_STA_ASSOC_LIST +{ + P2P_ETHER_ADDR maclist[3]; + UINT maclist_count; + P2P_PEER_SSID device_name[3]; + P2P_PEER_DEV_TYPE device_type[3]; + BOOLEAN is_p2p[3]; +} P2P_STA_ASSOC_LIST, *PP2P_STA_ASSOC_LIST; + +/* Store for persistent P2P group */ +typedef struct _RT_P2P_CONFIG +{ +/* PNET_DEV dev; */ + UCHAR P2p_OpMode; + UCHAR CurrentAddress[ETH_LENGTH_OF_ADDRESS]; + P2P_CTRL_STATE CtrlCurrentState; + STATE_MACHINE P2PCtrlMachine; + STATE_MACHINE_FUNC P2PCtrlFunc[P2P_CTRL_FUNC_SIZE]; + P2P_DISC_STATE DiscCurrentState; + STATE_MACHINE P2PDiscMachine; + STATE_MACHINE_FUNC P2PDiscFunc[P2P_DISC_FUNC_SIZE]; + P2P_GO_FORM_STATE GoFormCurrentState; + STATE_MACHINE P2PGoFormMachine; + STATE_MACHINE_FUNC P2PGoFormFunc[P2P_GO_FORM_FUNC_SIZE]; + P2P_ACTION_STATE ActionState; + STATE_MACHINE P2PActionMachine; + STATE_MACHINE_FUNC P2PActionFunc[P2P_ACTION_FUNC_SIZE]; + UCHAR Rule; /* Device / Client / GO. */ + + +/* P2P_DISCOPROV_STATE P2PDiscoProvState; */ /* P2P State for P2P discovery(listen, scan, search) and P2P provistioning (Service provision, wps provision) */ + P2P_CONNECT_STATE P2PConnectState; /* P2P State for P2P connection. */ +/* P2P_EVENTQUEUE_STRUCT P2pEventQueue; */ + P2P_COUNTER_STRUCT P2pCounter; + P2P_RALINK_STRUCT P2pProprietary; /* Ralink Proprietary to improve usage. */ + P2P_BEACONOFFSET_STRUCT P2pBcnOffset; + P2P_SAVED_PUBLIC_FRAME LatestP2pPublicFrame; /* Latest received P2P Public frame */ + P2P_MANAGED_STRUCT P2pManagedParm; + + BOOLEAN bFirstTimeCancelOpps; + BOOLEAN bPreKeepSlient; + BOOLEAN bKeepSlient; + UCHAR MyGOwcid; + UCHAR LastSentInviteFlag; + UCHAR P2pCapability[2]; + ULONG MyIp; + WSC_DEV_INFO DevInfo; + UCHAR Wsc_Uuid_E[UUID_LEN_STR]; + UCHAR Wsc_Uuid_Str[UUID_LEN_STR]; + ULONG WscMode; /* predefined WSC mode, 1: PIN, 2: PBC */ + BOOLEAN bConfiguredAP; /* true (1:un-configured), false(2: configured) ; used by GO */ + USHORT Dpid; /* WPS device password ID. */ + USHORT ConfigMethod; /* WPS device password ID. */ + UCHAR PinCode[9]; + UCHAR ConfigTimeout[2]; + UCHAR AssocPriDeviceType[8]; + UCHAR PhraseKey[64]; + UCHAR PhraseKeyLen; + P2P_STA_ASSOC_LIST AssocList; + UCHAR P2pPhyMode; + UCHAR NoAIndex; + UCHAR PopUpIndex; /* store the p2p entry index when receiving Go Nego Req and need a GUI to pop up a window to set connection. */ + UCHAR ConnectingIndex; /* Point to the ?rd Connecting MAC that I will try to connect with. */ + UCHAR ConnectingMAC[MAC_ADDR_LEN]; /* Specify MAC address want to connect. Set to all 0xff or all 0x0 if not specified. */ + UCHAR ConnectingDeviceName[MAX_P2P_GROUP_SIZE][32]; /* Specify the Device Name that want to connect. Set to all 0xff or all 0x0 if not specified. */ + UCHAR SSID[32]; + UCHAR SSIDLen; + UCHAR Token; + UCHAR p2pidxForServiceCbReq; + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR DeviceName[32]; + ULONG DeviceNameLen; + UCHAR ListenChannel; /* The channel that perform the group formatuib oricedure. */ + UCHAR GroupChannel; /* Group setting channel from GUI. Real OP channel need to be negociated.. */ + UCHAR GroupOpChannel; /* Group operating channel. */ + UCHAR GoIntentIdx; /* Value = 0~15. Intent to be a GO in P2P */ + BOOLEAN bIntraBss; + BOOLEAN bExtListen; + USHORT ExtListenPeriod; /* Period for extended listening */ + USHORT ExtListenInterval; /* Interval for extended listening */ + UCHAR CTWindows; /* CTWindows and OppPS parameter field */ + ULONG GOBeaconBufWscLen; + UCHAR LastConfigMode; /* Disable, activate p2p, or activate WPSE, or delete p2p profile. */ + + P2PCLIENT_NOA_SCHEDULE GONoASchedule; + RALINK_TIMER_STRUCT P2pCTWindowTimer; + RALINK_TIMER_STRUCT P2pSwNoATimer; + RALINK_TIMER_STRUCT P2pPreAbsenTimer; + RALINK_TIMER_STRUCT P2pWscTimer; + RALINK_TIMER_STRUCT P2pReSendTimer; + BOOLEAN bP2pReSendTimerRunning; + RALINK_TIMER_STRUCT P2pCliReConnectTimer; + BOOLEAN bP2pCliReConnectTimerRunning; + + PORT_COMMON_CONFIG PortCfg; + UCHAR DefaultConfigMethod; + P2P_CONTROL P2pControl; + INT WscState; + BOOLEAN bSigmaEnabled; + BOOLEAN bP2pCliPmEnable; + BOOLEAN bLowRateQoSNULL; + BOOLEAN bP2pCliReConnect; + BOOLEAN bStopAuthRsp; + ULONG DevDiscPeriod; /* Unit 100ms */ + BOOLEAN bPeriodicListen; + BOOLEAN bConfirmByUI; + + BOOLEAN bProvAutoRsp; + UCHAR P2pProvIndex; + USHORT P2pProvConfigMethod; + UCHAR P2pProvToken; + BOOLEAN P2pProvUserNotify; + PUCHAR pGoNegoRspOutBuffer; + BOOLEAN bSentProbeRSP; + +} RT_P2P_CONFIG, *PRT_P2P_CONFIG; + +typedef struct _RT_P2P_CLIENT_ENTRY +{ + P2P_CLIENT_STATE P2pClientState; /* From the state, can know peer it registra or enrollee. */ + UCHAR MyGOIndex; /* If this device is a client in a P2P group, then this is its GO's table index. */ + ULONG Peerip; + CHAR Dbm; + UCHAR P2pFlag; + UCHAR NoAToken; + UCHAR GeneralToken; + UCHAR StateCount; + UCHAR Rule; + UCHAR DevCapability; /* table 10 */ + UCHAR GroupCapability; + USHORT ConfigMethod; + UCHAR PIN[8]; + USHORT Dpid; + UCHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SsidLen; + UCHAR GoIntent; + UCHAR addr[MAC_ADDR_LEN]; + UCHAR InterfaceAddr[MAC_ADDR_LEN]; + UCHAR bssid[MAC_ADDR_LEN]; + UCHAR PrimaryDevType[P2P_DEVICE_TYPE_LEN]; + UCHAR NumSecondaryType; + UCHAR SecondaryDevType[P2P_DEVICE_TYPE_LEN]; + UCHAR RegClass; + UCHAR ChannelNr; + UCHAR OpChannel; + UCHAR DeviceName[P2P_DEVICE_NAME_LEN]; + ULONG DeviceNameLen; + UCHAR ConfigTimeOut; + UCHAR ListenChannel; + ULONG WscMode; + USHORT ExtListenPeriod; /* Period for extended listening */ + USHORT ExtListenInterval; /* Interval for extended listening */ + UCHAR CTWindow; /* As GO, Store client's Presence request NoA. As Client, Store GO's NoA In beacon or P2P Action frame */ + BOOLEAN bValid; + 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 */ + CHAR Rssi; +#ifdef DPA_S + UCHAR SameRxTimeCount; + ULONG LastRxTimeA; /* OS's timestamp */ + ULONG LastRxTime; /* OS's timestamp */ +#endif /* DPA_S */ + ULONG ReTransmitCnt; + UCHAR Token; +} RT_P2P_CLIENT_ENTRY, *PRT_P2P_CLIENT_ENTRY; + +typedef struct _P2P_ENTRY_PARM +{ + P2P_CLIENT_STATE P2pClientState; /* From the state, can know peer it registra or enrollee. */ + UCHAR P2pFlag; + UCHAR NoAToken; + UCHAR GeneralToken; + UCHAR DevCapability; /* table 10 */ + UCHAR GroupCapability; /* */ + UCHAR DevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ + UCHAR InterfaceAddr[MAC_ADDR_LEN]; + UCHAR PrimaryDevType[P2P_DEVICE_TYPE_LEN]; + UCHAR NumSecondaryType; + UCHAR SecondaryDevType[P2P_DEVICE_TYPE_LEN]; /* This definition only support save one 2ndary DevType */ + UCHAR DeviceName[32]; + ULONG DeviceNameLen; + USHORT ConfigMethod; +/* USHORT ExtListenPeriod; */ /* Period for extended listening */ +/* USHORT ExtListenInterval; */ /* Interval for extended listening */ + 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 */ + UCHAR p2pIndex; +}P2P_ENTRY_PARM, *PP2P_ENTRY_PARM; + +/* Save for "Persistent" P2P table. Temporary P2P doesn't need to save in the table. */ +typedef struct _RT_GO_CREDENTIAL_ENTRY +{ + BOOLEAN bValid; + UCHAR InterAddr[MAC_ADDR_LEN]; /* this addr is to distinguish this persistent entry is for which mac addr */ + WSC_CREDENTIAL Profile; /* profile's bssid is always the GO's bssid. */ +} RT_GO_CREDENTIAL_ENTRY, *PRT_GO_CREDENTIAL_ENTRY; + +/* Store for persistent P2P group */ +typedef struct _RT_P2P_TABLE +{ + UCHAR PerstNumber; /* What persistent profile is set ? */ + UCHAR ClientNumber; /* What clients are in my group now? */ + RT_P2P_PERSISTENT_ENTRY PerstEntry[MAX_P2P_TABLE_SIZE]; /* Save persistent profile for auto reconnect */ + RT_P2P_CLIENT_ENTRY Client[MAX_P2P_GROUP_SIZE]; /* Store for current group member. */ + RT_GO_CREDENTIAL_ENTRY TempCredential[2/*MAX_P2P_SAVECREDN_SIZE*/]; +} RT_P2P_TABLE, *PRT_P2P_TABLE; + +typedef struct _RT_P2P_UI_TABLE +{ + UCHAR ClientNumber; /* What clients are in my group now? */ + RT_P2P_CLIENT_ENTRY Client[MAX_P2P_GROUP_SIZE]; /* Store for current group member. */ +} RT_P2P_UI_TABLE, *PRT_P2P_UI_TABLE; + +#ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT +typedef struct _RT_P2P_DEV_FOUND +{ + UCHAR addr[MAC_ADDR_LEN]; + UCHAR dev_addr[MAC_ADDR_LEN]; + UCHAR pri_dev_type[P2P_DEVICE_TYPE_LEN]; + UCHAR dev_name[32]; + USHORT config_methods; + USHORT dpid; + UCHAR dev_capab; + UCHAR group_capab; + CHAR rssi; +} RT_P2P_DEV_FOUND, *PRT_P2P_DEV_FOUND; + +typedef struct _RT_P2P_PROV_DISC_REQ +{ + UCHAR peer[MAC_ADDR_LEN]; + USHORT config_methods; + UCHAR dev_addr[MAC_ADDR_LEN]; + UCHAR pri_dev_type[P2P_DEVICE_TYPE_LEN]; + UCHAR dev_name[32]; + USHORT supp_config_methods; + UCHAR dev_capab; + UCHAR group_capab; +} RT_P2P_PROV_DISC_REQ, *PRT_P2P_PROV_DISC_REQ; + +typedef struct _RT_P2P_PROV_DISC_RESP +{ + UCHAR peer[MAC_ADDR_LEN]; + USHORT config_methods; +} RT_P2P_PROV_DISC_RESP, *PRT_P2P_PROV_DISC_RESP; + +typedef struct _RT_P2P_GO_NEG_REQ_RX +{ + UCHAR src[MAC_ADDR_LEN]; + USHORT dev_passwd_id; +} RT_P2P_GO_NEG_REQ_RX, *PRT_P2P_GO_NEG_REQ_RX; + +typedef struct _RT_P2P_GROUP_INFO +{ + UCHAR Rule; + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR Ssid[32]; + UCHAR peer[MAC_ADDR_LEN]; +} RT_P2P_GROUP_INFO, *PRT_P2P_GROUP_INFO; +#endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ + + +#endif /* __P2P_CMM_H__ */ +#endif /* P2P_SUPPORT */ + +/* End of p2p_cmm.h */ diff --git a/mt7620/src/include/p2p_inf.h b/mt7620/src/include/p2p_inf.h new file mode 100644 index 0000000..ba990f1 --- /dev/null +++ b/mt7620/src/include/p2p_inf.h @@ -0,0 +1,73 @@ + /* + *************************************************************************** + * 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: + p2p_inf.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + + */ + +#ifndef __P2P_INF_H__ +#define __P2P_INF_H__ + +#define P2P_DISABLE 0x0 +#define P2P_GO_UP 0x1 +#define P2P_CLI_UP 0x2 +/*#define P2P_GO_ON(_p) (OPSTATUS_TEST_FLAG(_p, fOP_STATUS_P2P_GO)) */ +/*#define P2P_CLI_ON(_p) (OPSTATUS_TEST_FLAG(_p, fOP_STATUS_P2P_CLI)) */ + + + +#define P2P_GO_ON(_pAd) \ + (((_pAd)->flg_p2p_init) \ + && ((_pAd)->flg_p2p_OpStatusFlags == P2P_GO_UP)) + + +#define P2P_CLI_ON(_pAd) \ + (((_pAd)->flg_p2p_init) \ + && ((_pAd)->flg_p2p_OpStatusFlags == P2P_CLI_UP)) + + /* P2P interface hook function definition */ + VOID RTMP_P2P_Init( + IN PRTMP_ADAPTER ad_p, + IN PNET_DEV main_dev_p); + + INT P2P_VirtualIF_Open( + IN PNET_DEV dev_p); + + INT P2P_VirtualIF_Close( + IN PNET_DEV dev_p); + + INT P2P_VirtualIF_PacketSend( + IN PNDIS_PACKET skb_p, + IN PNET_DEV dev_p); + + INT P2P_VirtualIF_Ioctl( + IN PNET_DEV dev_p, + IN OUT struct ifreq *rq_p, + IN INT cmd); + + VOID RTMP_P2P_Remove( + IN PRTMP_ADAPTER pAd); + + #endif /* __P2P_INF_H__ */ + diff --git a/mt7620/src/include/p2pcli.h b/mt7620/src/include/p2pcli.h new file mode 100644 index 0000000..b317f57 --- /dev/null +++ b/mt7620/src/include/p2pcli.h @@ -0,0 +1,209 @@ +/* + *************************************************************************** + * 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: + p2pcli.h + + Abstract: + Support AP-Client function. + + Revision History: + Who When What + -------------- ---------- ---------------------------------------------- + Shiang, Fonchi 02-13-2007 created +*/ + +#ifndef _P2P_CLI_H_ +#define _P2P_CLI_H_ + +#ifdef P2P_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 + +#define P2P_CLI_ROOT_BSSID_GET(pAd, wcid) ((pAd)->MacTab.Content[(wcid)].Addr) +#define P2P_CLI_IF_UP_CHECK(pAd, ifidx) ((pAd)->StaCfg.P2PCliTab[(ifidx)].dev->flags & IFF_UP) + +/* sanity check for apidx */ +#define P2P_CLI_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 _P2PCLI_MLME_JOIN_REQ_STRUCT { + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR SsidLen; + UCHAR Ssid[MAX_LEN_OF_SSID]; +} P2PCLI_MLME_JOIN_REQ_STRUCT; + +typedef struct _P2PCLI_CTRL_MSG_STRUCT { + USHORT Status; +} P2PCLI_CTRL_MSG_STRUCT, *PP2PCLI_CTRL_MSG_STRUCT; + +BOOLEAN isValidP2pCliIf( + SHORT ifIndex); + +/* + * Private routines in apcli_ctrl.c +*/ + +VOID P2P_CliCtrlStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +/* + * Private routines in apcli_sync.c +*/ + +VOID P2P_CliSyncStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +/* + * Private routines in apcli_auth.c +*/ + +VOID P2P_CliAuthStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +/* +* Private routines in apcli_assoc.c +*/ + +VOID P2P_CliAssocStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +MAC_TABLE_ENTRY *P2P_CliTableLookUpByWcid( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid, + IN PUCHAR pAddrs); + +BOOLEAN P2P_CliAllowToSendPacket( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + OUT UCHAR *pWcid); + +BOOLEAN P2P_CliValidateRSNIE( + IN PRTMP_ADAPTER pAd, + IN PEID_STRUCT pEid_ptr, + IN USHORT eid_len, + IN USHORT idx); + +INT P2P_CliIfLookUp( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +VOID P2P_CliMgtMacHeaderInit( + 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 P2P_CliCheckHt( + IN PRTMP_ADAPTER pAd, + IN USHORT IfIndex, + IN OUT HT_CAPABILITY_IE *pHtCapability, + IN OUT ADD_HT_INFO_IE *pAddHtInfo); +#endif /* DOT11_N_SUPPORT */ + +BOOLEAN P2P_CliLinkUp( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex); + +VOID P2P_CliLinkDown( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex); + +VOID P2P_CliIfUp( + IN PRTMP_ADAPTER pAd); + +VOID P2P_CliIfDown( + IN PRTMP_ADAPTER pAd); + +VOID P2P_CliIfMonitor( + IN PRTMP_ADAPTER pAd); + +BOOLEAN P2P_CliMsgTypeSubst( + IN PRTMP_ADAPTER pAd, + IN PFRAME_802_11 pFrame, + OUT INT *Machine, + OUT INT *MsgType); + +BOOLEAN P2P_PreCheckMsgTypeSubset( + IN PRTMP_ADAPTER pAd, + IN PFRAME_802_11 pFrame, + OUT INT *Machine, + OUT INT *MsgType); + +BOOLEAN P2P_CliPeerAssocRspSanity( + 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); + +BOOLEAN P2P_CliHandleRxBroadcastFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR FromWhichBSSID); + +VOID P2P_CliInstallPairwiseKey( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +BOOLEAN P2P_CliInstallSharedKey( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKey, + IN UCHAR KeyLen, + IN UCHAR DefaultKeyIdx, + IN MAC_TABLE_ENTRY *pEntry); + +#endif /* P2P_SUPPORT */ +#endif /* _P2P_CLI_H_ */ + diff --git a/mt7620/src/include/radar.h b/mt7620/src/include/radar.h new file mode 100644 index 0000000..ce3f27f --- /dev/null +++ b/mt7620/src/include/radar.h @@ -0,0 +1,89 @@ +/* + *************************************************************************** + * 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__ + +/* RESTRICTION_BAND_1: 5600MHz ~ 5650MHz */ +#define RESTRICTION_BAND_1(_pAd) \ + _pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40 ? \ + ((_pAd->CommonCfg.Channel >= 116) && (_pAd->CommonCfg.Channel <= 128)) : \ + ((_pAd->CommonCfg.Channel >= 120) && (_pAd->CommonCfg.Channel <= 128)) + +/* 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 */ + USHORT ChMovingTime; + BOOLEAN bDFSIndoor; + ULONG InServiceMonitorCount; /* unit: sec */ +} DOT11_H, *PDOT11_H; + +BOOLEAN RadarChannelCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR Ch); + +ULONG JapRadarType( + IN PRTMP_ADAPTER pAd); + +#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/mt7620/src/include/rt_cal.h b/mt7620/src/include/rt_cal.h new file mode 100644 index 0000000..e3a0d86 --- /dev/null +++ b/mt7620/src/include/rt_cal.h @@ -0,0 +1,100 @@ +/* + *************************************************************************** + * 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); + +INT Set_TestLoftTxIQCalibration_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/mt7620/src/include/rt_config.h b/mt7620/src/include/rt_config.h new file mode 100644 index 0000000..9b2c17b --- /dev/null +++ b/mt7620/src/include/rt_config.h @@ -0,0 +1,252 @@ +/* + *************************************************************************** + * 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__ + +/* #define WDS_VLAN_SUPPORT */ + +#include "rtmp_comm.h" +/*#include "rtmp_type.h" */ +/*#include "rtmp_os.h" */ + +#include "rtmp_def.h" +#include "rtmp_chip.h" +#include "rtmp_timer.h" + + +#ifdef LINUX +#ifdef RT_CFG80211_SUPPORT +#include "cfg80211extr.h" +#endif /* RT_CFG80211_SUPPORT */ +#endif /* LINUX */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef AGS_SUPPORT +#include "ags.h" +#endif /* AGS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef BAND_STEERING +#include "band_steering_def.h" +#endif /* BAND_STEERING */ + +#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 "ap.h" +#include "wpa.h" +#include "chlist.h" +#include "spectrum.h" +#ifdef CONFIG_AP_SUPPORT +#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 "rtmp_mcu.h" +#endif + +#undef AP_WSC_INCLUDED +#undef STA_WSC_INCLUDED +#undef WSC_INCLUDED + +#include "rt_os_net.h" + +#include "rt_cal.h" + +#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 */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef MAT_SUPPORT +#include "mat.h" +#endif /* MAT_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT +#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 MESH_SUPPORT +#include "mesh.h" +#endif /* MESH_SUPPORT */ + +#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 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 */ +#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" +#endif /* WSC_INCLUDED */ + + +#ifdef IKANOS_VX_1X0 +#include "vr_ikans.h" +#endif /* IKANOS_VX_1X0 */ + + + + + +#ifdef WAPI_SUPPORT +#include "wapi.h" +#endif /* WAPI_SUPPORT */ + +#ifdef P2P_SUPPORT +/*#include "p2p_inf.h" */ +#include "p2p.h" +#include "p2pcli.h" +#endif /* P2P_SUPPORT */ + +#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 */ + +#ifdef WORKQUEUE_BH +#include +#endif /* WORKQUEUE_BH / */ +#endif /* RTMP_RBUS_SUPPORT */ + +#ifdef BAND_STEERING +#include "band_steering.h" +#endif /* BAND_STEERING */ + + +#ifdef TXBF_SUPPORT +#include "rt_txbf.h" +#endif /* TXBF_SUPPORT */ + + +#endif /* __RT_CONFIG_H__ */ + diff --git a/mt7620/src/include/rt_led.h b/mt7620/src/include/rt_led.h new file mode 100644 index 0000000..9b5ac1c --- /dev/null +++ b/mt7620/src/include/rt_led.h @@ -0,0 +1,535 @@ +/**************************************************************************** + * 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 +#ifdef CONFIG_WIFI_LED_SHARE +#define WPS_LED_MODE_SHARE 0x0d +#endif /* CONFIG_WIFI_LED_SHARE */ +#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 */ +#ifdef CONFIG_WIFI_LED_SHARE +#define LED_WPS_PRE_STAGE 0x20 +#define LED_WPS_POST_STAGE 0x21 +#endif /* CONFIG_WIFI_LED_SHARE */ +#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. */ +#ifdef CONFIG_WIFI_LED_SHARE +#define LINK_STATUS_WPS_PRE_STAGE 0x10 +#define LINK_STATUS_WPS_POST_STAGE 0x11 +#endif /* CONFIG_WIFI_LED_SHARE */ +#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 +#ifdef CONFIG_WIFI_LED_SHARE +#define MCU_LED_ACT_WPS_PRE_STAGE 14 +#define MCU_LED_ACT_WPS_POST_STAGE 15 +#endif /* CONFIG_WIFI_LED_SHARE */ +#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); + +#ifdef WSC_LED_SUPPORT +void SetWPSLinkStatus( + IN PRTMP_ADAPTER pAd); +#endif /* WSC_LED_SUPPORT */ + +#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/mt7620/src/include/rt_os_net.h b/mt7620/src/include/rt_os_net.h new file mode 100644 index 0000000..4663134 --- /dev/null +++ b/mt7620/src/include/rt_os_net.h @@ -0,0 +1,639 @@ +/**************************************************************************** + + 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)( + IN VOID *net_dev_, + IN UCHAR *pData); + +typedef int (*RTMP_NET_PACKET_TRANSMIT)( + IN 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)( + IN PVOID handle, + OUT VOID **ppAdapter); + +VOID (*RTMPFreeAdapter)( + IN VOID *pAd); + +BOOLEAN (*RtmpRaDevCtrlExit)( + IN VOID *pAd); + +INT (*RtmpRaDevCtrlInit)( + IN VOID *pAd, + IN RTMP_INF_TYPE infType); + +VOID (*RTMPHandleInterrupt)( + IN 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 (*MBSS_PacketSend)( + IN PNDIS_PACKET pPktSrc, + IN PNET_DEV pDev, + IN RTMP_NET_PACKET_TRANSMIT Func); + +int (*WDS_PacketSend)( + IN PNDIS_PACKET pPktSrc, + IN PNET_DEV pDev, + IN RTMP_NET_PACKET_TRANSMIT Func); + +int (*APC_PacketSend)( + IN PNDIS_PACKET pPktSrc, + IN PNET_DEV pDev, + IN RTMP_NET_PACKET_TRANSMIT Func); + +int (*MESH_PacketSend)( + IN PNDIS_PACKET pPktSrc, + IN PNET_DEV pDev, + IN RTMP_NET_PACKET_TRANSMIT 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)( + IN VOID *pAd); + +VOID (*RTMPDrvClose)( + IN VOID *pAd, + IN VOID *net_dev); + +VOID (*RTMPInfClose)( + IN VOID *pAd); + +int (*rt28xx_init)( + IN VOID *pAd, + IN PSTRING pDefaultMac, + IN 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)( + IN VOID *pURB); + +typedef struct _RTMP_NET_ABL_OPS { + + +} RTMP_NET_ABL_OPS; + +extern RTMP_NET_ABL_OPS *pRtmpDrvNetOps; + +VOID RtmpNetOpsInit( + IN VOID *pNetOpsOrg); + +VOID RtmpNetOpsSet( + IN 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 MBSS_PacketSend (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->MBSS_PacketSend) +#define WDS_PacketSend (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->WDS_PacketSend) +#define APC_PacketSend (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->APC_PacketSend) +#define MESH_PacketSend (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->MESH_PacketSend) +#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( + IN PVOID handle, + OUT VOID **ppAdapter); + +VOID RTMPFreeAdapter( + IN VOID *pAd); + +BOOLEAN RtmpRaDevCtrlExit( + IN VOID *pAd); + +INT RtmpRaDevCtrlInit( + IN VOID *pAd, + IN RTMP_INF_TYPE infType); + +VOID RTMPHandleInterrupt( + IN 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 MBSS_PacketSend( + IN PNDIS_PACKET pPktSrc, + IN PNET_DEV pDev, + IN RTMP_NET_PACKET_TRANSMIT Func); + +int WDS_PacketSend( + IN PNDIS_PACKET pPktSrc, + IN PNET_DEV pDev, + IN RTMP_NET_PACKET_TRANSMIT Func); + +int APC_PacketSend( + IN PNDIS_PACKET pPktSrc, + IN PNET_DEV pDev, + IN RTMP_NET_PACKET_TRANSMIT Func); + +int MESH_PacketSend( + IN PNDIS_PACKET pPktSrc, + IN PNET_DEV pDev, + IN RTMP_NET_PACKET_TRANSMIT 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( + IN VOID *pAd); + +VOID RTMPDrvClose( + IN VOID *pAd, + IN VOID *net_dev); + +VOID RTMPInfClose( + IN VOID *pAd); + +int rt28xx_init( + IN VOID *pAd, + IN PSTRING pDefaultMac, + IN PSTRING pHostName); + +PNET_DEV RtmpPhyNetDevMainCreate( + IN 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( + IN VOID *pAd, + IN PNET_DEV main_dev_p); +VOID RT28xx_MBSS_Remove( + IN VOID *pAd); +INT MBSS_VirtualIF_Open( + IN PNET_DEV dev_p); +INT MBSS_VirtualIF_Close( + IN PNET_DEV dev_p); +INT MBSS_VirtualIF_PacketSend( + IN PNDIS_PACKET skb_p, + IN PNET_DEV dev_p); +INT MBSS_VirtualIF_Ioctl( + IN PNET_DEV dev_p, + IN OUT VOID *rq_p, + IN INT cmd); + +VOID RT28xx_WDS_Init( + IN VOID *pAd, + IN PNET_DEV net_dev); +INT WdsVirtualIFSendPackets( + IN PNDIS_PACKET pSkb, + IN PNET_DEV dev); +INT WdsVirtualIF_open( + IN PNET_DEV dev); +INT WdsVirtualIF_close( + IN PNET_DEV dev); +INT WdsVirtualIF_ioctl( + IN PNET_DEV net_dev, + IN OUT VOID *rq, + IN INT cmd); +VOID RT28xx_WDS_Remove( + IN VOID *pAd); + +VOID RT28xx_ApCli_Init( + IN VOID *pAd, + IN PNET_DEV main_dev_p); +INT ApCli_VirtualIF_Open( + IN PNET_DEV dev_p); +INT ApCli_VirtualIF_Close( + IN PNET_DEV dev_p); +INT ApCli_VirtualIF_PacketSend( + IN PNDIS_PACKET pPktSrc, + IN PNET_DEV pDev); +INT ApCli_VirtualIF_Ioctl( + IN PNET_DEV dev_p, + IN OUT VOID *rq_p, + IN INT cmd); +VOID RT28xx_ApCli_Remove( + IN VOID *pAd); + +VOID RTMP_Mesh_Init( + IN VOID *pAd, + IN PNET_DEV main_dev_p, + IN PSTRING pHostName); +VOID RTMP_Mesh_Remove( + IN VOID *pAd); +INT Mesh_VirtualIF_Open( + IN PNET_DEV pDev); +INT Mesh_VirtualIF_Close( + IN PNET_DEV pDev); +INT Mesh_VirtualIF_PacketSend( + IN PNDIS_PACKET pPktSrc, + IN PNET_DEV pDev); +INT Mesh_VirtualIF_Ioctl( + IN PNET_DEV dev_p, + IN OUT VOID *rq_p, + IN INT cmd); + +VOID RTMP_P2P_Init( + IN VOID *pAd, + IN PNET_DEV main_dev_p); + + INT P2P_VirtualIF_Open( + IN PNET_DEV dev_p); + + INT P2P_VirtualIF_Close( + IN PNET_DEV dev_p); + + INT P2P_VirtualIF_PacketSend( + IN PNDIS_PACKET skb_p, + IN PNET_DEV dev_p); + + INT P2P_VirtualIF_Ioctl( + IN PNET_DEV dev_p, + IN OUT VOID *rq_p, + IN INT cmd); + +VOID RTMP_P2P_Remove( + IN VOID *pAd); + + +/* 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) + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +#define RTMP_DRIVER_MAX_IN_BITS_SET(__pAd, __MaxInBit) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_MAX_IN_BIT, 0, NULL, __MaxInBit) +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ +#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) + +#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) + + +#ifdef WOW_SUPPORT +#endif /* WOW_SUPPORT */ + +#endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ +#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_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 */ + +/* cfg80211 */ +#define RTMP_DRIVER_CFG80211_START(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_CFG80211_CFG_START, 0, NULL, 0) + + +#ifdef RT_CFG80211_SUPPORT +#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_CHAN_SET(__pAd, __pChan) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_CHAN_SET, 0, __pChan, 0) +#define RTMP_DRIVER_80211_VIF_SET(__pAd, __Filter, __IfType) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_VIF_CHG, 0, &__Filter, __IfType) +#define RTMP_DRIVER_80211_SCAN(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_SCAN, 0, NULL, 0) +#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_STA_LEAVE(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_STA_LEAVE, 0, NULL, 0) +#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_KEY_ADD(__pAd, __pKeyInfo) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_KEY_ADD, 0, __pKeyInfo, 0) +#define RTMP_DRIVER_80211_KEY_DEFAULT_SET(__pAd, __KeyId) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_KEY_DEFAULT_SET, 0, NULL, __KeyId) +#define RTMP_DRIVER_80211_CONNECT(__pAd, __pConnInfo) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_CONNECT_TO, 0, __pConnInfo, 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_UNREGISTER(__pAd, __pNetDev) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_UNREGISTER, 0, __pNetDev, 0) +#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_SURVEY_GET(__pAd, __pSurveyInfo) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_80211_SURVEY_GET, 0, __pSurveyInfo, 0) +#define RTMP_DRIVER_80211_PMKID_CTRL(__pAd, __pPmkidInfo) \ + RTMP_STA_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_STA_SIOCSIWPMKSA, 0, __pPmkidInfo, 0, 0); +#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) + +/* 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_TSO_SUPPORT_TEST(__pAd, __flag) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ADAPTER_TSO_SUPPORT_TEST, 0, __flag, 0) + +#endif /* __RT_OS_NET_H__ */ + +/* End of rt_os_net.h */ diff --git a/mt7620/src/include/rt_os_util.h b/mt7620/src/include/rt_os_util.h new file mode 100644 index 0000000..3a9eb3f --- /dev/null +++ b/mt7620/src/include/rt_os_util.h @@ -0,0 +1,1009 @@ +/**************************************************************************** + + 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( + IN ULONG usec); + +VOID RtmpOsMsDelay( + IN ULONG msec); + +void RTMP_GetCurrentSystemTime( + IN LARGE_INTEGER *time); + +void RTMP_GetCurrentSystemTick( + IN ULONG *pNow); + +VOID RtmpOsWait( + IN UINT32 Time); + +UINT32 RtmpOsTimerAfter( + IN ULONG a, + IN ULONG b); + +UINT32 RtmpOsTimerBefore( + IN ULONG a, + IN ULONG b); + +VOID RtmpOsGetSystemUpTime( + IN ULONG *pTime); + +UINT32 RtmpOsTickUnitGet(VOID); + +/* OS Memory */ +NDIS_STATUS os_alloc_mem( + IN VOID *pReserved, + OUT UCHAR **mem, + IN ULONG size); + +NDIS_STATUS os_alloc_mem_suspend( + IN VOID *pReserved, + OUT UCHAR **mem, + IN ULONG size); + +NDIS_STATUS os_free_mem( + IN VOID *pReserved, + IN PVOID mem); + +NDIS_STATUS AdapterBlockAllocateMemory( + IN PVOID handle, + OUT PVOID *ppAd, + IN UINT32 SizeOfpAd); + +VOID *RtmpOsVmalloc( + IN ULONG Size); + +VOID RtmpOsVfree( + IN VOID *pMem); + +ULONG RtmpOsCopyFromUser( + OUT VOID *to, + IN const void *from, + IN ULONG n); + +ULONG RtmpOsCopyToUser( + OUT VOID *to, + IN const void *from, + IN ULONG n); + +BOOLEAN RtmpOsStatsAlloc( + IN VOID **ppStats, + IN VOID **ppIwStats); + +/* OS Packet */ +PNDIS_PACKET RtmpOSNetPktAlloc( + IN VOID *pReserved, + IN int size); + +PNDIS_PACKET RTMP_AllocateFragPacketBuffer( + IN VOID *pReserved, + IN 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( + IN VOID *pReserved, + IN PNDIS_PACKET pPacket); + +NDIS_STATUS Sniff2BytesFromNdisBuffer( + IN PNDIS_BUFFER pFirstBuffer, + IN UCHAR DesiredOffset, + OUT PUCHAR pByte0, + OUT PUCHAR pByte1); + +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); + +void send_monitor_packets( + IN PNET_DEV pNetDev, + IN PNDIS_PACKET pRxPacket, + IN PHEADER_802_11 pHeader, + 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); + +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( + IN PNDIS_PACKET pNetPkt); + +PNDIS_PACKET RtmpOsPktCopy( + IN PNDIS_PACKET pNetPkt); + +PNDIS_PACKET RtmpOsPktClone( + IN PNDIS_PACKET pNetPkt); + +VOID RtmpOsPktDataPtrAssign( + IN PNDIS_PACKET pNetPkt, + IN UCHAR *pData); + +VOID RtmpOsPktLenAssign( + IN PNDIS_PACKET pNetPkt, + IN LONG Len); + +VOID RtmpOsPktTailAdjust( + IN PNDIS_PACKET pNetPkt, + IN UINT removedTagLen); + +PUCHAR RtmpOsPktTailBufExtend( + IN PNDIS_PACKET pNetPkt, + IN UINT Len); + +PUCHAR RtmpOsPktHeadBufExtend( + IN PNDIS_PACKET pNetPkt, + IN UINT Len); + +VOID RtmpOsPktReserve( + IN PNDIS_PACKET pNetPkt, + IN UINT Len); + +VOID RtmpOsPktProtocolAssign( + IN PNDIS_PACKET pNetPkt); + +VOID RtmpOsPktInfPpaSend( + IN PNDIS_PACKET pNetPkt); + +VOID RtmpOsPktRcvHandle( + IN PNDIS_PACKET pNetPkt); + +VOID RtmpOsPktNatMagicTag( + IN PNDIS_PACKET pNetPkt); + +VOID RtmpOsPktNatNone( + IN PNDIS_PACKET pNetPkt); + +VOID RtmpOsPktInit( + IN PNDIS_PACKET pNetPkt, + IN PNET_DEV pNetDev, + IN UCHAR *pData, + IN USHORT DataSize); + +PNDIS_PACKET RtmpOsPktIappMakeUp( + IN PNET_DEV pNetDev, + IN UINT8 *pMac); + +BOOLEAN RtmpOsPktOffsetInit(VOID); + +UINT16 RtmpOsNtohs( + IN UINT16 Value); + +UINT16 RtmpOsHtons( + IN UINT16 Value); + +UINT32 RtmpOsNtohl( + IN UINT32 Value); + +UINT32 RtmpOsHtonl( + IN 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( + IN VOID *pFile); + +void RtmpOSFSInfoChange( + IN RTMP_OS_FS_INFO *pOSFSInfoOrg, + IN BOOLEAN bSet); + +/* OS Network Interface */ +int RtmpOSNetDevAddrSet( + IN UCHAR OpMode, + IN PNET_DEV pNetDev, + IN PUCHAR pMacAddr, + IN PUCHAR dev_name); + +void RtmpOSNetDevClose( + IN PNET_DEV pNetDev); + +void RtmpOSNetDevFree( + IN PNET_DEV pNetDev); + +INT RtmpOSNetDevAlloc( + IN PNET_DEV *new_dev_p, + IN UINT32 privDataSize); + +INT RtmpOSNetDevOpsAlloc( + IN PVOID *pNetDevOps); + + +PNET_DEV RtmpOSNetDevGetByName( + IN PNET_DEV pNetDev, + IN PSTRING pDevName); + +void RtmpOSNetDeviceRefPut( + IN PNET_DEV pNetDev); + +INT RtmpOSNetDevDestory( + IN VOID *pReserved, + IN PNET_DEV pNetDev); + +void RtmpOSNetDevDetach( + IN PNET_DEV pNetDev); + +int RtmpOSNetDevAttach( + IN UCHAR OpMode, + IN PNET_DEV pNetDev, + IN RTMP_OS_NETDEV_OP_HOOK *pDevOpHook); + +PNET_DEV RtmpOSNetDevCreate( + IN INT32 MC_RowID, + IN UINT32 *pIoctlIF, + IN INT devType, + IN INT devNum, + IN INT privMemSize, + IN PSTRING pNamePrefix); + +BOOLEAN RtmpOSNetDevIsUp( + IN VOID *pDev); + +unsigned char *RtmpOsNetDevGetPhyAddr( + IN VOID *pDev); + +VOID RtmpOsNetQueueStart( + IN PNET_DEV pDev); + +VOID RtmpOsNetQueueStop( + IN PNET_DEV pDev); + +VOID RtmpOsNetQueueWake( + IN PNET_DEV pDev); + +VOID RtmpOsSetPktNetDev( + IN VOID *pPkt, + IN VOID *pDev); + +PNET_DEV RtmpOsPktNetDevGet( + IN VOID *pPkt); + +char *RtmpOsGetNetDevName( + IN VOID *pDev); + +VOID RtmpOsSetNetDevPriv( + IN VOID *pDev, + IN VOID *pPriv); + +VOID *RtmpOsGetNetDevPriv( + IN VOID *pDev); + +USHORT RtmpDevPrivFlagsGet( + IN VOID *pDev); + +VOID RtmpDevPrivFlagsSet( + IN VOID *pDev, + IN USHORT PrivFlags); + +VOID RtmpOsSetNetDevType( + IN VOID *pDev, + IN USHORT Type); + +VOID RtmpOsSetNetDevTypeMonitor( + IN VOID *pDev); + +/* OS Semaphore */ +VOID RtmpOsCmdUp( + IN RTMP_OS_TASK *pCmdQTask); + +BOOLEAN RtmpOsSemaInitLocked( + IN RTMP_OS_SEM *pSemOrg, + IN LIST_HEADER *pSemList); + +BOOLEAN RtmpOsSemaInit( + IN RTMP_OS_SEM *pSemOrg, + IN LIST_HEADER *pSemList); + +BOOLEAN RtmpOsSemaDestory( + IN RTMP_OS_SEM *pSemOrg); + +INT32 RtmpOsSemaWaitInterruptible( + IN RTMP_OS_SEM *pSemOrg); + +VOID RtmpOsSemaWakeUp( + IN RTMP_OS_SEM *pSemOrg); + +VOID RtmpOsMlmeUp( + IN RTMP_OS_TASK *pMlmeQTask); + +/* OS Task */ +BOOLEAN RtmpOsTaskletSche( + IN RTMP_NET_TASK_STRUCT *pTasklet); + +BOOLEAN RtmpOsTaskletInit( + IN RTMP_NET_TASK_STRUCT *pTasklet, + IN VOID (*pFunc)(unsigned long data), + IN ULONG Data, + IN LIST_HEADER *pTaskletList); + +BOOLEAN RtmpOsTaskletKill( + IN RTMP_NET_TASK_STRUCT *pTasklet); + +VOID RtmpOsTaskletDataAssign( + IN RTMP_NET_TASK_STRUCT *pTasklet, + IN ULONG Data); + +VOID RtmpOsTaskWakeUp( + IN RTMP_OS_TASK *pTaskOrg); + +INT32 RtmpOsTaskIsKilled( + IN RTMP_OS_TASK *pTaskOrg); + +BOOLEAN RtmpOsCheckTaskLegality( + IN RTMP_OS_TASK *pTaskOrg); + +BOOLEAN RtmpOSTaskAlloc( + IN RTMP_OS_TASK *pTask, + IN LIST_HEADER *pTaskList); + +VOID RtmpOSTaskFree( + IN RTMP_OS_TASK *pTask); + +NDIS_STATUS RtmpOSTaskKill( + IN RTMP_OS_TASK *pTaskOrg); + +INT RtmpOSTaskNotifyToExit( + IN RTMP_OS_TASK *pTaskOrg); + +VOID RtmpOSTaskCustomize( + IN 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( + IN RTMP_OS_TASK *pTaskOrg); + +INT32 RtmpThreadPidKill( + IN RTMP_OS_PID PID); + +/* OS Cache */ +VOID RtmpOsDCacheFlush( + IN ULONG AddrStart, + IN 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( + IN NDIS_MINIPORT_TIMER *pTimerOrg, + IN unsigned long timeout); + +VOID RTMP_OS_Mod_Timer( + IN NDIS_MINIPORT_TIMER *pTimerOrg, + IN unsigned long timeout); + +VOID RTMP_OS_Del_Timer( + IN NDIS_MINIPORT_TIMER *pTimerOrg, + OUT BOOLEAN *pCancelled); + +VOID RTMP_OS_Release_Timer( + IN NDIS_MINIPORT_TIMER *pTimerOrg); + +BOOLEAN RTMP_OS_Alloc_Rsc( + IN LIST_HEADER *pRscList, + IN VOID *pRsc, + IN UINT32 RscLen); + +VOID RTMP_OS_Free_Rscs( + IN LIST_HEADER *pRscList); + +/* OS Lock */ +BOOLEAN RtmpOsAllocateLock( + IN NDIS_SPIN_LOCK *pLock, + IN LIST_HEADER *pLockList); + +VOID RtmpOsFreeSpinLock( + IN NDIS_SPIN_LOCK *pLockOrg); + +VOID RtmpOsSpinLockBh( + IN NDIS_SPIN_LOCK *pLockOrg); + +VOID RtmpOsSpinUnLockBh( + IN NDIS_SPIN_LOCK *pLockOrg); + +VOID RtmpOsIntLock( + IN NDIS_SPIN_LOCK *pLockOrg, + IN ULONG *pIrqFlags); + +VOID RtmpOsIntUnLock( + IN NDIS_SPIN_LOCK *pLockOrg, + IN ULONG IrqFlags); + +/* OS PID */ +VOID RtmpOsGetPid( + IN ULONG *pDst, + IN ULONG PID); + +VOID RtmpOsTaskPidInit( + IN RTMP_OS_PID *pPid); + +/* OS I/O */ +VOID RTMP_PCI_Writel( + IN ULONG Value, + IN VOID *pAddr); + +VOID RTMP_PCI_Writew( + IN ULONG Value, + IN VOID *pAddr); + +VOID RTMP_PCI_Writeb( + IN ULONG Value, + IN VOID *pAddr); + +ULONG RTMP_PCI_Readl( + IN VOID *pAddr); + +ULONG RTMP_PCI_Readw( + IN VOID *pAddr); + +ULONG RTMP_PCI_Readb( + IN VOID *pAddr); + +int RtmpOsPciConfigReadWord( + IN VOID *pDev, + IN UINT32 Offset, + OUT UINT16 *pValue); + +int RtmpOsPciConfigWriteWord( + IN VOID *pDev, + IN UINT32 Offset, + IN UINT16 Value); + +int RtmpOsPciConfigReadDWord( + IN VOID *pDev, + IN UINT32 Offset, + OUT UINT32 *pValue); + +int RtmpOsPciConfigWriteDWord( + IN VOID *pDev, + IN UINT32 Offset, + IN UINT32 Value); + +int RtmpOsPciFindCapability( + IN VOID *pDev, + IN int Cap); + +VOID *RTMPFindHostPCIDev( + IN VOID *pPciDevSrc); + +int RtmpOsPciMsiEnable( + IN VOID *pDev); + +VOID RtmpOsPciMsiDisable( + IN VOID *pDev); + +/* OS Wireless */ +ULONG RtmpOsMaxScanDataGet(VOID); + +/* OS Interrutp */ +INT32 RtmpOsIsInInterrupt(VOID); + +/* OS USB */ +VOID *RtmpOsUsbUrbDataGet( + IN VOID *pUrb); + +NTSTATUS RtmpOsUsbUrbStatusGet( + IN VOID *pUrb); + +ULONG RtmpOsUsbUrbLenGet( + IN VOID *pUrb); + +/* OS Atomic */ +BOOLEAN RtmpOsAtomicInit( + IN RTMP_OS_ATOMIC *pAtomic, + IN LIST_HEADER *pAtomicList); + +VOID RtmpOsAtomicDestroy( + IN RTMP_OS_ATOMIC *pAtomic); + +LONG RtmpOsAtomicRead( + IN RTMP_OS_ATOMIC *pAtomic); + +VOID RtmpOsAtomicDec( + IN RTMP_OS_ATOMIC *pAtomic); + +VOID RtmpOsAtomicInterlockedExchange( + IN RTMP_OS_ATOMIC *pAtomicSrc, + IN LONG Value); + +/* OS Utility */ +void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen); + +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); + + +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( + IN UINT16 *pWord); + +UINT32 RtmpOsGetUnaligned32( + IN UINT32 *pWord); + +ULONG RtmpOsGetUnalignedlong( + IN ULONG *pWord); + +long RtmpOsSimpleStrtol( + IN const char *cp, + IN char **endp, + IN unsigned int base); + +VOID RtmpOsOpsInit( + IN RTMP_OS_ABL_OPS *pOps); + +/* ============================ rt_os_util.c ================================ */ +VOID RtmpDrvMaxRateGet( + IN VOID *pReserved, + IN UINT8 MODE, + IN UINT8 ShortGI, + IN UINT8 BW, + IN UINT8 MCS, + OUT UINT32 *pRate); + +char * rtstrchr(const char * s, int c); + +PSTRING WscGetAuthTypeStr( + IN USHORT authFlag); + +PSTRING WscGetEncryTypeStr( + IN USHORT encryFlag); + +USHORT WscGetAuthTypeFromStr( + IN PSTRING arg); + +USHORT WscGetEncrypTypeFromStr( + IN PSTRING arg); + +VOID RtmpMeshDown( + IN VOID *pDrvCtrlBK, + IN BOOLEAN WaitFlag, + IN BOOLEAN (*RtmpMeshLinkCheck)(IN VOID *pAd)); + +USHORT RtmpOsNetPrivGet( + IN PNET_DEV pDev); + +BOOLEAN RtmpOsCmdDisplayLenCheck( + IN UINT32 LenSrc, + IN UINT32 Offset); + +VOID WpaSendMicFailureToWpaSupplicant( + IN PNET_DEV pNetDev, + IN BOOLEAN bUnicast); + +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 RTMP_AllocateTxDescMemory( + IN PPCI_DEV pPciDev, + IN UINT Index, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +void RTMP_AllocateMgmtDescMemory( + IN PPCI_DEV pPciDev, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +void RTMP_AllocateRxDescMemory( + IN PPCI_DEV pPciDev, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +void RTMP_FreeDescMemory( + IN PPCI_DEV pPciDev, + IN ULONG Length, + IN PVOID VirtualAddress, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + +void RTMP_AllocateFirstTxBuffer( + IN PPCI_DEV pPciDev, + IN UINT Index, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *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); +#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 INT32 ralinkrate[]; +extern UINT32 RT_RateSize; + +#ifdef PLATFORM_UBM_IPX8 +#include "vrut_ubm.h" +#endif /* PLATFORM_UBM_IPX8 */ + +INT32 RtPrivIoctlSetVal(VOID); + +#endif /* __RT_OS_UTIL_H__ */ diff --git a/mt7620/src/include/rt_txbf.h b/mt7620/src/include/rt_txbf.h new file mode 100644 index 0000000..33d5b3a --- /dev/null +++ b/mt7620/src/include/rt_txbf.h @@ -0,0 +1,215 @@ +/* + *************************************************************************** + * 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 + +//#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 +#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 + +// 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; + + +typedef +struct { + UCHAR gBeg[2]; + UCHAR gEnd[2]; + UCHAR aLowBeg[2]; + UCHAR aLowEnd[2]; + UCHAR aMidBeg[2]; + UCHAR aMidEnd[2]; + UCHAR aHighBeg[2]; + UCHAR aHighEnd[2]; +} ITXBF_PHASE_PARAMS; // ITxBF BBP reg phase calibration parameters + +typedef +struct { + UCHAR gBeg[2]; + UCHAR gEnd[2]; + UCHAR aLowBeg[2]; + UCHAR aLowEnd[2]; + UCHAR aMidBeg[2]; + UCHAR aMidEnd[2]; + UCHAR aHighBeg[2]; + UCHAR aHighEnd[2]; +} ITXBF_LNA_PARAMS; // ITxBF BBP reg LNA calibration parameters + +typedef +struct { + UCHAR gBeg[2]; + UCHAR gEnd[2]; + UCHAR aLow[2]; + UCHAR aMid[2]; + UCHAR aHigh[2]; +} ITXBF_DIV_PARAMS; // ITxBF Divider Calibration parameters + +void ITxBFGetEEPROM( + IN RTMP_ADAPTER *pAd, + IN ITXBF_PHASE_PARAMS *phaseParams, + IN ITXBF_LNA_PARAMS *lnaParams, + IN ITXBF_DIV_PARAMS *divParams); + +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); + +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); + +// 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); + +void ITxBFSetEEPROM( + IN RTMP_ADAPTER *pAd, + IN ITXBF_PHASE_PARAMS *phaseParams, + IN ITXBF_LNA_PARAMS *lnaParams, + IN ITXBF_DIV_PARAMS *divParams); + +#endif // TXBF_SUPPORT // + +#endif // _RT_TXBF_H_ diff --git a/mt7620/src/include/rtmp.h b/mt7620/src/include/rtmp.h new file mode 100644 index 0000000..f641087 --- /dev/null +++ b/mt7620/src/include/rtmp.h @@ -0,0 +1,10466 @@ +/* + *************************************************************************** + * 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 MESH_SUPPORT +#include "mesh_def.h" +#endif /* MESH_SUPPORT */ + +#ifdef WAPI_SUPPORT +#include "wapi_def.h" +#endif /* WAPI_SUPPORT */ + +#include "rtmp_chip.h" + + + + +#ifdef DOT11Z_TDLS_SUPPORT +#include "tdls_cmm.h" +#endif /* DOT11Z_TDLS_SUPPORT */ + +#ifdef CLIENT_WDS +#include "client_wds_cmm.h" +#endif /* CLIENT_WDS */ + + + +#ifdef P2P_SUPPORT +#include "p2p_cmm.h" +#endif /* P2P_SUPPORT */ + +#include "drs_extr.h" + +struct _RTMP_TX_RATE_SWITCH; + +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; + +typedef struct _UAPSD_INFO { + BOOLEAN bAPSDCapable; +} UAPSD_INFO; + +#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 */ + +/*#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 +/*---Used for merge MiniportMMRequest() and MiniportDataMMRequest() into one function */ +/* The number of channels for per-channel Tx power offset */ + + +#define MAXSEQ (0xFFF) + +#ifdef DOT11N_SS3_SUPPORT +#define MAX_MCS_SET 24 /* From MCS 0 ~ MCS 23 */ +#else +#define MAX_MCS_SET 16 /* From MCS 0 ~ MCS 15 */ +#endif /* DOT11N_SS3_SUPPORT */ + + +#define MAX_TXPOWER_ARRAY_SIZE 5 +#ifdef RT2883 +#undef MAX_TXPOWER_ARRAY_SIZE +#define MAX_TXPOWER_ARRAY_SIZE 7 +#endif /* RT2883 */ +#ifdef RT3883 +#undef MAX_TXPOWER_ARRAY_SIZE +#define MAX_TXPOWER_ARRAY_SIZE 10 +#endif /* RT3883 */ + +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 ULONG BIT32[32]; +extern char *CipherName[]; +extern UCHAR RxwiMCSToOfdmRate[12]; +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]; +extern UCHAR TDLS_ETHERTYPE[2]; +#endif /* DOT11Z_TDLS_SUPPORT */ +extern UCHAR OfdmRateToRxwiMCS[]; +extern UCHAR MapUserPriorityToAccessCategory[8]; + +extern USHORT RateUpPER[]; +extern USHORT RateDownPER[]; +extern UCHAR Phy11BNextRateDownward[]; +extern UCHAR Phy11BNextRateUpward[]; +extern UCHAR Phy11BGNextRateDownward[]; +extern UCHAR Phy11BGNextRateUpward[]; +extern UCHAR Phy11ANextRateDownward[]; +extern UCHAR Phy11ANextRateUpward[]; +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; +#ifdef CONFIG_STA_SUPPORT +extern UCHAR PRE_N_HT_OUI[]; +#endif /* CONFIG_STA_SUPPORT */ +#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 PowerConstraintIE[]; + +typedef struct { + LONG i:8; + LONG q:8; +} COMPLEX_VALUE; /* Signed 8-bit complex values */ + +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; + +/* */ +/* 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 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)) + +#ifdef CONFIG_STA_SUPPORT +#define STA_NO_SECURITY_ON(_p) (_p->StaCfg.WepStatus == Ndis802_11EncryptionDisabled) +#define STA_WEP_ON(_p) (_p->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) +#define STA_TKIP_ON(_p) (_p->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) +#define STA_AES_ON(_p) (_p->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + +#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 */ + +/* */ +/* MACRO for 32-bit PCI register read / write */ +/* */ +/* Usage : RTMP_IO_READ32( */ +/* PRTMP_ADAPTER pAd, */ +/* ULONG Register_Offset, */ +/* PULONG pValue) */ +/* */ +/* RTMP_IO_WRITE32( */ +/* PRTMP_ADAPTER pAd, */ +/* ULONG Register_Offset, */ +/* ULONG Value) */ +/* */ + +/* */ +/* Common fragment list structure - Identical to the scatter gather frag list structure */ +/* */ +/*#define RTMP_SCATTER_GATHER_ELEMENT SCATTER_GATHER_ELEMENT */ +/*#define PRTMP_SCATTER_GATHER_ELEMENT PSCATTER_GATHER_ELEMENT */ +#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)) +#define MONITOR_ON(_p) (((_p)->StaCfg.BssType) == BSS_MONITOR) +#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(_p, _pMac1, _pMac2, _pType) \ +{ \ + NdisMoveMemory(_p, _pMac1, MAC_ADDR_LEN); \ + NdisMoveMemory((_p + MAC_ADDR_LEN), _pMac2, MAC_ADDR_LEN); \ + NdisMoveMemory((_p + 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 +#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); \ +} +#endif /* RTMP_MAC_PCI */ + +#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))) + +/* */ +/* Check if it is Japan W53(ch52,56,60,64) channel. */ +/* */ +#define JapanChannelCheck(channel) ((channel == 52) || (channel == 56) || (channel == 60) || (channel == 64)) + +#ifdef CONFIG_STA_SUPPORT +#define STA_EXTRA_SETTING(_pAd) + +#define STA_PORT_SECURED(_pAd) \ +{ \ + BOOLEAN Cancelled; \ + (_pAd)->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; \ + RTMP_IndicateMediaState(_pAd, NdisMediaStateConnected); \ + NdisAcquireSpinLock(&((_pAd)->MacTabLock)); \ + (_pAd)->MacTab.Content[BSSID_WCID].PortSecured = (_pAd)->StaCfg.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 */ +} RTMP_TX_RING, *PRTMP_TX_RING; + +typedef struct _RTMP_RX_RING { + RTMP_DMACB Cell[RX_RING_SIZE]; + UINT32 RxCpuIdx; + UINT32 RxDmaIdx; + INT32 RxSwReadIdx; /* software next read index */ +} RTMP_RX_RING, *PRTMP_RX_RING; + +typedef struct _RTMP_MGMT_RING { + RTMP_DMACB Cell[MGMT_RING_SIZE]; + UINT32 TxCpuIdx; + UINT32 TxDmaIdx; + UINT32 TxSwFreeIdx; /* software next free tx index */ +} RTMP_MGMT_RING, *PRTMP_MGMT_RING; + + +/* */ +/* Statistic counter structure */ +/* */ +typedef struct _COUNTER_802_3 { + /* General Stats */ + ULONG GoodTransmits; + ULONG GoodReceives; + ULONG TxErrors; + ULONG RxErrors; + ULONG RxNoBuffer; + + /* Ethernet Stats */ + ULONG RcvAlignmentErrors; + ULONG OneCollision; + ULONG MoreCollisions; + +} 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 */ + +#ifdef MICROWAVE_OVEN_SUPPORT + UINT16 FalseCCACnt_100MS[MLME_TASK_EXEC_MULTIPLE]; /* one handred millisecond false CCA Count */ + UINT16 PLCPErrCnt_100MS[MLME_TASK_EXEC_MULTIPLE]; /* one handred millisecond PLCP Error Count */ +#endif /* MICROWAVE_OVEN_SUPPORT */ + + 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 OneSecFalseCCACnt1; + + 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; +} COUNTER_RALINK, *PCOUNTER_RALINK; + +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 { + 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 */ + +#if defined(MICROWAVE_OVEN_SUPPORT) || defined(DYNAMIC_VGA_SUPPORT) +/* for Microwave oven */ +typedef struct _MO_CFG_STRUCT { + BOOLEAN bEnable; + BOOLEAN bDyncVGAEnable; + UINT8 nPeriod_Cnt; /* measurement period 100ms, mitigate the interference period 900 ms */ + UINT16 nFalseCCACnt; + UINT16 nFalseCCATh; /* default is 100 */ + UINT16 nLowFalseCCATh; + UINT32 Stored_BBP_R65; + UCHAR Stored_BBP_R66; + UCHAR Stored_RF_B5_R6; + UCHAR Stored_RF_B5_R7; +#ifdef RT6352 + UCHAR Stored_RF_B7_R6; + UCHAR Stored_RF_B7_R7; +#endif /* RT6352 */ +} MO_CFG_STRUCT, *PMO_CFG_STRUCT; +#endif /* defined(MICROWAVE_OVEN_SUPPORT) || defined(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 */ + UINT TxRingFullCnt; /* Tx ring full occurrance number */ + 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; + +/* + 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 + */ +#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 + + 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]; + +#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]; +#endif /* DOT11Z_TDLS_SUPPORT */ + +#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]; + +#ifdef MESH_SUPPORT + STATE_MACHINE MeshCtrlMachine; + STATE_MACHINE MeshLinkMngMachine; + + STATE_MACHINE_FUNC MeshCtrlFunc[MESH_CTRL_FUNC_SIZE]; + STATE_MACHINE_FUNC MeshLinkMngFunc[MESH_LINK_MNG_FUNC_SIZE]; +#endif /* MESH_SUPPORT */ + + ULONG ChannelQuality; /* 0..100, Channel Quality Indication for Roaming */ + ULONG Now32; /* latch the value of NdisGetSystemUpTime() */ + ULONG LastSendNULLpsmTime; + + BOOLEAN bRunning; + NDIS_SPIN_LOCK TaskLock; + MLME_QUEUE Queue; + + UINT ShiftReg; + + RALINK_TIMER_STRUCT PeriodicTimer; + RALINK_TIMER_STRUCT APSDPeriodicTimer; + RALINK_TIMER_STRUCT LinkDownTimer; + RALINK_TIMER_STRUCT LinkUpTimer; +#ifdef RTMP_MAC_PCI + UCHAR bPsPollTimerRunning; + RALINK_TIMER_STRUCT PsPollTimer; + RALINK_TIMER_STRUCT RadioOnOffTimer; +#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; +/* 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_HTMIX) + +#define IS_HT_RATE(_pMacEntry) \ + (_pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) + +#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, *PIOT_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, *PREG_TRANSMIT_SETTING; + + +typedef union _DESIRED_TRANSMIT_SETTING { +#ifdef RT_BIG_ENDIAN + struct { + USHORT rsv:3; + USHORT FixedTxMode:2; /* If MCS isn't AUTO, fix rate in CCK, OFDM or HT mode. */ + USHORT PhyMode:4; + USHORT MCS:7; /* MCS */ + } field; +#else + struct { + USHORT MCS:7; /* MCS */ + USHORT PhyMode:4; + USHORT FixedTxMode:2; /* If MCS isn't AUTO, fix rate in CCK, OFDM or HT mode. */ + USHORT rsv:3; + } field; +#endif + USHORT word; + } DESIRED_TRANSMIT_SETTING, *PDESIRED_TRANSMIT_SETTING; + + + +/*************************************************************************** + * 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, wcid) \ + { UCHAR tim_offset = wcid >> 3; \ + UCHAR bit_offset = wcid & 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, wcid) \ + { UCHAR tim_offset = wcid >> 3; \ + UCHAR bit_offset = wcid & 0x7; \ + ad_p->ApCfg.MBSSID[apidx].TimBitmaps[tim_offset] |= NUM_BIT8[bit_offset]; } + +#ifdef EASY_CONFIG_SETUP +#ifdef WAC_SUPPORT +typedef struct _WAC_REQUEST { + BOOLEAN bReqType; /* TRUE: set, FALSE: get */ + UCHAR Command; /* 0: add, 1: del */ + UCHAR FrameType; + BOOLEAN RV; /* TRUE: success, FALSE: fail */ + USHORT CurrentStatus; + UCHAR VendorInfoLen; + PUCHAR pVendorInfo; +} WAC_REQUEST, *PWAC_REQUEST; +#endif /* WAC_SUPPORT */ +typedef struct _EASY_CONFIG_INFO { +#ifdef CONFIG_STA_SUPPORT + RALINK_TIMER_STRUCT ScanTimer; + RALINK_TIMER_STRUCT InfraConnTimer; + RALINK_TIMER_STRUCT AdhocConnTimer; + UCHAR ModuleType; + BOOLEAN bRaAutoWpsAp; + BOOLEAN bChangeMode; + UCHAR WpsEncryptPIN[12]; +#ifdef WAC_SUPPORT + BOOLEAN bWACAP; + UCHAR DoAutoWAC; /* 0x00: Do WAC by driver, 0x01: Do WAC by UI */ + BOOLEAN bAutoWAC; /* TRUE: Do WAC by driver, FALSE: Do WAC by UI */ + PUCHAR pVendorInfoForProbeReq; + UCHAR VendorInfoForProbeReqLen; +#endif /* WAC_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + BOOLEAN bEnable; + BOOLEAN bDoAutoWps; + CHAR RssiThreshold; + UCHAR WpsPTK[64]; /* Ralink proprietary PTK */ + UCHAR WpsPinCode[8]; +#ifdef WAC_SUPPORT + BOOLEAN bEnableWAC; + NDIS_SPIN_LOCK WAC_PeerListSemLock; + LIST_HEADER WAC_PeerList; +#ifdef WAC_QOS_PRIORITY + NDIS_SPIN_LOCK WAC_ForcePriorityListSemLock; + LIST_HEADER WAC_ForcePriorityList; +#endif /* WAC_QOS_PRIORITY */ + USHORT CurrentStatus; +#ifdef CONFIG_AP_SUPPORT + PUCHAR pVendorInfoForProbeRsp; + UCHAR VendorInfoForProbeRspLen; + PUCHAR pVendorInfoForBeacon; + UCHAR VendorInfoForBeaconLen; +#endif /* CONFIG_AP_SUPPORT */ +#endif /* WAC_SUPPORT */ +} EASY_CONFIG_INFO, *PEASY_CONFIG_INFO; +#endif /* EASY_CONFIG_SETUP */ + +#ifdef CONFIG_AP_SUPPORT +typedef struct _MULTISSID_STRUCT { + +#ifdef HOSTAPD_SUPPORT + BOOLEAN Hostapd; + BOOLEAN HostapdWPS; +#endif + + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR SsidLen; + CHAR Ssid[MAX_LEN_OF_SSID]; + USHORT CapabilityInfo; + + UCHAR MaxStaNum; /* Limit the STA connection number per BSS */ + UCHAR StaCount; + + PNET_DEV MSSIDDev; + + NDIS_802_11_AUTHENTICATION_MODE AuthMode; + NDIS_802_11_WEP_STATUS WepStatus; + NDIS_802_11_WEP_STATUS GroupKeyWepStatus; + WPA_MIX_PAIR_CIPHER WpaMixPairCipher; + + HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode; /* For transmit phy setting in TXWI. */ + RT_HT_PHY_INFO DesiredHtPhyInfo; + DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; /* Desired transmit setting. this is for reading registry setting only. not useful. */ + BOOLEAN bAutoTxRateSwitch; + + /*MBSS_STATISTICS MbssStat;*/ + ULONG 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; + + /*CIPHER_KEY SharedKey[SHARE_KEY_NUM]; // ref pAd->SharedKey[BSS][4] */ + UCHAR DefaultKeyId; + + 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 */ + +/* ULONG TimBitmap; // bit0 for broadcast, 1 for AID1, 2 for AID2, ...so on */ +/* ULONG TimBitmap2; // b0 for AID32, b1 for AID33, ... and so on */ + UCHAR TimBitmaps[WLAN_MAX_NUM_OF_TIM]; + + /* WPA */ + UCHAR GMK[32]; + UCHAR PMK[32]; + UCHAR GTK[32]; +#ifdef DOT1X_SUPPORT + BOOLEAN IEEE8021X; + BOOLEAN PreAuth; +#endif /* DOT1X_SUPPORT */ + UCHAR GNonce[32]; + UCHAR PortSecured; + NDIS_802_11_PRIVACY_FILTER PrivacyFilter; + UCHAR BANClass3Data; + ULONG IsolateInterStaTraffic; + + UCHAR RSNIE_Len[2]; + UCHAR RSN_IE[2][MAX_LEN_OF_RSNIE]; + + /* for Group Rekey */ + RT_WPA_REKEY WPAREKEY; + ULONG REKEYCOUNTER; + RALINK_TIMER_STRUCT REKEYTimer; + UCHAR REKEYTimerRunning; + UINT8 RekeyCountDown; + +#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 */ + + UCHAR TimIELocationInBeacon; + UCHAR CapabilityInfoLocationInBeacon; + + /* For PMK Cache using */ + ULONG PMKCachePeriod; /* unit : jiffies */ + NDIS_AP_802_11_PMKID PMKIDCache; + + /* outgoing BEACON frame buffer and corresponding TXWI */ + /* PTXWI_STRUC BeaconTxWI; */ + CHAR BeaconBuf[MAX_BEACON_SIZE]; /* NOTE: BeaconBuf should be 4-byte aligned */ + + BOOLEAN bHideSsid; + UINT16 StationKeepAliveTime; /* unit: second */ + + /* VLAN related */ + BOOLEAN bVLAN_Tag; + USHORT VLAN_VID; + USHORT VLAN_Priority; + + RT_802_11_ACL AccessControlList; + + /* EDCA Qos */ + BOOLEAN bWmmCapable; /* 0:disable WMM, 1:enable WMM */ + BOOLEAN bDLSCapable; /* 0:disable DLS, 1:enable DLS */ + + /* + 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 */ + +#ifdef QOS_DLS_SUPPORT + UCHAR DlsPTK[64]; /* Due to windows dirver count on meetinghouse to handle 4-way shake */ +#endif /* QOS_DLS_SUPPORT */ + +#ifdef DOT1X_SUPPORT + /* 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 RTL865X_SOC + unsigned int mylinkid; +#endif + +#ifdef CONFIG_AP_SUPPORT + WSC_LV_INFO WscIEBeacon; + WSC_LV_INFO WscIEProbeResp; +#ifdef WSC_AP_SUPPORT + WSC_CTRL WscControl; + WSC_SECURITY_MODE WscSecurityMode; +#endif /* WSC_AP_SUPPORT */ + +#endif /* CONFIG_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 */ + + /* used in if beacon send or stop */ + BOOLEAN bBcnSntReq; + UCHAR BcnBufIdx; + + + + + + UCHAR PhyMode; + +#ifdef EASY_CONFIG_SETUP + EASY_CONFIG_INFO EasyConfigInfo; +#endif /* EASY_CONFIG_SETUP */ + + /* UAPSD information: such as enable or disable, do not remove */ + UAPSD_INFO UapsdInfo; + +#ifdef SPECIFIC_TX_POWER_SUPPORT + CHAR TxPwrAdj; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + +} MULTISSID_STRUCT, *PMULTISSID_STRUCT; +#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; /* PHY_11A, PHY_11B, PHY_11BG_MIXED, PHY_ABG_MIXED */ + UCHAR DesiredPhyMode; /* PHY_11A, PHY_11B, PHY_11BG_MIXED, PHY_ABG_MIXED */ + 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 SINGLE_SKU_V2 + UCHAR SkuChannel; +#endif /* SINGLE_SKU_V2 */ + + 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; + + + BOOLEAN bAPSDAC_BE; + BOOLEAN bAPSDAC_BK; + BOOLEAN bAPSDAC_VI; + BOOLEAN bAPSDAC_VO; + +#ifdef DOT11Z_TDLS_SUPPORT + BOOLEAN TDLS_bAPSDAC_BE; + BOOLEAN TDLS_bAPSDAC_BK; + BOOLEAN TDLS_bAPSDAC_VI; + BOOLEAN TDLS_bAPSDAC_VO; + UCHAR TDLS_MaxSPLength; +#endif /* DOT11Z_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 */ + /* move to MULTISSID_STRUCT for MBSS */ + /*HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI. */ + REG_TRANSMIT_SETTING RegTransmitSetting; /*registry transmit setting. this is for reading registry setting only. not useful. */ + /*UCHAR FixedTxMode; // Fixed Tx Mode (CCK, OFDM), for HT fixed tx mode (GF, MIX) , refer to RegTransmitSetting.field.HTMode */ + 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 RateSwitchTable */ + UCHAR TxRateTableSize; /* Valid Tx rate table size in RateSwitchTable */ + /*BOOLEAN bAutoTxRateSwitch; */ + 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 */ + 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 */ + 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 */ + 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 */ + 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 */ + /*UCHAR BASize; // USer desired BAWindowSize. Should not exceed our max capability */ + /*RT_HT_CAPABILITY SupportedHtPhy; */ + 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; +#endif /* DOT11N_DRAFT3 */ + + BOOLEAN bHTProtect; + BOOLEAN bMIMOPSEnable; + BOOLEAN bBADecline; + BOOLEAN bDisableReordering; + BOOLEAN bForty_Mhz_Intolerant; + BOOLEAN bExtChannelSwitchAnnouncement; + BOOLEAN bRcvBSSWidthTriggerEvents; + ULONG LastRcvBSSWidthTriggerEventsTime; + + UCHAR TxBASize; + + BOOLEAN bRalinkBurstMode; + UINT32 RestoreBurstMode; +#endif /* DOT11_N_SUPPORT */ + +#ifdef SYSTEM_LOG_SUPPORT + /* Enable wireless event */ + BOOLEAN bWirelessEvent; +#endif /* SYSTEM_LOG_SUPPORT */ + + BOOLEAN bWiFiTest; /* Enable this parameter for WiFi test */ + + /* 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 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 */ + +#if defined(RT305x)||defined(RT30xx) + /* request by Gary, for High Power issue */ + UCHAR HighPowerPatchDisabled; +#endif /* defined(RT305x)|| defined(RT30xx) */ + + BOOLEAN HT_DisallowTKIP; /* Restrict the encryption type in 11n HT mode */ + + BOOLEAN HT_Disable; /* 1: disable HT function; 0: enable HT function */ + +#if defined (RT2883) || defined (RT3883) + ULONG PhyRateLimit; /* PHY Rate limit in Mbps */ + INT FixedRate; /* Fix the rate during Rate Adaptation. FixedRate is ItemNo index into RateSwitch Table. -1 => disabled. */ + BOOLEAN FineAGC; /* Fine AGC enabled */ +#endif /* defined (RT2883) || defined (RT3883) */ + +#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 */ + BOOLEAN TrainUpRule; /* QuickDRS train up criterion: 0=>Throughput, 1=>PER, 2=> Throughput & PER */ + 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 */ +#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; + 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 */ +#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 */ + +#ifdef CONFIG_ZTE_RADIO_ONOFF + BOOLEAN bRadioEnable; +#endif /* CONFIG_ZTE_RADIO_ONOFF */ + +#if defined(MICROWAVE_OVEN_SUPPORT) || defined(DYNAMIC_VGA_SUPPORT) + MO_CFG_STRUCT MO_Cfg; /* data structure for mitigating microwave interference */ +#endif /* defined(MICROWAVE_OVEN_SUPPORT) || defined(DYNAMIC_VGA_SUPPORT) */ + BOOLEAN bEnTemperatureTrack; +} 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 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 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 */ + UINT16 TdlsSwitchTime; + UINT16 TdlsSwitchTimeout; + BOOLEAN TdlsForcePowerSaveWithAP; + BOOLEAN bTdlsNoticeAPPowerSave; + + RALINK_TIMER_STRUCT TdlsPeriodGoBackBaseChTimer; + RALINK_TIMER_STRUCT TdlsPeriodGoOffChTimer; + RALINK_TIMER_STRUCT TdlsResponderGoBackBaseChTimer; + RALINK_TIMER_STRUCT TdlsDisableChannelSwitchTimer; + + BOOLEAN bDoingPeriodChannelSwitch; + BOOLEAN bChannelSwitchUnSolRsp; + BOOLEAN bChannelSwitchInitiator; + BOOLEAN bTdlsCurrentDoingChannelSwitchWaitSuccess; + UCHAR TdlsTargetOffChannel; + UCHAR TdlsTargetOffChannelBW; + UCHAR TdlsCurrentChannel; + UCHAR TdlsCurrentChannelBW; + UCHAR TdlsCurrentOperateChannel; + UCHAR TdlsCurrentOperateChannelBW; + + UINT16 TdlsOffChannelDelay; + UCHAR TdlsChannelSwitchPairCount; + UCHAR TdlsChannelSwitchRetryCount; + ULONG TdlsGoBackStartTime; + ULONG TdlsGlobalSwitchTime; + ULONG TdlsGlobalSwitchTimeOut; + UCHAR TdlsSendNullFrameCount; + BOOLEAN TdlsChannelSwitchHWTimerRunning; + UCHAR TdlsChannelSwitchHWTimerCount; + 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 { + /* + 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 + */ + UCHAR RssiTrigger; + UCHAR RssiTriggerMode; /* RSSI_TRIGGERED_UPON_BELOW_THRESHOLD or RSSI_TRIGGERED_UPON_EXCCEED_THRESHOLD */ + USHORT DefaultListenCount; /* default listen count; */ + 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 */ + 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]; + + NDIS_802_11_PRIVACY_FILTER PrivacyFilter; /* PrivacyFilter enum for 802.1X */ + NDIS_802_11_AUTHENTICATION_MODE AuthMode; /* This should match to whatever microsoft defined */ + NDIS_802_11_WEP_STATUS WepStatus; + + /* 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; + + NDIS_802_11_WEP_STATUS GroupKeyWepStatus; + + 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 */ + + UCHAR DefaultKeyId; + +#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 */ + + /* WPA 802.1x port control, WPA_802_1X_PORT_SECURED, WPA_802_1X_PORT_NOT_SECURED */ + UCHAR PortSecured; + + /* 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 Last11bBeaconRxTime; /* OS's timestamp of the last 11B BEACON RX time */ + ULONG Last11gBeaconRxTime; /* OS's timestamp of the last 11G BEACON RX time */ + ULONG Last20NBeaconRxTime; /* OS's timestamp of the last 20MHz N 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 + BOOLEAN IEEE8021X; + 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; +#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; + + HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode; /* For transmit phy setting in TXWI. */ + DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; + RT_HT_PHY_INFO DesiredHtPhyInfo; + BOOLEAN bAutoTxRateSwitch; + +#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 */ + + + + + 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; + +#ifdef EASY_CONFIG_SETUP + EASY_CONFIG_INFO EasyConfigInfo; +#endif /* EASY_CONFIG_SETUP */ + + + + /* UAPSD information: such as enable or disable, do not remove */ + UAPSD_INFO UapsdInfo; + +} 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(pAd) or INFRA_ON(pAd) 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_HT_PHY_INFO SupportedPhyInfo; + RT_HT_CAPABILITY SupportedHtPhy; +} 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; + +typedef enum _MAC_ENTRY_OP_MODE_ { + ENTRY_OP_MODE_ERROR = 0x00, + ENTRY_OP_MODE_CLI = 0x01, /* Sta mode, set this TRUE after Linkup,too. */ + ENTRY_OP_MODE_WDS = 0x02, /* This is WDS Entry. only for AP mode. */ + ENTRY_OP_MODE_APCLI = 0x04, /* This is a AP-Client entry, only for AP mode which enable AP-Client functions. */ + ENTRY_OP_MODE_MESH = 0x08, /* Peer conect with us via mesh. */ + ENTRY_OP_MODE_DLS = 0x10, /* This is DLS Entry. only for STA mode. */ + ENTRY_OP_MODE_MAX = 0x20 +} MAC_ENTRY_OP_MODE; +#endif /* CONFIG_AP_SUPPORT */ + +/* 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 */ + +#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; +#ifdef P2P_SUPPORT + UINT32 P2PEntryType; /* 0:Invalid, 1:P2P_GO, 2:P2P_CLI */ +#endif /* P2P_SUPPORT */ + BOOLEAN isCached; + BOOLEAN bIAmBadAtheros; /* Flag if this is Atheros chip that has IOT problem. We need to turn on RTS/CTS protection. */ + + /* 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 */ + + /*jan for wpa */ + /* record which entry revoke MIC Failure , if it leaves the BSS itself, AP won't update aMICFailTime MIB */ + UCHAR CMTimerRunning; + UCHAR apidx; /* MBSS number */ + 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; +#ifdef TXBF_SUPPORT + RALINK_TIMER_STRUCT eTxBfProbeTimer; +#endif /* TXBF_SUPPORT */ + 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; + NDIS_802_11_PRIVACY_FILTER PrivacyFilter; /* PrivacyFilter enum for 802.1X */ + CIPHER_KEY PairwiseKey; + PVOID pAd; + 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 Addr[MAC_ADDR_LEN]; + UCHAR HdrAddr1[MAC_ADDR_LEN]; + UCHAR HdrAddr2[MAC_ADDR_LEN]; + UCHAR HdrAddr3[MAC_ADDR_LEN]; + UCHAR PsMode; + UCHAR FlgPsModeIsWakeForAWhile; /* wake up for a while until a condition */ + UCHAR VirtualTimeout; /* peer power save virtual timeout */ + SST Sst; + AUTH_STATE AuthState; /* for SHARED KEY authentication state machine used only */ + BOOLEAN IsReassocSta; /* Indicate whether this is a reassociation procedure */ + USHORT Aid; + USHORT CapabilityInfo; + UCHAR LastRssi; + ULONG NoDataIdleCount; + UINT16 StationKeepAliveCount; /* unit: second */ + ULONG PsQIdleCount; + QUEUE_HEADER PsQueue; + + 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 DOT11_N_SUPPORT + BOOLEAN bSendBAR; + USHORT NoBADataCountDown; + + UINT32 CachedBuf[16]; /* UINT (4 bytes) for alignment */ + +#ifdef TXBF_SUPPORT + COUNTER_TXBF TxBFCounters; /* TxBF Statistics */ + UINT LastETxCount; /* Used to compute %BF statistics */ + UINT LastITxCount; + UINT LastTxCount; +#endif /* TXBF_SUPPORT */ +#endif /* DOT11_N_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; + BOOLEAN bDlsInit; + +/*==================================================== */ +/*WDS entry needs these */ +/* if ValidAsWDS==TRUE, MatchWDSTabIdx is the index in WdsTab.MacTab */ + UINT MatchWDSTabIdx; + UCHAR MaxSupportedRate; + UCHAR CurrTxRate; + UCHAR CurrTxRateIndex; + UCHAR lastRateIdx; + UCHAR *pTable; /* Pointer to this entry's Tx Rate Table */ + +#ifdef NEW_RATE_ADAPT_SUPPORT + UCHAR lowTrafficCount; + UCHAR fewPktsCnt; + BOOLEAN perThrdAdj; + UCHAR mcsGroup;/*the mcs group to be tried */ +#endif /* NEW_RATE_ADAPT_SUPPORT */ + enum RATE_ADAPT_ALG rateAlg; + +#ifdef PEER_DELBA_TX_ADAPT + BOOLEAN 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_TX_RATE_SWITCH *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; + INT sndg0Snr0, sndg0Snr1, sndg0Snr2; + UCHAR sndg0Mcs; +#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; + + 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 +#endif /* TXBF_SUPPORT */ + + /* to record the each TX rate's quality. 0 is best, the bigger the worse. */ + USHORT TxQuality[MAX_TX_RATE_INDEX + 1]; + UINT32 OneSecTxNoRetryOkCount; + UINT32 OneSecTxRetryOkCount; + UINT32 OneSecTxFailCount; + UINT32 OneSecRxLGICount; // unicast-to-me Long GI count + UINT32 OneSecRxSGICount; // unicast-to-me Short GI count + +#ifdef FIFO_EXT_SUPPORT + UINT32 fifoTxSucCnt; + UINT32 fifoTxRtyCnt; +#endif /* FIFO_EXT_SUPPORT */ + + + 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 ContinueTxFailCnt; + UINT32 CurrTxRateStableTime; /* # of second in current TX rate */ + UCHAR TxRateUpPenalty; /* extra # of second penalty due to last unstable condition */ +#ifdef WDS_SUPPORT + BOOLEAN LockEntryTx; /* TRUE = block to WDS Entry traffic, FALSE = not. */ +#endif /* WDS_SUPPORT */ + ULONG TimeStamp_toTxRing; + +/*==================================================== */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + UINT MatchAPCLITabIdx; /* indicate the index in ApCfg.ApCliTab. */ +#endif /* APCLI_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 */ + +#ifdef MESH_SUPPORT + UINT MatchMeshTabIdx; /* indicate the index in pAd->MeshTab. */ +#endif /* MESH_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT + UINT MatchDlsEntryIdx; /* indicate the index in pAd->StaCfg.DLSEntry */ +#endif /* QOS_DLS_SUPPORT */ +#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 */ + /* 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, MinHTPhyMode; /* For transmit phy setting in TXWI. */ + +#ifdef DOT11_N_SUPPORT + /* HT EWC MIMO-N used parameters */ + 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 */ + + /* 802.11n features. */ + UCHAR MpduDensity; + UCHAR MaxRAmpduFactor; + UCHAR AMsduSize; + UCHAR MmpsMode; /* MIMO power save more. */ + + HT_CAPABILITY_IE HTCapability; + +#ifdef DOT11N_DRAFT3 + UCHAR BSS2040CoexistenceMgmtSupport; + BOOLEAN bForty_Mhz_Intolerant; +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + + BOOLEAN bAutoTxRateSwitch; + + UCHAR RateLen; + struct _MAC_TABLE_ENTRY *pNext; + USHORT TxSeq[NUM_OF_TID]; + USHORT NonQosDataSeq; + INT TxBarSeq[NUM_OF_TID]; + + RSSI_SAMPLE RssiSample; + UINT32 LastRxRate; + SHORT freqOffset; /* Last RXWI FOFFSET */ + SHORT freqOffsetValid; /* Set when freqOffset field has been updated */ + +#if defined (RT2883) || defined (RT3883) + INT32 BF_SNR[3]; /* Last RXWI BF SNR. Units=0.25 dB */ +#endif /* defined (RT2883) || defined (RT3883) */ + + BOOLEAN bWscCapable; + UCHAR Receive_EapolStart_EapRspId; +#ifdef EASY_CONFIG_SETUP + BOOLEAN bRaAutoWpsCapable; +#endif /* EASY_CONFIG_SETUP */ +#ifdef WAC_SUPPORT + BOOLEAN bSamsungAutoWpsCapable; +#ifdef WAC_QOS_PRIORITY + BOOLEAN bSamsungForcePriority; +#endif /* WAC_QOS_PRIORITY */ +#endif /* WAC_SUPPORT */ + + UINT32 TXMCSExpected[MAX_MCS_SET]; + UINT32 TXMCSSuccessful[MAX_MCS_SET]; + UINT32 TXMCSFailed[MAX_MCS_SET]; + UINT32 TXMCSAutoFallBack[MAX_MCS_SET][MAX_MCS_SET]; + +#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 */ + + + ULONG AssocDeadLine; + + + + + ULONG ChannelQuality; /* 0..100, Channel Quality Indication for Roaming */ + + +#ifdef CONFIG_AP_SUPPORT + MULTISSID_STRUCT *pMbss; +#endif /* CONFIG_AP_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 */ + +#ifdef AGS_SUPPORT + AGS_CONTROL AGSCtrl; /* AGS control */ +#endif /* AGS_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + LARGE_INTEGER TxPackets; + LARGE_INTEGER RxPackets; + ULONG TxBytes; + ULONG RxBytes; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef P2P_SUPPORT + P2P_ENTRY_PARM P2pInfo; + BOOLEAN bP2pClient; +#endif /* P2P_SUPPORT */ +#ifdef IWSC_SUPPORT + BOOLEAN bIWscSmpbcAccept; +#endif // IWSC_SUPPORT // + +UCHAR SupportRateMode; /* 1: CCK 2:OFDM 4: HT */ +BOOLEAN SupportCCKMCS[MAX_LEN_OF_CCK_RATES]; +BOOLEAN SupportOFDMMCS[MAX_LEN_OF_OFDM_RATES]; +BOOLEAN SupportHTMCS[MAX_LEN_OF_HT_RATES]; + +#ifdef DOT11Z_TDLS_SUPPORT + UINT16 TdlsTxFailCount; + UINT32 TdlsKeyLifeTimeCount; + UCHAR MatchTdlsEntryIdx; // indicate the index in pAd->StaCfg.DLSEntry +#endif // DOT11Z_TDLS_SUPPORT // +} MAC_TABLE_ENTRY, *PMAC_TABLE_ENTRY; + +typedef struct _MAC_TABLE { + MAC_TABLE_ENTRY *Hash[HASH_TABLE_SIZE]; +#ifdef MAC_REPEATER_SUPPORT + MAC_TABLE_ENTRY Content[MAX_MAC_TABLE_SIZE_WITH_REPEATER]; +#else + MAC_TABLE_ENTRY Content[MAX_LEN_OF_MAC_TABLE]; +#endif /* MAC_REPEATER_SUPPORT */ + 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 */ + BOOLEAN fAnyStaFortyIntolerant; /* Check if still has any station set the Intolerant bit on! */ + 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 */ + + USHORT MsduLifeTime; /* life time for PS packet */ + +#ifdef WAPI_SUPPORT + BOOLEAN fAnyWapiStation; +#endif /* WAPI_SUPPORT */ + + BOOLEAN fMcastPsQEnable; +} MAC_TABLE, *PMAC_TABLE; + + + +#ifdef CONFIG_AP_SUPPORT +/*************************************************************************** + * AP WDS related data structures + **************************************************************************/ +#ifdef WDS_SUPPORT +typedef struct _WDS_COUNTER { + LARGE_INTEGER ReceivedFragmentCount; + LARGE_INTEGER TransmittedFragmentCount; + ULONG ReceivedByteCount; + ULONG TransmittedByteCount; + ULONG RxErrors; + ULONG TxErrors; + LARGE_INTEGER MulticastReceivedFrameCount; + ULONG OneCollision; + ULONG MoreCollisions; + ULONG RxNoBuffer; + ULONG RcvAlignmentErrors; +} 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 { + PNET_DEV dev; + UCHAR Valid; + UCHAR PhyMode; + UCHAR PeerWdsAddr[MAC_ADDR_LEN]; + UCHAR MacTabMatchWCID; /* ASIC */ + NDIS_802_11_WEP_STATUS WepStatus; + UCHAR KeyIdx; + CIPHER_KEY WdsKey; + HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode; + RT_HT_PHY_INFO DesiredHtPhyInfo; + BOOLEAN bAutoTxRateSwitch; + DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; /* Desired transmit setting. */ + WDS_COUNTER WdsCounter; + +#ifdef WDS_VLAN_SUPPORT + /* VLAN */ + USHORT VLAN_VID; + USHORT VLAN_Priority; +#endif /* WDS_VLAN_SUPPORT */ +} RT_802_11_WDS_ENTRY, *PRT_802_11_WDS_ENTRY; + +typedef struct _WDS_TABLE { + UCHAR Mode; + ULONG 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; + RALINK_TIMER_STRUCT ReptCliResetTimer; + + 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[ETH_LENGTH_OF_ADDRESS]; + UCHAR CurrentAddress[ETH_LENGTH_OF_ADDRESS]; + 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; +#endif /* MAC_REPEATER_SUPPORT */ + +/*************************************************************************** + * AP APCLI related data structures + **************************************************************************/ +typedef struct _APCLI_STRUCT { + PNET_DEV dev; +#ifdef RTL865X_SOC + unsigned int mylinkid; +#endif + 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 ApCliMlmeAux; /* 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]; + + UCHAR CfgSsidLen; + CHAR CfgSsid[MAX_LEN_OF_SSID]; + UCHAR CfgApCliBssid[ETH_LENGTH_OF_ADDRESS]; + UCHAR CurrentAddress[ETH_LENGTH_OF_ADDRESS]; + + ULONG ApCliRcvBeaconTime; + ULONG ApCliLinkUpTime; + USHORT ApCliBeaconPeriod; + + ULONG CtrlCurrState; + ULONG SyncCurrState; + ULONG AuthCurrState; + ULONG AssocCurrState; + ULONG WpaPskCurrState; + +#ifdef APCLI_AUTO_CONNECT_SUPPORT + USHORT ProbeReqCnt; +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + USHORT AuthReqCnt; + USHORT AssocReqCnt; + + ULONG ClientStatusFlags; + UCHAR MpduDensity; + + NDIS_802_11_AUTHENTICATION_MODE AuthMode; /* This should match to whatever microsoft defined */ + NDIS_802_11_WEP_STATUS WepStatus; + + /* 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]; + UCHAR DefaultKeyId; + + /* WPA 802.1x port control, WPA_802_1X_PORT_SECURED, WPA_802_1X_PORT_NOT_SECURED */ + /*UCHAR PortSecured; */ + + /* 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 */ + /*WPA_STATE WpaState; // Default is SS_NOTUSE */ + UCHAR ReplayCounter[8]; + /*UCHAR ANonce[32]; // ANonce for WPA-PSK from authenticator */ + UCHAR SNonce[32]; /* SNonce for WPA-PSK */ + UCHAR GNonce[32]; /* GNonce for WPA-PSK from authenticator */ + +#ifdef WSC_AP_SUPPORT + WSC_CTRL WscControl; +#endif /* WSC_AP_SUPPORT */ + + HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode; + RT_HT_PHY_INFO DesiredHtPhyInfo; + BOOLEAN bAutoTxRateSwitch; + DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; /* Desired transmit setting. */ + UCHAR RxMcsSet[16]; +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT + BOOLEAN IEEE8021X; + BOOLEAN IEEE8021x_required_keys; + CIPHER_KEY DesireSharedKey[4]; // Record user desired WEP keys + UCHAR DesireSharedKeyId; + UCHAR WpaSupplicantUP; + UCHAR WpaSupplicantScanCount; + BOOLEAN bRSN_IE_FromWpaSupplicant; + BOOLEAN bLostAp; + UCHAR *pWpsProbeReqIe; + UINT WpsProbeReqIeLen; + UCHAR *pWpaAssocIe; + UINT WpaAssocIeLen; + 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/*APCLI_WPA_SUPPLICANT_SUPPORT*/ + +#ifdef P2P_SUPPORT + BOOLEAN bP2pClient; +#endif /* P2P_SUPPORT */ + + PSPOLL_FRAME PsPollFrame; + HEADER_802_11 NullFrame; + + UAPSD_INFO UapsdInfo; +#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 */ + UCHAR LinkIdx; + PVOID pAd; +} APCLI_STRUCT, *PAPCLI_STRUCT; + +typedef struct _AP_ADMIN_CONFIG { + USHORT CapabilityInfo; + /* Multiple SSID */ + UCHAR BssidNum; + UCHAR MacMask; + MULTISSID_STRUCT MBSSID[HW_BEACON_MAX_NUM]; + ULONG IsolateInterStaTrafficBTNBSSID; + +#ifdef APCLI_SUPPORT + UCHAR ApCliInfRunned; /* Number of ApClient interface which was running. value from 0 to MAX_APCLI_INTERFACE */ + BOOLEAN FlgApCliIsUapsdInfoUpdated; + APCLI_STRUCT ApCliTab[MAX_APCLI_NUM]; /*AP-client */ + RALINK_TIMER_STRUCT ApCliScanTimer; +#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[ETH_LENGTH_OF_ADDRESS]; + REPEATER_CTRL_STRUCT ReptControl; +#endif /* MAC_REPEATER_SUPPORT */ + + /* 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 */ + UINT32 ScanChannelCnt; + UINT32 LastScanChannel; + BOOLEAN bImprovedScan; +#endif /* AP_SCAN_SUPPORT */ + BOOLEAN bAvoidDfsChannel; /* 0: disable, 1: enable */ + BOOLEAN bIsolateInterStaTraffic; + 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 RcvdAuthCount; + UINT32 RcvdAssocReqCount; + UINT32 RcvdReassocReqCount; + UINT32 RcvdProbeReqCount; + UINT32 RcvdDisassocCount; + UINT32 RcvdDeauthCount; + UINT32 RcvdEapReqCount; + + 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 CLIENT_WDS + NDIS_SPIN_LOCK CliWdsTabLock; + PCLIWDS_PROXY_ENTRY pCliWdsEntryPool; + LIST_HEADER CliWdsEntryFreeList; + LIST_HEADER CliWdsProxyTab[CLIWDS_HASH_TAB_SIZE]; +#endif /* CLIENT_WDS */ + +#ifdef DOT11_N_SUPPORT +#ifdef GREENAP_SUPPORT + UCHAR GreenAPLevel; + BOOLEAN bGreenAPEnable; + BOOLEAN bGreenAPActive; +#endif /* GREENAP_SUPPORT */ + + ULONG MAX_PSDU_LEN; /* Maximum PSDU length */ +#endif /* DOT11_N_SUPPORT */ + + UCHAR EntryClientCount; + +#ifdef MAC_REPEATER_SUPPORT + BOOLEAN bMACRepeaterEn; + UCHAR MACRepeaterOuiMode; + UINT8 EthApCliIdx; + UCHAR RepeaterCliSize; +#endif /* MAC_REPEATER_SUPPORT */ +#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 NINTENDO_AP +typedef struct _NINDO_CTRL_BLOCK { + + RT_NINTENDO_TABLE DS_TABLE; + +#ifdef CHIP25XX + spinlock_t NINTENDO_TABLE_Lock; +#else + NDIS_SPIN_LOCK NINTENDO_TABLE_Lock; +#endif /* CHIP25XX */ + + UCHAR NINTENDO_UP_BUFFER[512]; + UCHAR Local_KeyIdx; + CIPHER_KEY Local_SharedKey; + UCHAR Local_bHideSsid; + UCHAR Local_AuthMode; + UCHAR Local_WepStatus; + USHORT Local_CapabilityInfo; +} NINDO_CTRL_BLOCK; +#endif /* NINTENDO_AP */ +#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 */ + +#ifdef MESH_SUPPORT +typedef struct _MESH_STRUCT { + PNET_DEV dev; + UCHAR HostName[MAX_HOST_NAME_LEN]; + UCHAR CurrentAddress[ETH_LENGTH_OF_ADDRESS]; + UCHAR OpMode; + UINT8 TTL; + BOOLEAN MeshAutoLink; + BOOLEAN UCGEnable; + UCHAR MeshChannel; +#ifdef DOT11_N_SUPPORT + UINT8 ExtChOffset; +#endif /* DOT11_N_SUPPORT */ + ULONG MeshMaxTxRate; + ULONG MeshMultiCastAgeOut; + + UCHAR MeshId[MAX_MESH_ID_LEN]; + UCHAR MeshIdLen; + + CHAR LastRssi; + + /*UCHAR MKDDID[MAC_ADDR_LEN]; */ + MESH_SECURITY_CAPABILITY_IE LocalMSCIE; + + UINT32 MeshSeq; + UINT32 MeshPreqID; + UINT32 MeshOriginatorDsn; + + UINT8 PathProtocolId; /* 0: mean HWMP. */ + UINT8 PathMetricId; /* 0: airtime. */ + UINT8 ContgesionCtrlId; + MESH_CAPABILITY MeshCapability; + UINT32 CPI; /* channel precedence indicator. */ + UINT32 NewCPI; /* channel precedence indicator. */ + PMESH_NEIGHBOR_TAB pMeshNeighborTab; /* all neighbor MPs list. */ + MESH_LINK MeshLink[MAX_MESH_LINKS]; /* Current established peer link list. */ + UINT8 LinkSize; /* record how much links establish already. */ + + NDIS_SPIN_LOCK MeshEntryTabLock; + PMESH_ENTRY_TABLE pMeshEntryTab; + + NDIS_SPIN_LOCK MeshRouteTabLock; + /*MESH_ROUTING_TABLE MeshRouteTab; */ + PMESH_ROUTING_TABLE pMeshRouteTab; + + UCHAR bMeshPortal; + NDIS_SPIN_LOCK MeshProxyTabLock; + PMESH_PROXY_ENTRY_TABLE pMeshProxyTab; + + NDIS_SPIN_LOCK MeshBMPktTabLock; + PMESH_BMPKTSIG_TAB pBMPktSigTab; + + NDIS_SPIN_LOCK MultipathTabLock; + PMESH_MULTIPATH_ENTRY pMultipathEntryPool; + LIST_HEADER MultipathEntryFreeList; + + CHAR BeaconBuf[MAX_BEACON_SIZE]; /* NOTE: BeaconBuf should be 4-byte aligned */ + UCHAR TimIELocationInBeacon; + UCHAR CapabilityInfoLocationInBeacon; + USHORT CapabilityInfo; + + NDIS_802_11_AUTHENTICATION_MODE AuthMode; + NDIS_802_11_WEP_STATUS WepStatus; + BOOLEAN EasyMeshSecurity; + UCHAR WPAPassPhraseKey[64]; + UCHAR WPAPassPhraseKeyLen; + UCHAR DesiredWepKey[26]; + UCHAR DesiredWepKeyLen; + UCHAR PMK[32]; + UCHAR DefaultKeyId; + CIPHER_KEY SharedKey; + + /* 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; + UCHAR PMKID[LEN_PMKID]; /*PMK-MAName(sender), the identifier of the currently-valid PMK-MA belonging to the key */ + /*hierarchy created by the local MP during a prior Initial MSA Authentiction. */ + UCHAR PMKID_Len; + + UCHAR LocalMpInitialMsaLink; /* 0 indicates this MP is MKD or this MP doesn't complete its Initial MSA */ + /* 1~4 indicates which MESHLINK is its Initial MSA link. */ + + BOOLEAN bInitialMsaDone; /* indicate that the MP had completed the Initial MSA Authentication */ + BOOLEAN bKeyholderDone; /* indicate that the MP had completed key holder handshake and became MA */ + BOOLEAN bConnectedToMKD; /* indicate that the MP has a valid path to the MKD */ + /* and a current security association with the MKD */ + BOOLEAN MeshOnly; /* 1: means mesh only mode. decline scan request from rausb0. */ + + HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode; + DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; /* Desired transmit setting. this is for reading registry setting only. not useful. */ + RT_HT_PHY_INFO DesiredHtPhyInfo; + BOOLEAN bAutoTxRateSwitch; + + MESH_CTRL_STATE CtrlCurrentState; + RALINK_TIMER_STRUCT PldTimer, McsTimer; + + BOOLEAN bBcnSntReq; + UCHAR BcnBufIdx; +} MESH_STRUCT, +*PMESH_STRUCT; +#endif /* MESH_SUPPORT */ + +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 */ +typedef struct _RtmpDiagStrcut_ { /* Diagnosis Related element */ + unsigned char inited; + unsigned char qIdx; + unsigned char ArrayStartIdx; + unsigned char ArrayCurIdx; + /* Tx Related Count */ + USHORT TxDataCnt[DIAGNOSE_TIME]; + USHORT TxFailCnt[DIAGNOSE_TIME]; +/* USHORT TxDescCnt[DIAGNOSE_TIME][16]; // TxDesc queue length in scale of 0~14, >=15 */ + USHORT TxDescCnt[DIAGNOSE_TIME][24]; /* 3*3 // TxDesc queue length in scale of 0~14, >=15 */ +/* USHORT TxMcsCnt[DIAGNOSE_TIME][16]; // TxDate MCS Count in range from 0 to 15, step in 1. */ + USHORT TxMcsCnt[DIAGNOSE_TIME][MAX_MCS_SET]; /* 3*3 */ + USHORT TxSWQueCnt[DIAGNOSE_TIME][9]; /* TxSwQueue length in scale of 0, 1, 2, 3, 4, 5, 6, 7, >=8 */ + + USHORT TxAggCnt[DIAGNOSE_TIME]; + USHORT TxNonAggCnt[DIAGNOSE_TIME]; +/* USHORT TxAMPDUCnt[DIAGNOSE_TIME][16]; // 10 sec, TxDMA APMDU Aggregation count in range from 0 to 15, in setp of 1. */ + USHORT TxAMPDUCnt[DIAGNOSE_TIME][MAX_MCS_SET]; /* 3*3 // 10 sec, TxDMA APMDU Aggregation count in range from 0 to 15, in setp of 1. */ + USHORT TxRalinkCnt[DIAGNOSE_TIME]; /* TxRalink Aggregation Count in 1 sec scale. */ + USHORT TxAMSDUCnt[DIAGNOSE_TIME]; /* TxAMSUD Aggregation Count in 1 sec scale. */ + + /* Rx Related Count */ + USHORT RxDataCnt[DIAGNOSE_TIME]; /* Rx Total Data count. */ + USHORT RxCrcErrCnt[DIAGNOSE_TIME]; +/* USHORT RxMcsCnt[DIAGNOSE_TIME][16]; // Rx MCS Count in range from 0 to 15, step in 1. */ + USHORT RxMcsCnt[DIAGNOSE_TIME][MAX_MCS_SET]; /* 3*3 */ +} 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 */ +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][33]; + 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 + +#ifdef RT2883 +#undef MAX_TX_PWR_CONTROL_OVER_MAC_REGISTERS +#define MAX_TX_PWR_CONTROL_OVER_MAC_REGISTERS 12 +#endif /* RT2883 */ + +#ifdef RT3883 +#undef MAX_TX_PWR_CONTROL_OVER_MAC_REGISTERS +#define MAX_TX_PWR_CONTROL_OVER_MAC_REGISTERS 15 +#endif /* RT3883 */ + +/* */ +/* 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 */ +#ifdef WOW_SUPPORT +#endif /* 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; + + + + +typedef struct _BBP_RESET_CTL +{ +#define BBP_RECORD_NUM 47 + REG_PAIR BBPRegDB[BBP_RECORD_NUM]; + BOOLEAN AsicCheckEn; +} BBP_RESET_CTL, *PBBP_RESET_CTL; + +/* */ +/* The miniport adapter structure */ +/* */ +struct _RTMP_ADAPTER { + PVOID OS_Cookie; /* save specific structure relative to OS */ + PNET_DEV net_dev; + ULONG VirtualIfCnt; + + RTMP_CHIP_OP chipOps; + RTMP_CHIP_CAP chipCap; + +#ifdef CONFIG_STA_SUPPORT + USHORT ThisTbttNumToNextWakeUp; +#endif /* CONFIG_STA_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 */ + +#ifdef RTMP_MAC_PCI +/*****************************************************************************************/ +/* PCI related parameters */ +/*****************************************************************************************/ + PUCHAR CSRBaseAddress; /* PCI MMIO Base Address, all access will use */ + unsigned int irq_num; +#ifdef CONFIG_STA_SUPPORT + USHORT LnkCtrlBitMask; + USHORT RLnkCtrlConfiguration; + USHORT RLnkCtrlOffset; + USHORT HostLnkCtrlConfiguration; + USHORT HostLnkCtrlOffset; + USHORT PCIePowerSaveLevel; + 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. */ + + UINT int_enable_reg; + UINT int_disable_mask; + UINT int_pending; + + RTMP_DMABUF TxBufSpace[NUM_OF_TX_RING]; /* Shared memory of all 1st pre-allocated TxBuf associated with each TXD */ + RTMP_DMABUF RxDescRing; /* 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~4 + HCCA */ + + NDIS_SPIN_LOCK LockInterrupt; +#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; + + +/*****************************************************************************************/ +/* RBUS related parameters */ +/*****************************************************************************************/ +#ifdef RTMP_RBUS_SUPPORT + /* resource for software backlog queues */ + NDIS_SPIN_LOCK page_lock; /* for nat speedup by bruce */ +#endif /* RTMP_RBUS_SUPPORT */ + +/*****************************************************************************************/ +/* Both PCI/USB related parameters */ +/*****************************************************************************************/ + /*RTMP_DEV_INFO chipInfo; */ + RTMP_INF_TYPE infType; + +/*****************************************************************************************/ +/* Driver Mgmt related parameters */ +/*****************************************************************************************/ + 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]; + + + /* 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; + + RTMP_DMABUF MgmtDescRing; /* Shared memory for MGMT descriptors */ + RTMP_MGMT_RING MgmtRing; + NDIS_SPIN_LOCK MgmtRingLock; /* Prio Ring spinlock */ + + UCHAR LastMCUCmd; + +/*****************************************************************************************/ +/* Rx related parameters */ +/*****************************************************************************************/ + +#ifdef RTMP_MAC_PCI + RTMP_RX_RING RxRing; + NDIS_SPIN_LOCK RxRingLock; /* Rx Ring spinlock */ +#endif /* RTMP_MAC_PCI */ + + +/*****************************************************************************************/ +/* ASIC related parameters */ +/*****************************************************************************************/ + UINT32 MACVersion; /* MAC version. Record rt2860C(0x28600100) or rt2860D (0x28600101).. */ + + /* --------------------------- */ + /* E2PROM */ + /* --------------------------- */ + 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]; +#ifdef TXBF_SUPPORT + USHORT EEPROMITxBFCalParams[6]; +#endif /* TXBF_SUPPORT */ + UCHAR EEPROMAddressNum; /* 93c46=6 93c66=8 */ + BOOLEAN EepromAccess; + UCHAR EFuseTag; + + /* --------------------------- */ + /* BBP Control */ + /* --------------------------- */ + UCHAR BbpWriteLatch[MAX_BBP_ID + 1]; /* record last BBP register value written via BBP_IO_WRITE/BBP_IO_WRITE_VY_REG_ID */ + CHAR BbpRssiToDbmDelta; /* change from UCHAR to CHAR for high power */ + BBP_R66_TUNING BbpTuning; + + /* ---------------------------- */ + /* RFIC control */ + /* ---------------------------- */ + UCHAR RfIcType; /* RFIC_xxx */ + ULONG RfFreqOffset; /* Frequency offset for channel switching */ + +#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 */ + + RTMP_RF_REGS LatchRfRegs; /* latch th latest RF programming value since RF IC doesn't support READ */ + + 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; + + /* This soft Rx Antenna Diversity mechanism is used only when user set */ + /* RX Antenna = DIVERSITY ON */ + SOFT_RX_ANT_DIVERSITY RxAnt; + + 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 */ + +#ifdef RT3883 + BOOLEAN bTxPwrRangeExt; +#endif /* RT3883 */ + + + UCHAR ChannelListNum; /* number of channel in ChannelList[] */ + UCHAR Bbp94; + 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]; + + + BOOLEAN bAutoTxAgcA; /* Enable driver auto Tx Agc control */ + UCHAR TssiRefA; /* Store Tssi reference value as 25 temperature. */ + UCHAR TssiPlusBoundaryA[5]; /* Tssi boundary for increase Tx power to compensate. */ + UCHAR TssiMinusBoundaryA[5]; /* Tssi boundary for decrease Tx power to compensate. */ + 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 */ +#ifdef RT6352 + 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; /* calculated by MP ATE temperature(e2p[77h]) */ +#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) + TX_POWER_CONTROL TxPowerCtrl; /* The Tx power control using the internal ALC */ +#endif /* RTMP_INTERNAL_TX_ALC || RTMP_TEMPERATURE_COMPENSATION */ + + UCHAR rf_pa_mode_over_cck[4]; + UCHAR rf_pa_mode_over_ofdm[8]; + UCHAR rf_pa_mode_over_ht[16]; + + +#ifdef THERMAL_PROTECT_SUPPORT + BOOLEAN force_one_tx_stream; + INT32 last_thermal_pro_temp; + INT32 thermal_pro_criteria; +#endif /* THERMAL_PROTECT_SUPPORT */ + + signed char BGRssiOffset0; /* Store B/G RSSI#0 Offset value on EEPROM 0x46h */ + signed char BGRssiOffset1; /* Store B/G RSSI#1 Offset value */ + signed char BGRssiOffset2; /* Store B/G RSSI#2 Offset value */ + + signed char ARssiOffset0; /* Store A RSSI#0 Offset value on EEPROM 0x4Ah */ + signed char ARssiOffset1; /* Store A RSSI#1 Offset value */ + signed char ARssiOffset2; /* Store A RSSI#2 Offset value */ + + 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 */ + + +#ifdef LED_CONTROL_SUPPORT + /* LED control */ + LED_CONTROL LedCntl; +#endif /* LED_CONTROL_SUPPORT */ + + /* ---------------------------- */ + /* MAC control */ + /* ---------------------------- */ +#ifdef SPECIFIC_BCN_BUF_SUPPORT + UCHAR ShrMSel; + NDIS_SPIN_LOCK ShrMemLock; +#endif /* SPECIFIC_BCN_BUF_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 MESH_SUPPORT + BOOLEAN flg_mesh_init; +#endif /* MESH_SUPPORT */ + +#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 */ + +/*=========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 APCLI_SUPPORT + //MLME_AUX ApCliMlmeAux; /* temporary settings used during MLME state machine */ +#endif /* APCLI_SUPPORT */ + +#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 */ + +/*#ifdef AUTO_CH_SELECT_ENHANCE */ + PBSSINFO pBssInfoTab; + PCHANNELINFO pChannelInfo; +/*#endif // AUTO_CH_SELECT_ENHANCE */ + +#ifdef NINTENDO_AP + UCHAR NINTENDO_WEP_SEED[NINTENDO_SSID_NICKNAME_LN]; + UCHAR NINTENDO_WEP_KEY[16]; + BOOLEAN bNintendoCapable; +#endif /* NINTENDO_AP */ + +#endif /* CONFIG_AP_SUPPORT */ + +/*=======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=========== */ + /* OP mode: either AP or STA */ + UCHAR OpMode; /* OPMODE_STA, OPMODE_AP */ + + 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 */ + /* ------------------------------------------------------ */ + 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) + BSS_TABLE ScanTab; /* store the latest SCAN result */ +#endif /* defined(AP_SCAN_SUPPORT) || defined(CONFIG_STA_SUPPORT) */ + + /*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; +#endif /* DOT11_N_SUPPORT */ + + /* 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] */ + + /* RX re-assembly buffer for fragmentation */ + FRAGMENT_FRAME FragFrame; /* Frame storage for fragment frame */ + + /* 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 */ + PRIVATE_STRUC PrivateInfo; /* Private information & counters */ + + /* 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 */ + ULONG SystemErrorBitmap; /* b0: E2PROM version error */ + + /*+++Didn't used anymore */ + ULONG MacIcVersion; /* MAC/BBP serial interface issue solved after ver.D */ + /*--- */ + +#ifdef SYSTEM_LOG_SUPPORT + /* --------------------------- */ + /* System event log */ + /* --------------------------- */ + RT_802_11_EVENT_TABLE EventTab; +#endif /* SYSTEM_LOG_SUPPORT */ + + BOOLEAN HTCEnable; + + /*****************************************************************************************/ + /* Statistic related parameters */ + /*****************************************************************************************/ + + BOOLEAN bUpdateBcnCntDone; + + ULONG macwd; + BOOLEAN bEnableMacWD; + /* ---------------------------- */ + /* DEBUG paramerts */ + /* ---------------------------- */ + + /* ---------------------------- */ + /* rt2860c emulation-use Parameters */ + /* ---------------------------- */ + /*ULONG rtsaccu[30]; */ + /*ULONG ctsaccu[30]; */ + /*ULONG cfendaccu[30]; */ + /*ULONG bacontent[16]; */ + /*ULONG rxint[RX_RING_SIZE+1]; */ + /*UCHAR rcvba[60]; */ + BOOLEAN bLinkAdapt; + BOOLEAN bForcePrintTX; + BOOLEAN bForcePrintRX; + /*BOOLEAN bDisablescanning; //defined in RT2870 USB */ + 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; + /*--- */ + + struct wificonf WIFItestbed; + + UCHAR TssiGain; +#ifdef RALINK_ATE + ATE_INFO ate; +#endif /* RALINK_ATE */ + +#ifdef DOT11_N_SUPPORT + struct reordering_mpdu_pool mpdu_blk_pool; +#endif /* DOT11_N_SUPPORT */ + + /* statistics count */ + + VOID *iw_stats; + VOID *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 */ +#ifdef RTMP_FLASH_SUPPORT + UCHAR *eebuf; +#endif /* RTMP_FLASH_SUPPORT */ + + ULONG TbttTickCount; /* beacon timestamp work-around */ +#ifdef PCI_MSI_SUPPORT + BOOLEAN HaveMsi; +#endif /* PCI_MSI_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + RALINK_TIMER_STRUCT PeriodicTimer; + +#ifdef AP_QLOAD_SUPPORT + UINT8 FlgQloadEnable; /* 1: any BSS WMM is enabled */ + ULONG QloadUpTimeLast; /* last up time */ + UINT8 QloadChanUtil; /* last QBSS Load, unit: us */ + UINT32 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 statistics for every TBTT */ +#define QLOAD_FUNC_BUSY_TIME_STATS + +/* 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->FlgQloadAlarmIsSuspended == TRUE) +#define QLOAD_ALARM_EVER_OCCUR(pAd) (pAd->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 */ + + /* 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 NINTENDO_AP + NINDO_CTRL_BLOCK nindo_ctrl_block; +#endif /* NINTENDO_AP */ + +#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 */ + + /* UCHAR Wsc_Uuid_E[UUID_LEN_HEX]; // now these two parameters move to structure "WSC_CTRL" */ + /* UCHAR Wsc_Uuid_Str[UUID_LEN_STR]; */ +#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 */ + +#ifdef MESH_SUPPORT + NDIS_SPIN_LOCK MeshTabLock; + MESH_STRUCT MeshTab; +#endif /* MESH_SUPPORT */ + +#ifdef DBG_DIAGNOSE + RtmpDiagStruct DiagStruct; +#endif /* DBG_DIAGNOSE */ + + + UINT8 FlgCtsEnabled; + UINT8 PM_FlgSuspend; + + +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + + EXT_CAP_INFO_ELEMENT ExtCapInfo; + + +#ifdef VENDOR_FEATURE1_SUPPORT + UCHAR FifoUpdateDone, FifoUpdateRx; +#endif /* VENDOR_FEATURE1_SUPPORT */ + + UINT8 RFICType; + +#ifdef LINUX +#ifdef RT_CFG80211_SUPPORT + VOID *pCfgDev; + VOID *pCfg80211_CB; + + BOOLEAN FlgCfg80211Scanning; + BOOLEAN FlgCfg80211Connecting; + UCHAR Cfg80211_Alpha2[2]; +#endif /* RT_CFG80211_SUPPORT */ +#endif /* LINUX */ + +#ifdef OS_ABL_SUPPORT +#ifdef MAT_SUPPORT + /* used in OS_ABL */ + BOOLEAN(*MATPktRxNeedConvert) ( + IN PRTMP_ADAPTER pAd, + IN PNET_DEV net_dev); + + PUCHAR (*MATEngineRxHandle)( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPkt, + IN 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 P2P_SUPPORT + RT_P2P_CONFIG P2pCfg; + NDIS_SPIN_LOCK P2pTableSemLock; + RT_P2P_TABLE P2pTable; + ULONG GOBeaconBufNoALen; + CHAR GoBeaconBuf[512]; /* NOTE: BeaconBuf should be 4-byte aligned */ + ULONG BeaconBufLen; + ULONG GoBeaconBufLen; + BOOLEAN bIsClearScanTab; /* TURE, we need to force Scan */ + BOOLEAN flg_p2p_init; + ULONG flg_p2p_OpStatusFlags; + UCHAR P2PChannel; +#ifdef DOT11_N_SUPPORT + UINT8 P2PExtChOffset; +#endif /* DOT11_N_SUPPORT */ + UCHAR P2PCurrentAddress[MAC_ADDR_LEN]; /* User changed MAC address */ + PNET_DEV p2p_dev; +#endif /* P2P_SUPPORT */ + +#ifdef RT3883 + UINT32 FlgCWC; +#endif /* RT3883 */ + + + +#ifdef WOW_SUPPORT +#endif /* WOW_SUPPORT */ +#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; + BOOLEAN DoDPDRunning; + INT32 DoCalibrationTemperature; + BOOLEAN bDoReCalibration; + UINT16 E2p_D0_Value; + INT32 CurrTemperature; + UCHAR CurrTemperatureMode; + CHAR TemperatureRef25C; + BOOLEAN bRef25CVaild; + BOOLEAN bLowTemperatureTrigger; + CHAR BW_Power_Delta; +#ifdef RTMP_TEMPERATURE_COMPENSATION + CHAR DeltaPwrBeforeTempComp; +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + BOOLEAN bExtPA; +#endif /* RT6352 */ + +#ifdef SINGLE_SKU_V2 + DL_LIST SingleSkuPwrList; + CHAR SingleSkuRatePwrDiff[18]; + BOOLEAN bOpenFileSuccess; +#endif /* SINGLE_SKU_V2 */ +}; + +#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 */ + +#ifdef CARRIER_DETECTION_SUPPORT +#define DELAYINTMASK 0x0013fffb +#define INTMASK 0x0013fffb +#define IndMask 0x0013fffc +#define RadarInt 0x00100000 +#else +#define DELAYINTMASK 0x0003fffb +#define INTMASK 0x0003fffb +#define IndMask 0x0003fffc +#endif /* CARRIER_DETECTION_SUPPORT */ + +#define RxINT 0x00000005 /* Delayed Rx or indivi rx */ +#define TxDataInt 0x000000fa /* Delayed Tx or indivi tx */ +#define TxMgmtInt 0x00000102 /* Delayed Tx or indivi tx */ +#define TxCoherent 0x00020000 /* tx coherent */ +#define RxCoherent 0x00010000 /* rx coherent */ +#define TxRxCoherent 0x00000400 /* tx rx coherent */ +#define McuCommand 0x00000200 /* mcu */ +#define PreTBTTInt 0x00001000 /* Pre-TBTT interrupt */ +#define TBTTInt 0x00000800 /* TBTT interrupt */ +#define GPTimeOutInt 0x00008000 /* GPtimeout interrupt */ +#define AutoWakeupInt 0x00004000 /* AutoWakeupInt interrupt */ +#define FifoStaFullInt 0x00002000 /* fifo statistics full interrupt */ + + +/*************************************************************************** + * Rx Path software control block related data structures + **************************************************************************/ +typedef struct _RX_BLK_ +{ +/* RXD_STRUC RxD; // sample */ + RT28XX_RXD_STRUC RxD; + PRXWI_STRUC pRxWI; + PHEADER_802_11 pHeader; + PNDIS_PACKET pRxPacket; + UCHAR *pData; + USHORT DataSize; + USHORT Flags; + UCHAR UserPriority; /* for calculate TKIP MIC using */ + UCHAR OpMode; /* 0:OPMODE_STA 1:OPMODE_AP */ +} 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 LENGTH_AMSDU_SUBFRAMEHEAD 14 +#define LENGTH_ARALINK_SUBFRAMEHEAD 14 +#define LENGTH_ARALINK_HEADER_FIELD 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 + + +/* 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; + PUCHAR pSrcBufHeader; /* Reference to the head of sk_buff->data */ + PUCHAR 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 + 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 apidx; /* The interface associated to this packet */ + UCHAR Wcid; /* The MAC entry associated to this packet */ + UCHAR UserPriority; /* priority class of packet */ + UCHAR FrameGap; /* what kind of IFS this packet use */ + UCHAR MpduReqNum; /* number of fragments of this frame */ + UCHAR TxRate; /* TODO: Obsoleted? Should change to MCS? */ + UCHAR CipherAlg; /* cipher alogrithm */ + PCIPHER_KEY pKey; + UCHAR KeyIdx; /* Indicate the transmit key index */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + UINT ApCliIfidx; + PAPCLI_STRUCT pApCliEntry; +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + 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 MESH_SUPPORT + PUCHAR pMeshDA; /* used to record Mesh DA. */ +#endif /* MESH_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + MULTISSID_STRUCT *pMbss; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef TXBF_SUPPORT + UCHAR TxSndgPkt; /* 1: sounding 2: NDP sounding */ + UCHAR TxNDPSndgBW; + UCHAR TxNDPSndgMcs; +#endif /* TXBF_SUPPORT */ + + UCHAR OpMode; +} TX_BLK, *PTX_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 MESH_SUPPORT +#define fTX_bMeshEntry 0x4000 /* Used when MESH_SUPPORT */ +#endif /* MESH_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 */ + +#ifdef DOT11Z_TDLS_SUPPORT +#define fTX_bTdlsEntry 0x20000 /* Used when DOT11Z_TDLS_SUPPORT */ +#endif /* DOT11Z_TDLS_SUPPORT */ + +#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)) + + + + +#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 PRTMP_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 */ + } + else + { + for(i=0; i < size/4 ; i++) + *(((UINT32 *)pData) +i) = SWAP32(*(((UINT32 *)pData)+i)); + } +} + + +#ifdef RTMP_MAC_PCI +static inline VOID WriteBackToDescriptor( + IN PUCHAR Dest, + IN PUCHAR 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( + IN PUCHAR pData, + IN ULONG DescriptorType) +{ + *((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 PRTMP_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 != BTYPE_CNTL) + { + /* swab 16 bit fields - Sequence Control field */ + *(USHORT *)(pMacHdr + 22) = SWAP16(*(USHORT *)(pMacHdr + 22)); + } + + if(pFrame->FC.Type == BTYPE_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 == BTYPE_DATA ) + { + } + else if(pFrame->FC.Type == BTYPE_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, ETH_LENGTH_OF_ADDRESS); */ + *(*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, ETH_LENGTH_OF_ADDRESS); */ + *(*ppMacAddr) = 0x01; + *(*ppMacAddr + 1) = 0x00; + *(*ppMacAddr + 2) = 0x5e; + *(*ppMacAddr + 3) = pIpAddr[1] & 0x7f; + *(*ppMacAddr + 4) = pIpAddr[2]; + *(*ppMacAddr + 5) = pIpAddr[3]; + break; + } + + return; +} + + +char *GetPhyMode(int Mode); +char* GetBW(int BW); + + + +BOOLEAN RTMPCheckForHang( + IN NDIS_HANDLE MiniportAdapterContext); + +/* */ +/* Private routines in rtmp_init.c */ +/* */ + +NDIS_STATUS RTMPAllocTxRxRingMemory( + IN PRTMP_ADAPTER pAd); + +#ifdef RESOURCE_PRE_ALLOC +NDIS_STATUS RTMPInitTxRxRingMemory( + IN RTMP_ADAPTER *pAd); +#endif /* RESOURCE_PRE_ALLOC */ + +NDIS_STATUS RTMPReadParametersHook( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS RTMPSetProfileParameters( + IN RTMP_ADAPTER *pAd, + IN 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 PRTMP_ADAPTER pAd, + IN char *tmpbuf, + IN char *buffer); +#endif/*WSC_INCLUDED*/ + + +#ifdef RTMP_RF_RW_SUPPORT +VOID NICInitRFRegisters( + IN PRTMP_ADAPTER pAd); + +VOID RTMP_ReadRF( + IN PRTMP_ADAPTER pAd, + IN UCHAR RegID, + OUT PUCHAR pValue1, + OUT PUCHAR pValue2, + IN UCHAR BitMask); + +VOID RTMP_WriteRF( + IN PRTMP_ADAPTER pAd, + IN UCHAR RegID, + IN UCHAR Value, + IN UCHAR BitMask); + +NDIS_STATUS RT30xxWriteRFRegister( + IN PRTMP_ADAPTER pAd, + IN UCHAR regID, + IN UCHAR value); + +NDIS_STATUS RT30xxReadRFRegister( + IN PRTMP_ADAPTER pAd, + IN UCHAR regID, + IN PUCHAR pValue); + +NDIS_STATUS RT635xWriteRFRegister( + IN PRTMP_ADAPTER pAd, + IN UCHAR bank, + IN UCHAR regID, + IN UCHAR value); + +NDIS_STATUS RT635xReadRFRegister( + IN PRTMP_ADAPTER pAd, + IN UCHAR bank, + IN UCHAR regID, + IN PUCHAR pValue); + +#endif /* RTMP_RF_RW_SUPPORT */ + +NDIS_STATUS NICInitBBP( + IN RTMP_ADAPTER *pAd); + +VOID NICReadEEPROMParameters( + IN PRTMP_ADAPTER pAd, + IN PSTRING mac_addr); + +VOID NICInitAsicFromEEPROM( + IN PRTMP_ADAPTER pAd); + + +NDIS_STATUS NICInitializeAdapter( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bHardReset); + +NDIS_STATUS NICInitializeAsic( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bHardReset); + +#ifdef RTMP_RBUS_SUPPORT +VOID NICResetFromError( + IN PRTMP_ADAPTER pAd); +#endif /* RTMP_RBUS_SUPPORT */ + +VOID RTMPRingCleanUp( + IN PRTMP_ADAPTER pAd, + IN UCHAR RingType); + +VOID UserCfgExit( + IN RTMP_ADAPTER *pAd); + +VOID UserCfgInit( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS NICLoadFirmware( + IN PRTMP_ADAPTER pAd); + +VOID NICEraseFirmware( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS NICLoadRateSwitchingParams( + IN PRTMP_ADAPTER pAd); + +VOID NICUpdateFifoStaCounters( + IN PRTMP_ADAPTER pAd); + +VOID NICUpdateRawCounters( + IN PRTMP_ADAPTER pAd); + +#ifdef FIFO_EXT_SUPPORT +BOOLEAN NicGetMacFifoTxCnt( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry); + +VOID AsicFifoExtSet( + IN RTMP_ADAPTER *pAd); + +VOID AsicFifoExtEntryClean( + IN RTMP_ADAPTER * pAd, + IN 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 RTMPZeroMemory( + IN PVOID pSrc, + IN ULONG Length); + +ULONG RTMPCompareMemory( + IN PVOID pSrc1, + IN PVOID pSrc2, + IN ULONG Length); + +VOID RTMPMoveMemory( + OUT PVOID pDest, + IN PVOID pSrc, + IN ULONG Length); + +VOID AtoH( + PSTRING src, + PUCHAR dest, + int destlen); + +UCHAR BtoH( + char ch); + +VOID RTMP_TimerListAdd( + IN PRTMP_ADAPTER pAd, + IN VOID *pRsc); + +VOID RTMP_TimerListRelease( + IN PRTMP_ADAPTER pAd); + +VOID RTMPInitTimer( + IN PRTMP_ADAPTER pAd, + IN PRALINK_TIMER_STRUCT pTimer, + IN PVOID pTimerFunc, + IN PVOID pData, + IN BOOLEAN Repeat); + +VOID RTMPSetTimer( + IN PRALINK_TIMER_STRUCT pTimer, + IN ULONG Value); + + +VOID RTMPModTimer( + IN PRALINK_TIMER_STRUCT pTimer, + IN ULONG Value); + +VOID RTMPCancelTimer( + IN PRALINK_TIMER_STRUCT pTimer, + OUT BOOLEAN *pCancelled); + +VOID RTMPReleaseTimer( + IN PRALINK_TIMER_STRUCT pTimer, + OUT BOOLEAN *pCancelled); + +VOID RTMPEnableRxTx( + IN PRTMP_ADAPTER pAd); + +VOID AntCfgInit( + IN PRTMP_ADAPTER pAd); + +/* */ +/* prototype in action.c */ +/* */ +VOID ActionStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID MlmeADDBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeDELBAAction( + 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 MlmeQOSAction( + 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); +#endif /* DOT11_N_SUPPORT */ + +VOID SendPSMPAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR Psmp); + +#ifdef CONFIG_AP_SUPPORT +VOID SendBeaconRequest( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid); +#endif /* CONFIG_AP_SUPPORT */ + +VOID PeerRMAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +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 CONFIG_AP_SUPPORT +VOID ApPublicAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif /* CONFIG_AP_SUPPORT */ + +VOID PeerBSSTranAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef DOT11_N_SUPPORT +VOID PeerHTAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif /* DOT11_N_SUPPORT */ + +VOID PeerQOSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef QOS_DLS_SUPPORT +VOID PeerDLSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif /* QOS_DLS_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT +VOID DlsParmFill( + IN PRTMP_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 ORIBATimerTimeout( + IN PRTMP_ADAPTER pAd); + +VOID SendRefreshBAR( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +#ifdef DOT11N_DRAFT3 +VOID RTMP_11N_D3_TimerInit( + IN PRTMP_ADAPTER pAd); + +VOID SendBSS2040CoexistMgmtAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR apidx, + IN UCHAR InfoReq); + +VOID SendNotifyBWActionFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR apidx); + +BOOLEAN ChannelSwitchSanityCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR NewChannel, + IN UCHAR Secondary); + +VOID ChannelSwitchAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR Channel, + IN UCHAR Secondary); + +ULONG BuildIntolerantChannelRep( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDest); + +VOID Update2040CoexistFrameAndNotify( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN BOOLEAN bAddIntolerantCha); + +VOID Send2040CoexistAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN BOOLEAN bAddIntolerantCha); + +VOID UpdateBssScanParm( + IN PRTMP_ADAPTER pAd, + IN OVERLAP_BSS_SCAN_IE APBssScan); +#endif /* DOT11N_DRAFT3 */ + +VOID AsicEnableRalinkBurstMode( + IN PRTMP_ADAPTER pAd); + +VOID AsicDisableRalinkBurstMode( + IN PRTMP_ADAPTER pAd); +#endif /* DOT11_N_SUPPORT */ + +VOID ActHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN PUCHAR Addr1, + IN PUCHAR Addr2, + IN PUCHAR Addr3); + +VOID BarHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PFRAME_BAR pCntlBar, + IN PUCHAR pDA, + IN PUCHAR pSA); + +VOID InsertActField( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Category, + IN UINT8 ActCode); + +BOOLEAN QosBADataParse( + IN PRTMP_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 PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN ULONG MsgLen, + IN PFRAME_BA_REQ pMsg); + +VOID BaAutoManSwitch( + IN PRTMP_ADAPTER pAd); +#endif /* DOT11_N_SUPPORT */ + +VOID HTIOTCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR BatRecIdx); + +/* */ +/* Private routines in rtmp_data.c */ +/* */ +BOOLEAN RTMPHandleTxRingDmaDoneInterrupt( + IN PRTMP_ADAPTER pAd, + IN INT_SOURCE_CSR_STRUC TxRingBitmap); + +VOID RTMPHandleMgmtRingDmaDoneInterrupt( + IN PRTMP_ADAPTER pAd); + +VOID RTMPHandleTBTTInterrupt( + IN PRTMP_ADAPTER pAd); + +VOID RTMPHandlePreTBTTInterrupt( + IN PRTMP_ADAPTER pAd); + +void RTMPHandleTwakeupInterrupt( + IN PRTMP_ADAPTER pAd); + +VOID RTMPHandleRxCoherentInterrupt( + IN PRTMP_ADAPTER pAd); + +#ifdef CONFIG_AP_SUPPORT +VOID RTMPHandleMcuInterrupt( + IN PRTMP_ADAPTER pAd); +#endif /* CONFIG_AP_SUPPORT */ + + +NDIS_STATUS STASendPacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket); + +VOID STASendPackets( + IN NDIS_HANDLE MiniportAdapterContext, + IN PPNDIS_PACKET ppPacketArray, + IN UINT NumberOfPackets); + +VOID RTMPDeQueuePacket( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bIntContext, + IN UCHAR QueIdx, + IN UCHAR Max_Tx_Packets); + +NDIS_STATUS RTMPHardTransmit( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR QueIdx, + OUT PULONG pFreeTXDLeft); + +NDIS_STATUS STAHardTransmit( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR QueIdx); + +VOID STARxEAPOLFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +NDIS_STATUS RTMPFreeTXDRequest( + IN PRTMP_ADAPTER pAd, + IN UCHAR RingType, + IN UCHAR NumberRequired, + IN PUCHAR FreeNumberIs); + +NDIS_STATUS MlmeHardTransmit( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket, + IN BOOLEAN FlgDataQForce, + IN BOOLEAN FlgIsLocked); + +NDIS_STATUS MlmeHardTransmitMgmtRing( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket); + +#ifdef RTMP_MAC_PCI +NDIS_STATUS MlmeHardTransmitTxRing( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket); + +NDIS_STATUS MlmeDataHardTransmit( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket); + +VOID RTMPWriteTxDescriptor( + IN PRTMP_ADAPTER pAd, + IN PTXD_STRUC pTxD, + IN BOOLEAN bWIV, + IN UCHAR QSEL); +#endif /* RTMP_MAC_PCI */ + +USHORT RTMPCalcDuration( + IN PRTMP_ADAPTER pAd, + IN UCHAR Rate, + IN ULONG Size); + +VOID RTMPWriteTxWI( + IN PRTMP_ADAPTER pAd, + IN PTXWI_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 BOOLEAN CfAck, + IN HTTRANSMIT_SETTING *pTransmit); + + +VOID RTMPWriteTxWI_Data( + IN PRTMP_ADAPTER pAd, + IN OUT PTXWI_STRUC pTxWI, + IN TX_BLK *pTxBlk); + + +VOID RTMPWriteTxWI_Cache( + IN PRTMP_ADAPTER pAd, + IN OUT PTXWI_STRUC pTxWI, + IN TX_BLK *pTxBlk); + +VOID RTMPSuspendMsduTransmission( + IN PRTMP_ADAPTER pAd); + +VOID RTMPResumeMsduTransmission( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS MiniportMMRequest( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PUCHAR pData, + IN UINT Length); + +VOID RTMPSendNullFrame( + IN PRTMP_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*/ + +#ifdef CONFIG_STA_SUPPORT +VOID RTMPReportMicError( + IN PRTMP_ADAPTER pAd, + IN PCIPHER_KEY pWpaKey); + +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); + +#endif /* CONFIG_STA_SUPPORT */ + + + +BOOLEAN RTMPFreeTXDUponTxDmaDone( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx); + +BOOLEAN RTMPCheckEtherType( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN PMAC_TABLE_ENTRY pMacEntry, + IN UCHAR OpMode, + OUT PUCHAR pUserPriority, + OUT PUCHAR pQueIdx); + + +VOID RTMPCckBbpTuning( + IN PRTMP_ADAPTER pAd, + IN UINT TxRate); +/* */ +/* MLME routines */ +/* */ + +VOID InitRfPaModeTable( + IN struct _RTMP_ADAPTER *pAd); + +/* 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); + +#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 PRTMP_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 PRTMP_ADAPTER pAd, + INOUT PCHAR pTotalDeltaPower); + +VOID AsicAdjustTxPower( + IN PRTMP_ADAPTER pAd); + +VOID AsicUpdateProtect( + IN PRTMP_ADAPTER pAd, + IN USHORT OperaionMode, + IN UCHAR SetMask, + IN BOOLEAN bDisableBGProtect, + IN BOOLEAN bNonGFExist); + +VOID AsicBBPAdjust( + IN RTMP_ADAPTER *pAd); + +VOID AsicSwitchChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel, + IN BOOLEAN bScan); + +VOID AsicLockChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel) ; + +VOID AsicAntennaSelect( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel); + +#ifdef THERMAL_PROTECT_SUPPORT +VOID thermal_protection( + IN PRTMP_ADAPTER pAd); +#endif /* THERMAL_PROTECT_SUPPORT */ + +VOID AsicResetBBPAgent( + IN PRTMP_ADAPTER pAd); + +#ifdef CONFIG_STA_SUPPORT +VOID AsicSleepThenAutoWakeup( + IN PRTMP_ADAPTER pAd, + IN USHORT TbttNumToNextWakeUp); + +VOID AsicForceSleep( + IN PRTMP_ADAPTER pAd); + +VOID AsicForceWakeup( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromTx); +#endif /* CONFIG_STA_SUPPORT */ + +VOID AsicSetBssid( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBssid); + +VOID AsicSetMcastWC( + IN PRTMP_ADAPTER pAd); + + +VOID AsicDelWcidTab( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid); + +#ifdef DOT11_N_SUPPORT +VOID AsicEnableRDG( + IN PRTMP_ADAPTER pAd); + +VOID AsicDisableRDG( + IN PRTMP_ADAPTER pAd); +#endif /* DOT11_N_SUPPORT */ + +VOID AsicDisableSync( + IN PRTMP_ADAPTER pAd); + +VOID AsicEnableBssSync( + IN PRTMP_ADAPTER pAd); + +VOID AsicEnableIbssSync( + IN PRTMP_ADAPTER pAd); + +VOID AsicSetEdcaParm( + IN PRTMP_ADAPTER pAd, + IN PEDCA_PARM pEdcaParm); + +VOID AsicSetSlotTime( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bUseShortSlotTime); + +VOID AsicAddSharedKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIndex, + IN UCHAR KeyIdx, + IN PCIPHER_KEY pCipherKey); + +VOID AsicRemoveSharedKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIndex, + IN UCHAR KeyIdx); + +VOID AsicUpdateWCIDIVEIV( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN ULONG uIV, + IN ULONG uEIV); + +VOID AsicUpdateRxWCIDTable( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN PUCHAR pAddr); + +VOID AsicUpdateWcidAttributeEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIdx, + IN UCHAR KeyIdx, + IN UCHAR CipherAlg, + IN UINT8 Wcid, + IN UINT8 KeyTabFlag); + +VOID AsicAddPairwiseKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR WCID, + IN PCIPHER_KEY pCipherKey); + +VOID AsicRemovePairwiseKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid); + +BOOLEAN AsicSendCommandToMcu( + IN PRTMP_ADAPTER pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1, + IN BOOLEAN in_atomic); + +BOOLEAN AsicSendCommandToMcuBBP( + IN PRTMP_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( + IN PRTMP_ADAPTER pAd, + IN UCHAR Command); +#endif /* RTMP_MAC_PCI */ + +#ifdef WAPI_SUPPORT +VOID AsicUpdateWAPIPN( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN ULONG pn_low, + IN ULONG pn_high); +#endif /* WAPI_SUPPORT */ + +#ifdef VCORECAL_SUPPORT +VOID AsicVCORecalibration( + IN PRTMP_ADAPTER pAd); +#endif /* VCORECAL_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 PRTMP_ADAPTER pAd, + IN PUCHAR pMacAddress); + +/* + Enable the stream mode + Parameters: + pAd: The adapter data structure + + Return Value: + None +*/ +VOID AsicEnableStreamMode( + IN PRTMP_ADAPTER pAd); + +/* + Disable the stream mode + Parameters: + pAd: The adapter data structure + Return Value: + None +*/ +VOID AsicDisableStreamMode( + IN PRTMP_ADAPTER pAd); + +INT Set_StreamMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_StreamModeMac_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_StreamModeMCS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* STREAM_MODE_SUPPORT */ + +#ifdef WOW_SUPPORT +#endif /* WOW_SUPPORT */ + +VOID MacAddrRandomBssid( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pAddr); + +VOID MgtMacHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN PUCHAR pDA, +#ifdef P2P_SUPPORT + IN PUCHAR pSA, +#endif /* P2P_SUPPORT */ + IN PUCHAR pBssid); + +VOID MgtMacHeaderInitExt( + IN PRTMP_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 PRTMP_ADAPTER pAd); + +VOID MlmeRadioOn( + IN PRTMP_ADAPTER pAd); + + +VOID BssTableInit( + IN BSS_TABLE *Tab); + +#ifdef DOT11_N_SUPPORT +VOID BATableInit( + IN PRTMP_ADAPTER pAd, + IN BA_TABLE *Tab); + +VOID BATableExit( + IN RTMP_ADAPTER *pAd); +#endif /* DOT11_N_SUPPORT */ + +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); + +VOID BssEntrySet( + IN PRTMP_ADAPTER pAd, + OUT PBSS_ENTRY pBss, + IN PUCHAR pBssid, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR BssType, + IN USHORT BeaconPeriod, + IN PCF_PARM CfParm, + IN USHORT AtimWin, + IN USHORT CapabilityInfo, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN HT_CAPABILITY_IE *pHtCapability, + IN ADD_HT_INFO_IE *pAddHtInfo, /* AP might use this additional ht info IE */ + IN UCHAR HtCapabilityLen, + IN UCHAR AddHtInfoLen, + IN UCHAR NewExtChanOffset, + IN UCHAR Channel, + IN CHAR Rssi, + IN LARGE_INTEGER TimeStamp, + IN UCHAR CkipFlag, + IN PEDCA_PARM pEdcaParm, + IN PQOS_CAPABILITY_PARM pQosCapability, + IN PQBSS_LOAD_PARM pQbssLoad, + IN USHORT LengthVIE, + IN PNDIS_802_11_VARIABLE_IEs pVIE); + +ULONG BssTableSetEntry( + IN PRTMP_ADAPTER pAd, + OUT PBSS_TABLE pTab, + IN PUCHAR pBssid, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR BssType, + IN USHORT BeaconPeriod, + IN CF_PARM *CfParm, + IN USHORT AtimWin, + IN USHORT CapabilityInfo, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN HT_CAPABILITY_IE *pHtCapability, + IN ADD_HT_INFO_IE *pAddHtInfo, /* AP might use this additional ht info IE */ + IN UCHAR HtCapabilityLen, + IN UCHAR AddHtInfoLen, + IN UCHAR NewExtChanOffset, + IN UCHAR Channel, + IN CHAR Rssi, + IN LARGE_INTEGER TimeStamp, + IN UCHAR CkipFlag, + IN PEDCA_PARM pEdcaParm, + IN PQOS_CAPABILITY_PARM pQosCapability, + IN PQBSS_LOAD_PARM pQbssLoad, + IN USHORT LengthVIE, + IN PNDIS_802_11_VARIABLE_IEs pVIE); + +#ifdef DOT11_N_SUPPORT +VOID BATableInsertEntry( + IN PRTMP_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 PRTMP_ADAPTER pAd); + +INT TriEventTableSetEntry( + IN PRTMP_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 PRTMP_ADAPTER pAd, + OUT BSS_TABLE *OutTab, + IN CHAR Ssid[], + IN UCHAR SsidLen); + +VOID BssTableSortByRssi( + IN OUT BSS_TABLE *OutTab, + IN BOOLEAN isInverseOrder); + +VOID BssCipherParse( + IN OUT PBSS_ENTRY pBss); + +NDIS_STATUS MlmeQueueInit( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE *Queue); + +VOID MlmeQueueDestroy( + IN MLME_QUEUE *Queue); + +BOOLEAN MlmeEnqueue( + IN PRTMP_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, + IN ULONG MsgLen, + IN PVOID Msg, + IN UCHAR Signal, + IN UCHAR OpMode); + +#ifdef WSC_INCLUDED +BOOLEAN MlmeEnqueueForWsc( + IN PRTMP_ADAPTER pAd, + IN ULONG eventID, + IN LONG senderID, + IN ULONG Machine, + IN ULONG MsgType, + IN ULONG MsgLen, + IN VOID *Msg); +#endif /* WSC_INCLUDED */ + +BOOLEAN MlmeDequeue( + IN MLME_QUEUE *Queue, + OUT MLME_QUEUE_ELEM **Elem); + +VOID MlmeRestartStateMachine( + IN PRTMP_ADAPTER pAd); + +BOOLEAN MlmeQueueEmpty( + IN MLME_QUEUE *Queue); + +BOOLEAN MlmeQueueFull( + IN MLME_QUEUE *Queue, + IN UCHAR SendId); + +BOOLEAN MsgTypeSubst( + IN PRTMP_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 PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + IN MLME_QUEUE_ELEM *Elem, + IN ULONG CurrState); + +VOID Drop( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID AssocStateMachineInit( + IN PRTMP_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 PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeAssocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeReassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeDisassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAssocRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerReassocRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerDisassocAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID DisassocTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID AssocTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ReassocTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID Cls3errAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +VOID InvalidStateWhenAssoc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenReassoc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenDisassociate( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + + +VOID ComposePsPoll( + IN PRTMP_ADAPTER pAd); + +VOID ComposeNullFrame( + IN PRTMP_ADAPTER pAd); + +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 HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN ADD_HT_INFO_IE *pAddHtInfo); + +VOID AuthStateMachineInit( + IN PRTMP_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 PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAuthRspAtSeq2Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAuthRspAtSeq4Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID AuthTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID Cls2errAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +VOID MlmeDeauthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenAuth( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +/*============================================= */ + +VOID AuthRspStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN PSTATE_MACHINE Sm, + IN STATE_MACHINE_FUNC Trans[]); + +VOID PeerDeauthAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAuthSimpleRspGenAndSend( + IN PRTMP_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 PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID APPeerDlsReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerDlsRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerDlsTearDownAction( + IN PRTMP_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 PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID MlmeDlsReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerDlsReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerDlsRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeDlsTearDownAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerDlsTearDownAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID RTMPCheckDLSTimeOut( + IN PRTMP_ADAPTER pAd); + +BOOLEAN RTMPRcvFrameDLSCheck( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHeader, + IN ULONG Len, + IN PRT28XX_RXD_STRUC pRxD); + +INT RTMPCheckDLSFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA); + +VOID RTMPSendDLSTearDownFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA); + +NDIS_STATUS RTMPSendSTAKeyRequest( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA); + +NDIS_STATUS RTMPSendSTAKeyHandShake( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA); + +VOID DlsTimeoutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +BOOLEAN MlmeDlsReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PRT_802_11_DLS *pDLS, + OUT PUSHORT pReason); + +INT Set_DlsEntryInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +MAC_TABLE_ENTRY *MacTableInsertDlsEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UINT DlsEntryIdx); + +BOOLEAN MacTableDeleteDlsEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT wcid, + IN PUCHAR pAddr); + +MAC_TABLE_ENTRY *DlsEntryTableLookup( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount); + +MAC_TABLE_ENTRY *DlsEntryTableLookupByWcid( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount); + +INT Set_DlsAddEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_DlsTearDownEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#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); + +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); + +BOOLEAN PeerDlsTearDownSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pDA, + OUT PUCHAR pSA, + OUT USHORT *pReason); +#endif /* QOS_DLS_SUPPORT */ + +BOOLEAN PeerProbeReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT CHAR Ssid[], + OUT UCHAR *SsidLen, + OUT BOOLEAN *bRequestRssi); + +/*======================================== */ + +VOID SyncStateMachineInit( + IN PRTMP_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 PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenScan( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenJoin( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenStart( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBeacon( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID EnqueueProbeRequest( + IN PRTMP_ADAPTER pAd); + +BOOLEAN ScanRunning( + IN PRTMP_ADAPTER pAd); +/*========================================= */ + +VOID MlmeCntlInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID MlmeCntlMachinePerformAction( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlIdleProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlOidScanProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlOidSsidProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem); + +VOID CntlOidRTBssidProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem); + +VOID CntlMlmeRoamingProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem); + +VOID CntlWaitDisassocProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitJoinProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitReassocProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitStartProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitAuthProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitAuthProc2( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitAssocProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef QOS_DLS_SUPPORT +VOID CntlOidDLSSetupProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif /* QOS_DLS_SUPPORT */ + + +VOID LinkUp( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssType); + +VOID LinkDown( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN IsReqFromAP); + +VOID IterateOnBssTab( + IN PRTMP_ADAPTER pAd); + +VOID IterateOnBssTab2( + IN PRTMP_ADAPTER pAd);; + +VOID JoinParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_JOIN_REQ_STRUCT *JoinReq, + IN ULONG BssIdx); + +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); + +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); + +VOID DisassocParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq, + IN PUCHAR pAddr, + IN USHORT Reason); + +VOID StartParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_START_REQ_STRUCT *StartReq, + IN CHAR Ssid[], + IN UCHAR SsidLen); + +VOID AuthParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_AUTH_REQ_STRUCT *AuthReq, + IN PUCHAR pAddr, + IN USHORT Alg); + +VOID EnqueuePsPoll( + IN PRTMP_ADAPTER pAd); + +VOID EnqueueBeaconFrame( + IN PRTMP_ADAPTER pAd); + +VOID MlmeJoinReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeScanReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeStartReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeForceJoinReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeForceScanReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ScanTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID BeaconTimeoutAtJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBeaconAtScanAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBeaconAtJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBeacon( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerProbeReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ScanNextChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR OpMode); + + +ULONG MakeIbssBeacon( + IN PRTMP_ADAPTER pAd); + +#ifdef CONFIG_STA_SUPPORT +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); +#endif /* CONFIG_STA_SUPPORT */ + +BOOLEAN MlmeScanReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *BssType, + OUT CHAR ssid[], + OUT UCHAR *SsidLen, + OUT UCHAR *ScanType); + +BOOLEAN PeerBeaconAndProbeRspSanity( + 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, +#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); + + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 +BOOLEAN PeerBeaconAndProbeRspSanity2( + IN PRTMP_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 PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2); + +BOOLEAN PeerAddBARspActionSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen); + +BOOLEAN PeerDelBAActionSanity( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN VOID *pMsg, + IN ULONG MsgLen); + +BOOLEAN MlmeAssocReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pApAddr, + OUT USHORT *CapabilityInfo, + OUT ULONG *Timeout, + OUT USHORT *ListenIntv); + +BOOLEAN MlmeAuthReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr, + OUT ULONG *Timeout, + OUT USHORT *Alg); + +BOOLEAN MlmeStartReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT CHAR Ssid[], + OUT UCHAR *Ssidlen); + +BOOLEAN PeerAuthSanity( + IN PRTMP_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 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); + +BOOLEAN PeerDisassocSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *Reason); + +BOOLEAN PeerDeauthSanity( + IN PRTMP_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 PRTMP_ADAPTER pAd, + IN UCHAR channel); + +NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity( + IN PBSS_ENTRY pBss); + +BOOLEAN MlmeDelBAReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen); + +BOOLEAN MlmeAddBAReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2); + +ULONG MakeOutgoingFrame( + OUT UCHAR *Buffer, + OUT ULONG *Length, ...); + +UCHAR RandomByte( + IN PRTMP_ADAPTER pAd); + +UCHAR RandomByte2( + IN PRTMP_ADAPTER pAd); + +VOID AsicUpdateAutoFallBackTable( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pTxRate); + + + +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( + PRTMP_ADAPTER pAd); + +VOID MlmeAutoScan( + IN PRTMP_ADAPTER pAd); + +VOID MlmeAutoReconnectLastSSID( + IN PRTMP_ADAPTER pAd); + +BOOLEAN MlmeValidateSSID( + IN PUCHAR pSsid, + IN UCHAR SsidLen); + +VOID MlmeCheckForRoaming( + IN PRTMP_ADAPTER pAd, + IN ULONG Now32); + +BOOLEAN MlmeCheckForFastRoaming( + IN PRTMP_ADAPTER pAd); + +#ifdef TXBF_SUPPORT +BOOLEAN MlmeTxBfAllowed( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN struct _RTMP_TX_RATE_SWITCH *pTxRate); +#endif /* TXBF_SUPPORT */ + +#ifdef AGS_SUPPORT +INT Show_AGS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +/* */ +/* 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); + +/* */ +/* 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); +#endif /* AGS_SUPPORT */ + +VOID MlmeCalculateChannelQuality( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pMacEntry, + IN ULONG Now); + +VOID MlmeCheckPsmChange( + IN PRTMP_ADAPTER pAd, + IN ULONG Now32); + +VOID MlmeSetPsmBit( + IN PRTMP_ADAPTER pAd, + IN USHORT psm); + +VOID MlmeSetTxPreamble( + IN PRTMP_ADAPTER pAd, + IN USHORT TxPreamble); + +VOID UpdateBasicRateBitmap( + IN PRTMP_ADAPTER pAd); + +VOID MlmeUpdateTxRates( + IN PRTMP_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 PRTMP_ADAPTER pAd, + IN OUT UCHAR SupRate[], + IN OUT UCHAR *SupRateLen); + +#ifdef CONFIG_STA_SUPPORT +BOOLEAN RTMPCheckChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR CentralChannel, + IN UCHAR Channel); +#endif /* CONFIG_STA_SUPPORT */ + +BOOLEAN RTMPCheckHt( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN OUT HT_CAPABILITY_IE *pHtCapability, + IN OUT ADD_HT_INFO_IE *pAddHtInfo); + +VOID RTMPUpdateMlmeRate( + IN PRTMP_ADAPTER pAd); + +CHAR RTMPMaxRssi( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi0, + IN CHAR Rssi1, + IN CHAR Rssi2); + +CHAR RTMPAvgRssi( + IN PRTMP_ADAPTER pAd, + IN RSSI_SAMPLE *pRssi); + + +CHAR RTMPMinSnr( + IN PRTMP_ADAPTER pAd, + IN CHAR Snr0, + IN CHAR Snr1); + +VOID AsicSetRxAnt( + IN PRTMP_ADAPTER pAd, + IN UCHAR Ant); + + + +#ifdef RT305x +VOID NICInitRT305xRFRegisters( + IN PRTMP_ADAPTER pAd); +#endif /* RT305x */ + +VOID AsicEvaluateRxAnt( + IN PRTMP_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); + +BOOLEAN RTMPCheckEntryEnableAutoRateSwitch( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry); + +UCHAR RTMPStaFixedTxMode( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry); + +VOID RTMPUpdateLegacyTxSetting( + UCHAR fixed_tx_mode, + PMAC_TABLE_ENTRY pEntry); + +BOOLEAN RTMPAutoRateSwitchCheck( + IN PRTMP_ADAPTER pAd); + +BOOLEAN RTMPAdjustFrequencyOffset( + IN PRTMP_ADAPTER pAd, + INOUT PUCHAR pRefFreqOffset); + +NDIS_STATUS MlmeInit( + IN PRTMP_ADAPTER pAd); + + +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef RTMP_TEMPERATURE_COMPENSATION +VOID InitLookupTable( + IN PRTMP_ADAPTER pAd); +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + +VOID MlmeHandler( + IN PRTMP_ADAPTER pAd); + +VOID MlmeHalt( + IN PRTMP_ADAPTER pAd); + +VOID MlmeResetRalinkCounters( + IN PRTMP_ADAPTER pAd); + +VOID BuildChannelList( + IN PRTMP_ADAPTER pAd); + +UCHAR FirstChannel( + IN PRTMP_ADAPTER pAd); + +UCHAR NextChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel); + +VOID ChangeToCellPowerLimit( + IN PRTMP_ADAPTER pAd, + IN UCHAR AironetCellPowerLimit); + +/* */ +/* Prototypes of function definition in cmm_tkip.c */ +/* */ +VOID RTMPInitMICEngine( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKey, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN UCHAR UserPriority, + IN PUCHAR pMICKey); + +BOOLEAN RTMPTkipCompareMICValue( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSrc, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN PUCHAR pMICKey, + IN UCHAR UserPriority, + IN UINT Len); + +VOID RTMPCalculateMICValue( + IN PRTMP_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( + IN PTKIP_KEY_INFO pTkip); + +/* */ +/* Prototypes of function definition in cmm_cfg.c */ +/* */ +INT RT_CfgSetCountryRegion( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg, + IN INT band); + +INT RT_CfgSetWirelessMode( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef CONFIG_AP_SUPPORT +#ifdef MBSS_SUPPORT +INT RT_CfgSetMbssWirelessMode( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +BOOLEAN RT_CfgMbssWirelessModeSameBand( + IN PRTMP_ADAPTER pAd, + IN UCHAR WirelessModeNew); + +UCHAR RT_CfgMbssWirelessModeMaxGet( + IN PRTMP_ADAPTER pAd); +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +INT RT_CfgSetShortSlot( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT RT_CfgSetWepKey( + IN PRTMP_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( + IN PSTRING arg); + +INT RT_CfgSetMacAddress( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT RT_CfgSetTxMCSProc( + IN PSTRING arg, + OUT BOOLEAN *pAutoRate); + +INT RT_CfgSetAutoFallBack( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef RT5350 +VOID RT5350SetRxAnt( + IN PRTMP_ADAPTER pAd, + IN UCHAR Ant); + +INT Set_Hw_Antenna_Div_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* RT5350 */ + +#ifdef RT6352 +INT Set_RfBankSel_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef RTMP_TEMPERATURE_CALIBRATION +INT Set_TemperatureCAL_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* RTMP_TEMPERATURE_CALIBRATION */ +#endif /* RT6352 */ + +#ifdef MCS_LUT_SUPPORT +INT Set_HwTxRateLookUp_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); +#endif /* MCS_LUT_SUPPORT */ + +/* */ +/* Prototypes of function definition in cmm_info.c */ +/* */ +NDIS_STATUS RTMPWPARemoveKeyProc( + IN PRTMP_ADAPTER pAd, + IN PVOID pBuf); + +VOID RTMPWPARemoveAllKeys( + IN PRTMP_ADAPTER pAd); + +BOOLEAN RTMPCheckStrPrintAble( + IN CHAR *pInPutStr, + IN UCHAR strLen); +VOID RTMPSetDefaultChannel( + IN PRTMP_ADAPTER pAd); + +VOID RTMPSetPhyMode( + IN PRTMP_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 PRTMP_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 PRTMP_ADAPTER pAd, + IN OID_SET_HT_PHYMODE *pHTPhyMode); + +VOID RTMPSetIndividualHT( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx); +#endif /* DOT11_N_SUPPORT */ + +VOID RTMPDisableDesiredHtInfo( + IN PRTMP_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( + IN PRTMP_ADAPTER pAd, + IN UCHAR Snr); + +#ifdef DOT11N_DRAFT3 +VOID BuildEffectedChannelList( + IN PRTMP_ADAPTER pAd); + + +VOID DeleteEffectedChannelList( + IN PRTMP_ADAPTER pAd); + +VOID CntlChannelWidth( + IN PRTMP_ADAPTER pAd, + IN UCHAR PrimaryChannel, + IN UCHAR CentralChannel, + IN UCHAR ChannelWidth, + IN UCHAR SecondaryChannelOffset); + +#endif /* DOT11N_DRAFT3 */ + + +VOID APAsicEvaluateRxAnt( + IN PRTMP_ADAPTER pAd); + + +VOID APAsicRxAntEvalTimeout( + IN PRTMP_ADAPTER pAd); + + +/* */ +/* function prototype in ap_wpa.c */ +/* */ +VOID RTMPGetTxTscFromAsic( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx, + OUT PUCHAR pTxTsc); + +MAC_TABLE_ENTRY *PACInquiry( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid); + +UINT APValidateRSNIE( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pRsnIe, + IN UCHAR rsnie_len); + +VOID HandleCounterMeasure( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +VOID WPAStart4WayHS( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN ULONG TimeInterval); + +VOID WPAStart2WayGroupHS( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +VOID PeerPairMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerPairMsg2Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerPairMsg3Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerPairMsg4Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerGroupMsg1Action( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerGroupMsg2Action( + IN PRTMP_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 PRTMP_ADAPTER pAdapter, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeDeAuthAction( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN USHORT Reason, + IN BOOLEAN bDataFrameFirst); + + +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 PRTMP_ADAPTER pAdapter, + IN PUCHAR pPacket, + IN ULONG Len); + +VOID RTMPAddPMKIDCache( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN PUCHAR pAddr, + IN UCHAR *PMKID, + IN UCHAR *PMK); + +INT RTMPSearchPMKIDCache( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN PUCHAR pAddr); + +VOID RTMPDeletePMKIDCache( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN INT idx); + +VOID RTMPMaintainPMKIDCache( + IN PRTMP_ADAPTER pAd); +#else +#define RTMPMaintainPMKIDCache(_pAd) +#endif /* DOT1X_SUPPORT */ + +/* timeout -- ms */ + +#ifdef RESOURCE_PRE_ALLOC +VOID RTMPResetTxRxRingMemory( + IN RTMP_ADAPTER *pAd); +#endif /* RESOURCE_PRE_ALLOC */ + +VOID RTMPFreeTxRxRingMemory( + IN PRTMP_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 PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR OpMode); +#endif /* DOT11_N_SUPPORT */ + +PNET_DEV get_netdev_from_bssid( + IN PRTMP_ADAPTER pAd, + IN UCHAR FromWhichBSSID); + + + +#ifdef DOT11_N_SUPPORT +void ba_flush_reordering_timeout_mpdus( + IN PRTMP_ADAPTER pAd, + IN PBA_REC_ENTRY pBAEntry, + IN ULONG Now32); + + +VOID BAOriSessionSetUp( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR TID, + IN USHORT TimeOut, + IN ULONG DelayTime, + IN BOOLEAN isForced); + +VOID BASessionTearDownALL( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR Wcid); + +VOID BAOriSessionTearDown( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR TID, + IN BOOLEAN bPassive, + IN BOOLEAN bForceSend); + +VOID BARecSessionTearDown( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR TID, + IN BOOLEAN bPassive); +#endif /* DOT11_N_SUPPORT */ + +BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num); +void ba_reordering_resource_release(PRTMP_ADAPTER pAd); + +INT ComputeChecksum( + IN UINT PIN); + +UINT GenerateWpsPinCode( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromApcli, + IN UCHAR apidx); + +#ifdef WSC_INCLUDED +INT Set_WscGenPinCode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WscVendorPinCode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef WSC_AP_SUPPORT +VOID RTMPIoctlSetWSCOOB(IN PRTMP_ADAPTER pAd); +#endif + +#ifdef WSC_STA_SUPPORT +VOID CntlWscIterate( + IN PRTMP_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 PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +#ifdef IWSC_SUPPORT +void IWSC_StateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID IWSC_Init( + IN IN PRTMP_ADAPTER pAd); +#endif // IWSC_SUPPORT // + +VOID WscEAPOLStartAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WscEAPAction( + IN PRTMP_ADAPTER pAdapter, + IN MLME_QUEUE_ELEM *Elem); + +VOID WscEapEnrolleeAction( + IN PRTMP_ADAPTER pAdapter, + IN MLME_QUEUE_ELEM *Elem, + IN UCHAR MsgType, + IN MAC_TABLE_ENTRY *pEntry, + IN PWSC_CTRL pWscControl); + +#ifdef CONFIG_AP_SUPPORT +VOID WscEapApProxyAction( + IN PRTMP_ADAPTER pAdapter, + IN MLME_QUEUE_ELEM *Elem, + IN UCHAR MsgType, + IN MAC_TABLE_ENTRY *pEntry, + IN PWSC_CTRL pWscControl); +#endif /* CONFIG_AP_SUPPORT */ + +VOID WscEapRegistrarAction( + IN PRTMP_ADAPTER pAdapter, + 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 PRTMP_ADAPTER pAdapter, + IN PMLME_QUEUE_ELEM pElem); + +VOID WscInitRegistrarPair( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + IN UCHAR apidx); + +VOID WscSendEapReqId( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR CurOpMode); + +VOID WscSendEapolStart( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBssid, + IN UCHAR CurOpMode); + +VOID WscSendEapRspId( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PWSC_CTRL pWscControl); + +VOID WscMacHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 Hdr, + IN PUCHAR pAddr1, + IN PUCHAR pBSSID, + IN BOOLEAN bFromApCli); + +VOID WscSendMessage( + IN PRTMP_ADAPTER pAdapter, + 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 PRTMP_ADAPTER pAdapter, + IN PMAC_TABLE_ENTRY pEntry); + +VOID WscSendEapReqDone( + IN PRTMP_ADAPTER pAdapter, + IN PMLME_QUEUE_ELEM pElem); + +VOID WscSendEapFail( + IN PRTMP_ADAPTER pAdapter, + 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 PRTMP_ADAPTER pAd, + IN UCHAR apIdx, + IN PUCHAR ssidStr, + IN PUCHAR macAddr, + IN INT Status, + IN UINT eventID, + IN UCHAR CurOpMode); + + +int WscSendUPnPMessage( + IN PRTMP_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 PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl, + IN UINT eventID); + +VOID WscBuildBeaconIE( + IN PRTMP_ADAPTER pAdapter, + 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 PRTMP_ADAPTER pAdapter, + 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 PRTMP_ADAPTER pAd, + IN UCHAR ApIdx, + IN UCHAR Reason, + OUT PUCHAR pOutBuf, + OUT PUCHAR pIeLen); + +VOID WscSelectedRegistrar( + IN PRTMP_ADAPTER pAd, + IN PUCHAR RegInfo, + IN UINT length, + IN UCHAR apidx); + +VOID WscInformFromWPA( + IN PMAC_TABLE_ENTRY pEntry); +#endif /* CONFIG_AP_SUPPORT */ + +//#ifdef CONFIG_STA_SUPPORT +VOID WscBuildProbeReqIE( + IN PWSC_CTRL pWscControl, + 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( + IN PRTMP_ADAPTER pAd, + IN 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 PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry); + +VOID IWSC_AddSmpbcEnrollee( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pPeerAddr); + +BOOLEAN IWSC_IpContentForCredential( + IN PRTMP_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 PRTMP_ADAPTER pAd, +#ifdef CONFIG_AP_SUPPORT + IN BOOLEAN bFromApcli, +#endif /* CONFIG_AP_SUPPORT */ + IN PWSC_CTRL pWscControl); + +VOID WscInit( + IN PRTMP_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( + IN UINT PIN); + +UINT WscRandomGen4digitPinCode( + IN PRTMP_ADAPTER pAd); + +UINT WscRandomGeneratePinCode( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx); + +int BuildMessageM1( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM2( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM2D( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM3( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM4( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM5( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM6( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM7( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM8( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageDONE( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageACK( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageNACK( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int ProcessMessageM1( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg); + +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 ProcessMessageM2D( + IN PRTMP_ADAPTER pAdapter, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM3( + IN PRTMP_ADAPTER pAdapter, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM4( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM5( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM6( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM7( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM8( + IN PRTMP_ADAPTER pAdapter, + 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( + IN RTMP_ADAPTER *pAd); + +BOOLEAN WscThreadExit( + IN RTMP_ADAPTER *pAd); + +int AppendWSCTLV( + IN USHORT index, + OUT UCHAR * obuf, + IN UCHAR * ibuf, + IN USHORT varlen); + +VOID WscGetRegDataPIN( + IN PRTMP_ADAPTER pAd, + IN UINT PinCode, + IN PWSC_CTRL pWscControl); + +VOID WscPushPBCAction( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl); + +VOID WscScanExec( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl); + +BOOLEAN WscPBCExec( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromM2, + IN PWSC_CTRL pWscControl); + +VOID WscPBCBssTableSort( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl); + +VOID WscGenRandomKey( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl, + INOUT PUCHAR pKey, + INOUT PUSHORT pKeyLen); + +VOID WscCreateProfileFromCfg( + IN PRTMP_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 PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl, + IN PWSC_CREDENTIAL pCredential, + IN BOOLEAN bEnrollee); + +#ifdef APCLI_SUPPORT +void WscWriteConfToApCliCfg( + IN PRTMP_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 PRTMP_ADAPTER pAd); + +VOID WscPBC_DPID_FromSTA( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMacAddr); + +#ifdef CONFIG_AP_SUPPORT +INT WscGetConfWithoutTrigger( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl, + IN BOOLEAN bFromUPnP); + +BOOLEAN WscReadProfileFromUfdFile( + IN PRTMP_ADAPTER pAd, + IN UCHAR ApIdx, + IN PSTRING pUfdFileName); + +BOOLEAN WscWriteProfileToUfdFile( + IN PRTMP_ADAPTER pAd, + IN UCHAR ApIdx, + IN PSTRING pUfdFileName); +#endif /* CONFIG_AP_SUPPORT */ + +VOID WscCheckWpsIeFromWpsAP( + IN PRTMP_ADAPTER pAd, + IN PEID_STRUCT pEid, + OUT PUSHORT pDPIDFromAP); + +#ifdef CONFIG_STA_SUPPORT +VOID PeerProbeRespAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +ULONG WscSearchWpsApBySSID( + IN PRTMP_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( + IN PRTMP_ADAPTER pAd); + +VOID WSC_HDR_BTN_Stop( + IN PRTMP_ADAPTER pAd); + +VOID WSC_HDR_BTN_CheckHandler( + IN PRTMP_ADAPTER pAd); +#ifdef WSC_LED_SUPPORT +BOOLEAN WscSupportWPSLEDMode( + IN PRTMP_ADAPTER pAdapter); + +BOOLEAN WscSupportWPSLEDMode10( + IN PRTMP_ADAPTER pAdapter); + +BOOLEAN WscAPHasSecuritySetting( + IN PRTMP_ADAPTER pAdapter, + IN 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 PRTMP_ADAPTER pAd, + IN PFRAME_802_11 Fr, + IN PUCHAR eid_data, + IN INT eid_len); + +VOID WscClearPeerList( + IN PLIST_HEADER pWscEnList); + +PWSC_PEER_ENTRY WscFindPeerEntry( + IN PLIST_HEADER pWscEnList, + IN PUCHAR pMacAddr); + +VOID WscDelListEntryByMAC( + PLIST_HEADER pWscEnList, + IN PUCHAR pMacAddr);; + +VOID WscInsertPeerEntryByMAC( + IN PLIST_HEADER pWscEnList, + IN PUCHAR pMacAddr); + +#ifdef CONFIG_AP_SUPPORT +INT WscApShowPeerList( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +INT WscStaShowPeerList( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* CONFIG_STA_SUPPORT */ + +VOID WscMaintainPeerList( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWpsCtrl); + +VOID WscAssignEntryMAC( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWpsCtrl); + +#ifdef WSC_V2_SUPPORT +#ifdef CONFIG_AP_SUPPORT +VOID WscOnOff( + IN PRTMP_ADAPTER pAd, + IN INT ApIdx, + IN BOOLEAN bOff); + +VOID WscAddEntryToAclList( + IN PRTMP_ADAPTER pAd, + IN INT ApIdx, + IN PUCHAR pMacAddr); + +VOID WscSetupLockTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID WscCheckPinAttackCount( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl); +#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 PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + IN PMAC_TABLE_ENTRY pEntry); + +VOID WscSendEapFragData( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + IN PMAC_TABLE_ENTRY pEntry); +#endif /* WSC_V2_SUPPORT */ + +BOOLEAN WscGetDataFromPeerByTag( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pIeData, + IN INT IeDataLen, + IN USHORT WscTag, + OUT PUCHAR pWscBuf, + OUT PUSHORT pWscBufLen); + +#endif /* WSC_INCLUDED */ + +#ifdef EASY_CONFIG_SETUP +#ifdef CONFIG_AP_SUPPORT +VOID AutoProvisionBuildAssocRspIE( + IN PRTMP_ADAPTER pAd, + IN PMLME_QUEUE_ELEM Elem, + IN PMAC_TABLE_ENTRY pEntry, + OUT PUCHAR pOutBuffer, + OUT PULONG pFrameLen); + +VOID AutoProvisionCheckEntry( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PEID_STRUCT eid_ptr); + +VOID AutoProvisionAssignSSID( + IN PRTMP_ADAPTER pAd, + IN PUCHAR eid_data, + IN INT eid_len, + IN PUCHAR pAddr2, + IN UCHAR apidx, + OUT PUCHAR SsidLen, + OUT PUCHAR Ssid); +#endif /* CONFIG_AP_SUPPORT */ + +VOID AutoProvisionGenWpsPTK( + IN PRTMP_ADAPTER pAd, + IN UCHAR ApIdx); + +VOID AutoProvisionDecodeExtData( + IN PRTMP_ADAPTER pAd, + IN UCHAR ApIdx, + IN PUCHAR pEntryAddr, + IN PUCHAR pData); + +BOOLEAN WpsMICIntegrity( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN INT DataLen, + IN PUCHAR pMacAddr, + IN UCHAR ApIdx); + +VOID WpsCalculateMIC( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBuf, + IN INT BufLen, + IN PEASY_CONFIG_INFO pEasyConfig, + IN PUCHAR pMacAddr, + OUT PUCHAR pMIC); +#endif /* EASY_CONFIG_SETUP */ + +#ifdef WAC_SUPPORT +VOID WAC_GenDeviceAdvertiseAttr( + IN BOOLEAN bEnableWAC, + OUT PUCHAR pData, + OUT PUCHAR pDataLen); + +BOOLEAN WAC_ParseAttr( + IN UCHAR AttrID, + IN PUCHAR pInData, + IN UCHAR InDataLen, + OUT PUCHAR pOutData, + IN UCHAR OutDataLen); + +VOID WAC_AddDevAdvAttrIE( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx, + INOUT PUCHAR pBeaconBuf, + INOUT ULONG *pFrameLen); + +INT WAC_IoctlReq( + IN PRTMP_ADAPTER pAd, + IN UCHAR ApIdx, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +#ifdef CONFIG_AP_SUPPORT +VOID WAC_GenStatusAttr( + IN PRTMP_ADAPTER pAd, + IN UCHAR ApIdx, + IN CHAR PeerRssi, + IN BOOLEAN bInvalidData, + IN CHAR ThresholdOffset1, + OUT PUCHAR pData, + OUT PUCHAR pDataLen); + +VOID WAC_MaintainPeerList( + IN PLIST_HEADER pWscEnList); + +VOID WAC_CheckWACEntry( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +VOID WAC_PeerProbeReq( + IN PRTMP_ADAPTER pAd, + IN UCHAR ApIdx, + IN MLME_QUEUE_ELEM *Elem, + IN UCHAR *Addr2, + INOUT UCHAR *pBuf, + INOUT ULONG *pFrameLen); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +VOID WAC_GenUicastProbeReqAttr( + IN BOOLEAN bEnableWAC, + IN PUCHAR pPIN, + OUT PUCHAR pData, + OUT PUCHAR pDataLen); + +UCHAR WAC_SearchSamsungWACAP( + IN PRTMP_ADAPTER pAd); + +BOOLEAN WAC_FindWACAP( + IN PRTMP_ADAPTER pAd); +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef WAC_QOS_PRIORITY +VOID WAC_InsertForcePriorityEntryByMAC( + IN PLIST_HEADER pWscEnList, + IN PUCHAR pMacAddr, + IN UCHAR DeviceType); +#endif /* WAC_QOS_PRIORITY */ +#endif /* CONFIG_AP_SUPPORT */ +#endif /* WAC_SUPPORT */ + +#ifdef NINTENDO_AP +VOID InitNINTENDO_TABLE( + IN PRTMP_ADAPTER pAd); + +UCHAR CheckNINTENDO_TABLE( + IN PRTMP_ADAPTER pAd, + PCHAR pDS_Ssid, + UCHAR DS_SsidLen, + PUCHAR pDS_Addr); + +UCHAR DelNINTENDO_ENTRY( + IN PRTMP_ADAPTER pAd, + UCHAR * pDS_Addr); + +VOID RTMPIoctlNintendoCapable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlNintendoGetTable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlNintendoSetTable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +#endif /* NINTENDO_AP */ + +BOOLEAN rtstrmactohex( + IN PSTRING s1, + IN PSTRING s2); + +BOOLEAN rtstrcasecmp( + IN PSTRING s1, + IN PSTRING s2); + +PSTRING rtstrstruncasecmp( + IN PSTRING s1, + IN PSTRING s2); + +PSTRING rtstrstr( + IN const PSTRING s1, + IN const PSTRING s2); + +PSTRING rstrtok( + IN PSTRING s, + IN const PSTRING ct); + +int rtinet_aton( + const PSTRING cp, + unsigned int *addr); + +/*//////// common ioctl functions ////////*/ +INT Set_DriverVersion_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_CountryRegion_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_CountryRegionABand_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WirelessMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MBSS_WirelessMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_Channel_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +INT Set_ShortSlot_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TxPower_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_BGProtection_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TxPreamble_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_RTSThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_FragThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TxBurst_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef RTMP_MAC_PCI +INT Set_ShowRF_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* RTMP_MAC_PCI */ + +#ifdef AGGREGATION_SUPPORT +INT Set_PktAggregate_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* AGGREGATION_SUPPORT */ + +#ifdef INF_PPA_SUPPORT +INT Set_INF_AMAZON_SE_PPA_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR 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( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef EXT_BUILD_CHANNEL_LIST +INT Set_ExtCountryCode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_ExtDfsType_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ChannelListAdd_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ChannelListShow_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +INT Set_ChannelListDel_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* EXT_BUILD_CHANNEL_LIST */ + +#ifdef DBG +INT Set_Debug_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif + +#ifdef TXBF_SUPPORT +INT Set_ReadITxBf_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ReadETxBf_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WriteITxBf_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WriteETxBf_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_StatITxBf_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_StatETxBf_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TxBfTag_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ITxBfTimeout_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ETxBfTimeout_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_InvTxBfTag_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ITxBfCal_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ITxBfDivCal_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ITxBfLnaCal_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ETxBfEnCond_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ETxBfCodebook_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ETxBfCoefficient_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ETxBfGrouping_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ETxBfNoncompress_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ETxBfIncapable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_NoSndgCntThrd_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_NdpSndgStreams_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_Trigger_Sounding_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ITxBfEn_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#endif /* TXBF_SUPPORT */ + +INT Set_RateAdaptInterval( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + + +#ifdef PRE_ANT_SWITCH +INT Set_PreAntSwitch_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_PreAntSwitchRSSI_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_PreAntSwitchTimeout_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* PRE_ANT_SWITCH */ + + +#if defined (RT2883) || defined (RT3883) +INT Set_PhyRateLimit_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef DBG +INT Set_FixedRate_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* DBG */ +#endif /* defined (RT2883) || defined (RT3883) */ + +#ifdef CFO_TRACK +INT Set_CFOTrack_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif // CFO_TRACK // + +#ifdef DBG_CTRL_SUPPORT +INT Set_DebugFlags_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef INCLUDE_DEBUG_QUEUE +INT Set_DebugQueue_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +void dbQueueEnqueue( + IN UCHAR type, + IN UCHAR *data); + +void dbQueueEnqueueTxFrame( + IN UCHAR *pTxWI, + IN UCHAR *pHeader_802_11); + +void dbQueueEnqueueRxFrame( + IN UCHAR *pRxWI, + IN UCHAR *pHeader_802_11, + IN ULONG flags); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + +INT Show_DescInfo_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ResetStatCounter_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef DOT11_N_SUPPORT +INT Set_BASetup_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_BADecline_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_BAOriTearDown_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_BARecTearDown_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_HtBw_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_HtMcs_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_HtGi_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_HtOpMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_HtStbc_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_HtHtc_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_HtExtcha_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_HtMpduDensity_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_HtBaWinSize_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_HtRdg_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_HtLinkAdapt_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_HtAmsdu_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_HtAutoBa_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_HtProtect_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_HtMimoPs_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef DOT11N_DRAFT3 +INT Set_HT_BssCoex_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING pParam); + +INT Set_HT_BssCoexApCntThr_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING pParam); +#endif /* DOT11N_DRAFT3 */ + + +#ifdef CONFIG_AP_SUPPORT +INT Set_HtTxStream_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_HtRxStream_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#ifdef DOT11_N_SUPPORT +#ifdef GREENAP_SUPPORT +INT Set_GreenAP_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* GREENAP_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +INT Set_ForceShortGI_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ForceGF_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT SetCommonHT( + IN PRTMP_ADAPTER pAd); + +INT Set_SendPSMPAction_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +void convert_reordering_packet_to_preAMSDU_or_802_3_packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +INT Set_HtMIMOPSmode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + + +INT Set_HtTxBASize_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_HtDisallowTKIP_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_BurstMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* DOT11_N_SUPPORT */ + +#ifdef APCLI_SUPPORT +INT RTMPIoctlConnStatus( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +#endif /*APCLI_SUPPORT*/ + +#ifdef ETH_CONVERT_SUPPORT +INT Set_EthConvertMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_EthCloneMac_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* ETH_CONVERT_SUPPORT */ + + + +#ifdef CONFIG_STA_SUPPORT +/*Dls , kathy */ +VOID RTMPSendDLSTearDownFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA); + +#ifdef DOT11_N_SUPPORT +/*Block ACK */ +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( + IN PRTMP_ADAPTER pAd, + IN UCHAR UserPriority, + IN UCHAR FlgIsOutput); + +VOID dynamic_tune_be_tx_op( + IN PRTMP_ADAPTER pAd, + IN ULONG nonBEpackets); +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef DOT11_N_SUPPORT +VOID Handle_BSS_Width_Trigger_Events( + IN PRTMP_ADAPTER pAd); + +void build_ext_channel_switch_ie( + IN PRTMP_ADAPTER pAd, + IN HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE *pIE); + +void assoc_ht_info_debugshow( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR HTCapability_Len, + IN HT_CAPABILITY_IE *pHTCapability); +#endif /* DOT11_N_SUPPORT */ + + +BOOLEAN APRxDoneInterruptHandle( + IN PRTMP_ADAPTER pAd); + +BOOLEAN STARxDoneInterruptHandle( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN argc); + +BOOLEAN RxDoneInterruptHandle( + IN PRTMP_ADAPTER pAd); + +#ifdef DOT11_N_SUPPORT +/* AMPDU packet indication */ +VOID Indicate_AMPDU_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +/* 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); + +VOID Indicate_EAPOL_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + + +UINT deaggregate_AMSDU_announce( + IN PRTMP_ADAPTER pAd, + PNDIS_PACKET pPacket, + IN PUCHAR pData, + IN ULONG DataSize, + IN UCHAR OpMode); + +#ifdef TXBF_SUPPORT +BOOLEAN clientSupportsETxBF( + IN PRTMP_ADAPTER pAd, + IN HT_BF_CAP *pTxBFCap); + +void setETxBFCap( + IN PRTMP_ADAPTER pAd, + OUT HT_BF_CAP *pTxBFCap); + +#ifdef ETXBF_EN_COND3_SUPPORT +VOID txSndgSameMcs( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY * pEntry, + IN UCHAR smoothMfb); + +VOID txSndgOtherGroup( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +VOID txMrqInvTxBF( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +VOID chooseBestMethod( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR mfb); + +VOID rxBestSndg( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); +#endif // ETXBF_EN_COND3_SUPPORT // + +VOID handleBfFb( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk); + +VOID TxBFInit( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN BOOLEAN supportsETxBF); + +VOID eTxBFProbing( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +VOID Trigger_Sounding_Packet( + IN PRTMP_ADAPTER pAd, + IN UCHAR SndgType, + IN UCHAR SndgBW, + IN UCHAR SndgMcs, + IN MAC_TABLE_ENTRY *pEntry); + +VOID rtmp_asic_set_bf( + IN RTMP_ADAPTER *pAd); + +BOOLEAN rtmp_chk_itxbf_calibration( + IN 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); \ +} +#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); \ +} +#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 PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +VOID CmmRxRalinkFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +VOID Update_Rssi_Sample( + IN PRTMP_ADAPTER pAd, + IN RSSI_SAMPLE *pRssi, + IN PRXWI_STRUC pRxWI); + +PNDIS_PACKET GetPacketFromRxRing( + IN PRTMP_ADAPTER pAd, + OUT PRT28XX_RXD_STRUC pSaveRxD, + OUT BOOLEAN *pbReschedule, + IN OUT UINT32 *pRxPending); + +PNDIS_PACKET RTMPDeFragmentDataFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk); + +/*////////////////////////////////////*/ + +#if defined (AP_SCAN_SUPPORT) || defined (CONFIG_STA_SUPPORT) +VOID RTMPIoctlGetSiteSurvey( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +INT Set_ApCli_AuthMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ApCli_EncrypType_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( + IN RTMP_ADAPTER *pAd); + +NDIS_STATUS MATEngineExit( + IN RTMP_ADAPTER *pAd); + +PUCHAR MATEngineRxHandle( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPkt, + IN UINT infIdx); + + +PUCHAR MATEngineTxHandle( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPkt, + IN UINT infIdx, + IN UCHAR OpMode); + +BOOLEAN MATPktRxNeedConvert( + IN PRTMP_ADAPTER pAd, + IN 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 , kathy */ +typedef struct _DefaultKeyIdxValue +{ + UCHAR KeyIdx; + UCHAR Value[16]; +} DefaultKeyIdxValue, *PDefaultKeyIdxValue; +#endif + + +#ifdef CONFIG_STA_SUPPORT + +/* The radio capture header precedes the 802.11 header. */ +typedef struct GNU_PACKED _ieee80211_radiotap_header { + UINT8 it_version; /* Version 0. Only increases + * for drastic changes, + * introduction of compatible + * new fields does not count. + */ + UINT8 it_pad; + UINT16 it_len; /* length of the whole + * header in bytes, including + * it_version, it_pad, + * it_len, and data fields. + */ + UINT32 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. + */ +}ieee80211_radiotap_header ; + +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 +}; + +#define WLAN_RADIOTAP_PRESENT ( \ + (1 << IEEE80211_RADIOTAP_TSFT) | \ + (1 << IEEE80211_RADIOTAP_FLAGS) | \ + (1 << IEEE80211_RADIOTAP_RATE) | \ + 0) + +typedef struct _wlan_radiotap_header { + ieee80211_radiotap_header wt_ihdr; + INT64 wt_tsft; + UINT8 wt_flags; + UINT8 wt_rate; +} wlan_radiotap_header; +/* Definition from madwifi */ + + +void STA_MonPktSend( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk); + +VOID RTMPSetDesiredRates( + IN PRTMP_ADAPTER pAdapter, + IN LONG Rates); + +#ifdef XLINK_SUPPORT +INT Set_XlinkMode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); +#endif /* XLINK_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +INT Set_FixedTxMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +INT Set_OpMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ + +INT Set_LongRetryLimit_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_ShortRetryLimit_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_AutoFallBack_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +#ifdef RT2883 +VOID RTMPRT2883ReadTxPwrPerRate( + IN PRTMP_ADAPTER pAd); + +VOID RTMPRT2883ReadChannelPwr( + IN PRTMP_ADAPTER pAd); +#endif /* RT2883 */ + +VOID RT28XXDMADisable( + IN RTMP_ADAPTER *pAd); + +VOID RT28XXDMAEnable( + IN RTMP_ADAPTER *pAd); + +VOID RT28xx_UpdateBeaconToAsic( + IN RTMP_ADAPTER * pAd, + IN INT apidx, + IN ULONG BeaconLen, + IN ULONG UpdatePos); + +void CfgInitHook(PRTMP_ADAPTER pAd); + + +NDIS_STATUS RtmpNetTaskInit( + IN RTMP_ADAPTER *pAd); + +VOID RtmpNetTaskExit( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS RtmpMgmtTaskInit( + IN RTMP_ADAPTER *pAd); + +VOID RtmpMgmtTaskExit( + IN RTMP_ADAPTER *pAd); + +#ifdef WORKQUEUE_BH +void tbtt_workq(struct work_struct *work); +#else +void tbtt_tasklet(unsigned long data); +#endif /* WORKQUEUE_BH */ + + + + +#ifdef RTMP_MAC_PCI +/* */ +/* Function Prototype in cmm_data_pci.c */ +/* */ + +VOID DBGPRINT_TX_RING( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx); + +USHORT RtmpPCI_WriteSingleTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN BOOLEAN bIsLast, + OUT USHORT *FreeNumber); + +USHORT RtmpPCI_WriteMultiTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR frameNum, + OUT USHORT *FreeNumber); + +USHORT RtmpPCI_WriteFragTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR fragNum, + OUT USHORT *FreeNumber); + +VOID RtmpPCI_FinalWriteTxResource( + IN PRTMP_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); + + +NDIS_STATUS RTMPCheckRxError( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHeader, + IN PRXWI_STRUC pRxWI, + IN PRT28XX_RXD_STRUC pRxD); + +BOOLEAN RT28xxPciAsicRadioOff( + IN PRTMP_ADAPTER pAd, + IN UCHAR Level, + IN USHORT TbttNumToNextWakeUp); + +BOOLEAN RT28xxPciAsicRadioOn( + IN PRTMP_ADAPTER pAd, + IN UCHAR Level); + +VOID RTMPInitPCIeDevice( + IN RT_CMD_PCIE_INIT *pConfig, + IN VOID *pAd); + +#ifdef CONFIG_STA_SUPPORT +#ifdef PCIE_PS_SUPPORT +VOID RTMPInitPCIeLinkCtrlValue( + IN PRTMP_ADAPTER pAd); + + +VOID RTMPPCIeLinkCtrlValueRestore( + IN PRTMP_ADAPTER pAd, + IN UCHAR Level); + +VOID RTMPPCIeLinkCtrlSetting( + IN PRTMP_ADAPTER pAd, + IN USHORT Max); + +VOID RTMPrt3xSetPCIePowerLinkCtrl( + IN PRTMP_ADAPTER pAd); + +VOID PsPollWakeExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID RadioOnExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif /* PCIE_PS_SUPPORT */ + +VOID RT28xxPciStaAsicForceWakeup( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromTx); + +VOID RT28xxPciStaAsicSleepThenAutoWakeup( + IN PRTMP_ADAPTER pAd, + IN USHORT TbttNumToNextWakeUp); + +#endif /* CONFIG_STA_SUPPORT */ + +VOID RT28xxPciMlmeRadioOn( + IN PRTMP_ADAPTER pAd); + +VOID RT28xxPciMlmeRadioOFF( + IN PRTMP_ADAPTER pAd); + +ra_dma_addr_t RtmpDrvPciMapSingle( + IN PRTMP_ADAPTER pAd, + IN VOID *ptr, + IN size_t size, + IN int sd_idx, + IN int direction); +#endif /* RTMP_MAC_PCI */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef CREDENTIAL_STORE +NDIS_STATUS RecoverConnectInfo( + IN RTMP_ADAPTER *pAd); + +NDIS_STATUS StoreConnectInfo( + IN RTMP_ADAPTER *pAd); +#endif /* CREDENTIAL_STORE */ +#endif /* CONFIG_STA_SUPPORT */ + +VOID AsicTurnOffRFClk( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel); + +#ifdef RT305x +INT Set_HiPower_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +#if defined(RT3352) || defined(RT5350) +#ifdef RTMP_INTERNAL_TX_ALC +INT Set_TSSIMaxRange_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); +#endif /* RTMP_INTERNAL_TX_ALC */ +#endif /* defined(RT3352) || defined(RT5350) */ +#endif /* RT305x */ + + +#ifdef RTMP_TIMER_TASK_SUPPORT +INT RtmpTimerQThread( + IN 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( + IN RTMP_ADAPTER *pAd); + +void RtmpTimerQInit( + IN RTMP_ADAPTER *pAd); +#endif /* RTMP_TIMER_TASK_SUPPORT */ + + + +/*////////////////////////////////////*/ + +#ifdef AP_QLOAD_SUPPORT +VOID QBSS_LoadInit( + IN RTMP_ADAPTER *pAd); + +VOID QBSS_LoadAlarmReset( + IN RTMP_ADAPTER *pAd); + +VOID QBSS_LoadAlarmResume( + IN RTMP_ADAPTER *pAd); + +UINT32 QBSS_LoadBusyTimeGet( + IN RTMP_ADAPTER *pAd); + +BOOLEAN QBSS_LoadIsAlarmIssued( + IN RTMP_ADAPTER *pAd); + +BOOLEAN QBSS_LoadIsBusyTimeAccepted( + IN RTMP_ADAPTER *pAd, + IN UINT32 BusyTime); + +UINT32 QBSS_LoadElementAppend( + IN RTMP_ADAPTER *pAd, + OUT 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( + IN RTMP_ADAPTER *pAd, + IN ULONG UpTime); + +VOID QBSS_LoadStatusClear( + IN RTMP_ADAPTER *pAd); + +INT Show_QoSLoad_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* AP_QLOAD_SUPPORT */ + +/*///////////////////////////////////*/ +INT RTMPShowCfgValue( + IN PRTMP_ADAPTER pAd, + IN PSTRING pName, + IN PSTRING pBuf, + IN UINT32 MaxLen); + +PSTRING RTMPGetRalinkAuthModeStr( + IN NDIS_802_11_AUTHENTICATION_MODE authMode); + +PSTRING RTMPGetRalinkEncryModeStr( + IN USHORT encryMode); +/*//////////////////////////////////*/ + +#ifdef CONFIG_STA_SUPPORT +VOID AsicStaBbpTuning( + IN PRTMP_ADAPTER pAd); + +BOOLEAN StaAddMacTableEntry( + IN PRTMP_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 USHORT CapabilityInfo); + + +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( + IN PRTMP_ADAPTER pAd); + +VOID RTMPSetAGCInitValue( + IN PRTMP_ADAPTER pAd, + IN UCHAR BandWidth); + +#ifdef TXBF_SUPPORT +VOID handleHtcField( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk); +#endif /* TXBF_SUPPORT */ + +#ifdef MFB_SUPPORT +VOID MFB_PerPareMRQ( + IN PRTMP_ADAPTER pAd, + OUT VOID* pBuf, + IN PMAC_TABLE_ENTRY pEntry); + +VOID MFB_PerPareMFB( + IN PRTMP_ADAPTER pAd, + OUT VOID* pBuf, + IN PMAC_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( + IN PRTMP_ADAPTER pAd, + IN PTX_BLK pTxBlk); + +VOID RTMPUpdateSwCacheCipherInfo( + IN PRTMP_ADAPTER pAd, + IN PTX_BLK pTxBlk, + IN PUCHAR pHdr); +#endif /* SOFT_ENCRYPT */ + + +/* + OS Related funciton prototype definitions. + TODO: Maybe we need to move these function prototypes to other proper place. +*/ + +VOID RTInitializeCmdQ( + IN PCmdQ cmdq); + +INT RTPCICmdThread( + IN ULONG Context); + +VOID CMDHandler( + IN PRTMP_ADAPTER pAd); + +VOID RTThreadDequeueCmd( + IN PCmdQ cmdq, + OUT PCmdQElmt *pcmdqelmt); + +NDIS_STATUS RTEnqueueInternalCmd( + IN PRTMP_ADAPTER pAd, + IN NDIS_OID Oid, + IN PVOID pInformationBuffer, + IN UINT32 InformationBufferLength); + +#ifdef HOSTAPD_SUPPORT +VOID ieee80211_notify_michael_failure( + IN PRTMP_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( + PRTMP_ADAPTER pAd, + UINT32 Offset, + UINT32 Value); + +VOID RTMP_BBP_IO_READ8_BY_REG_ID( + PRTMP_ADAPTER pAd, + UINT32 Offset, + UINT8 *pValue); + +VOID RTMP_BBP_IO_READ8( + PRTMP_ADAPTER pAd, + UCHAR Offset, + UINT8 *pValue, + BOOLEAN FlgValidMCR); + +VOID RTMP_BBP_IO_WRITE8_BY_REG_ID( + PRTMP_ADAPTER pAd, + UINT32 Offset, + UINT8 Value); + +VOID RTMP_BBP_IO_WRITE8( + PRTMP_ADAPTER pAd, + UCHAR Offset, + UINT8 Value, + BOOLEAN FlgValidMCR); +#endif /* VENDOR_FEATURE3_SUPPORT */ + +NDIS_STATUS AsicBBPWriteWithRxChain( + IN RTMP_ADAPTER *pAd, + IN UCHAR bbpId, + IN CHAR bbpVal, + IN RX_CHAIN_IDX rx_ch_idx); + +NDIS_STATUS AsicBBPReadWithRxChain( + IN RTMP_ADAPTER *pAd, + IN UCHAR bbpId, + IN CHAR *pBbpVal, + IN RX_CHAIN_IDX rx_ch_idx); + +INT AsicGetMacVersion( + IN RTMP_ADAPTER *pAd); + +INT WaitForAsicReady( + IN RTMP_ADAPTER *pAd); + +BOOLEAN CHAN_PropertyCheck( + IN PRTMP_ADAPTER pAd, + IN UINT32 ChanNum, + IN UCHAR Property); + +#ifdef CONFIG_STA_SUPPORT + +/* command */ +INT Set_SSID_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +#ifdef WMM_SUPPORT +INT Set_WmmCapable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif + +INT Set_NetworkType_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_AuthMode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_EncrypType_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_Key1_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_Key2_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_Key3_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_Key4_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_WPAPSK_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + + +INT Set_PSMode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +#ifdef WPA_SUPPLICANT_SUPPORT +INT Set_Wpa_Support( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* WPA_SUPPLICANT_SUPPORT */ + +#ifdef DBG + +VOID RTMPIoctlMAC( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlE2PROM( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif /* DBG */ + +#ifdef WSC_STA_SUPPORT +INT Set_WscConfMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WscConfStatus_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WscSsid_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WscBssid_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WscMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WscUUIDE_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WscGetConf_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WscStop_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_WscPinCode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#ifdef WSC_V2_SUPPORT +INT Set_WscForceSetAP_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* WSC_V2_SUPPORT */ +#endif /* WSC_STA_SUPPORT */ + +NDIS_STATUS RTMPWPANoneAddKeyProc( + IN PRTMP_ADAPTER pAd, + IN PVOID pBuf); + +INT Set_FragTest_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +#ifdef DOT11_N_SUPPORT +INT Set_TGnWifiTest_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* DOT11_N_SUPPORT */ + +INT Set_LongRetryLimit_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +INT Set_ShortRetryLimit_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); + +#ifdef EXT_BUILD_CHANNEL_LIST +INT Set_Ieee80211dClientMode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PSTRING arg); +#endif /* EXT_BUILD_CHANNEL_LIST */ + +INT Show_Adhoc_MacTable_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING extra, + IN UINT32 size); + +#ifdef RTMP_RF_RW_SUPPORT +VOID RTMPIoctlRF( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif /* RTMP_RF_RW_SUPPORT */ + + +INT Set_BeaconLostTime_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_AutoRoaming_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_SiteSurvey_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ForceTxBurst_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +VOID RTMPAddKey( + IN PRTMP_ADAPTER pAd, + IN PNDIS_802_11_KEY pKey); + + +VOID StaSiteSurvey( + IN PRTMP_ADAPTER pAd, + IN PNDIS_802_11_SSID pSsid, + IN UCHAR ScanType); + +VOID MaintainBssTable( + IN PRTMP_ADAPTER pAd, + IN OUT BSS_TABLE *Tab, + IN ULONG MaxRxTimeDiff, + IN UCHAR MaxSameRxTimeCount); +#endif /* CONFIG_STA_SUPPORT */ + +void getRate( + IN HTTRANSMIT_SETTING HTSetting, + OUT ULONG* fLastTxRxRate); + + +#ifdef APCLI_SUPPORT +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT +VOID ApcliSendAssocIEsToWpaSupplicant( + IN PRTMP_ADAPTER pAd, + IN UINT ifIndex); + +INT ApcliWpaCheckEapCode( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pFrame, + IN USHORT FrameLen, + IN USHORT OffSet); + +VOID ApcliWpaSendEapolStart( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBssid, + IN PMAC_TABLE_ENTRY pMacEntry, + IN PAPCLI_STRUCT pApCliEntry); +#endif/*APCLI_WPA_SUPPLICANT_SUPPORT*/ + +VOID ApCliRTMPSendNullFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR TxRate, + IN BOOLEAN bQosNull, + IN PMAC_TABLE_ENTRY pMacEntry); +#endif/*APCLI_SUPPORT*/ + + +void RTMP_IndicateMediaState( + IN PRTMP_ADAPTER pAd, + IN NDIS_MEDIA_STATE media_state); + +#if defined(RT3350) || defined(RT33xx) +VOID RTMP_TxEvmCalibration( + IN PRTMP_ADAPTER pAd); +#endif /* defined(RT3350) || defined(RT33xx) */ + +INT RTMPSetInformation( + IN PRTMP_ADAPTER pAd, + IN OUT RTMP_IOCTL_INPUT_STRUCT *rq, + IN INT cmd); + +INT RTMPQueryInformation( + IN PRTMP_ADAPTER pAd, + IN OUT RTMP_IOCTL_INPUT_STRUCT *rq, + IN INT cmd); + +VOID RTMPIoctlShow( + IN PRTMP_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( + IN RTMP_ADAPTER *pAd, + IN VOID *pCB); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef P2P_SUPPORT +BOOLEAN APHandleRxDonePacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pRxPacket, + IN RX_BLK *pRxCell); + +BOOLEAN STAHandleRxDonePacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pRxPacket, + IN RX_BLK *pRxCell); +#endif /* P2P_SUPPORT */ + +INT Set_VcoPeriod_Proc( + IN RTMP_ADAPTER *pAd, + IN PSTRING arg); + +INT Set_RateAlg_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +VOID RtmpUpdateFilterCoefficientControl( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel); + +#ifdef MAC_APCLI_SUPPORT +VOID AsicSetApCliBssid( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBssid, + IN UCHAR index); +#endif /* MAC_APCLI_SUPPORT */ + +#ifdef SINGLE_SKU +INT Set_ModuleTxpower_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* SINGLE_SKU */ + +VOID RtmpEnqueueNullFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR TxRate, + IN UCHAR PID, + IN UCHAR apidx, + IN BOOLEAN bQosNull, + IN BOOLEAN bEOSP, + IN UCHAR OldUP); + +VOID RtmpCleanupPsQueue( + IN PRTMP_ADAPTER pAd, + IN PQUEUE_HEADER pQueue); + +NDIS_STATUS RtmpInsertPsQueue( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN MAC_TABLE_ENTRY *pMacEntry, + IN UCHAR QueIdx); + +VOID RtmpHandleRxPsPoll( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN USHORT Aid, + IN BOOLEAN isActive); + +BOOLEAN RtmpPsIndicate( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN ULONG Wcid, + IN UCHAR Psm); + +#ifdef CONFIG_STA_SUPPORT +BOOLEAN RtmpPktPmBitCheck( + IN PRTMP_ADAPTER pAd); + +VOID RtmpPsActiveExtendCheck( + IN PRTMP_ADAPTER pAd); + +VOID RtmpPsModeChange( + IN PRTMP_ADAPTER pAd, + IN UINT32 PsMode); +#endif /* CONFIG_STA_SUPPORT */ + +#if defined(MICROWAVE_OVEN_SUPPORT) || defined(DYNAMIC_VGA_SUPPORT) +INT Set_MO_FalseCCATh_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_MO_LowFalseCCATh_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#ifdef MICROWAVE_OVEN_SUPPORT +VOID AsicMeasureFalseCCA( + IN PRTMP_ADAPTER pAd); + +VOID AsicMitigateMicrowave( + IN PRTMP_ADAPTER pAd); +#endif /* MICROWAVE_OVEN_SUPPORT */ +#endif /* defined(MICROWAVE_OVEN_SUPPORT) || defined(DYNAMIC_VGA_SUPPORT) */ + +#ifdef MAC_REPEATER_SUPPORT +REPEATER_CLIENT_ENTRY *RTMPLookupRepeaterCliEntry( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bRealMAC, + IN PUCHAR pAddr); + +VOID RTMPInsertRepeaterAsicEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR CliIdx, + IN PUCHAR pAddr); + +VOID RTMPRemoveRepeaterAsicEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR CliIdx); + +VOID RTMPInsertRepeaterEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx, + IN PUCHAR pAddr); + +VOID RTMPRemoveRepeaterEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx, + IN UCHAR CliIdx); + +VOID RTMPRepeaterReconnectionCheck( + IN PRTMP_ADAPTER pAd); + +MAC_TABLE_ENTRY *RTMPInsertRepeaterMacEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR apidx, + IN UCHAR cliIdx, + IN BOOLEAN CleanAll); + +BOOLEAN RTMPRepeaterVaildMacEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +INVAILD_TRIGGER_MAC_ENTRY *RepeaterInvaildMacLookup( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +VOID RTMPRepeaterInsertInvaildMacEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +BOOLEAN RTMPRepeaterRemoveInvaildMacEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR idx, + IN PUCHAR pAddr); + +INT Show_Repeater_Cli_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef SINGLE_SKU_V2 +NDIS_STATUS RTMPSetSingleSKUParameters( + IN RTMP_ADAPTER *pAd); + +VOID InitSkuRateDiffTable( + IN PRTMP_ADAPTER pAd); + +UCHAR GetSkuChannelBasePwr( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel); + +UCHAR GetSkuPerRatePwr( + IN PRTMP_ADAPTER pAd, + IN CHAR phymode, + IN UCHAR channel, + IN UCHAR bw, + IN INT32 paValue); +#endif /* SINGLE_SKU_V2 */ +#ifdef PEER_DELBA_TX_ADAPT +VOID Peer_DelBA_Tx_Adapt_Init( + IN PRTMP_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 */ +#endif /* __RTMP_H__ */ + diff --git a/mt7620/src/include/rtmp_chip.h b/mt7620/src/include/rtmp_chip.h new file mode 100644 index 0000000..dc89b2c --- /dev/null +++ b/mt7620/src/include/rtmp_chip.h @@ -0,0 +1,1267 @@ +/* + *************************************************************************** + * 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; + +#ifdef RTMP_MAC_PCI +#include "chip/mac_pci.h" +#endif /* RTMP_MAC_PCI */ + + +#ifdef RT2860 +#include "chip/rt2860.h" +#include "chip/rt28xx.h" +#endif /* RT2860 */ + + + + +#ifdef RT2880 +#include "chip/rt2880.h" +#include "chip/rt28xx.h" +#endif /* RT2880 */ + +#ifdef RT2883 +#include "chip/rt2883.h" +#endif /* RT2883 */ + +#ifdef RT3883 +#include "chip/rt3883.h" +#endif /* RT3883 */ + + +#ifdef RT305x +#include "chip/rt305x.h" +#endif /* RT305x */ + + + + +#ifdef RT3352 +#include "chip/rt3352.h" +#endif /* RT3352 */ + +#ifdef RT5350 +#include "chip/rt5350.h" +#endif /* RT5350 */ + + + + + +#ifdef RT6352 +#include "chip/rt6352.h" +#endif /* RT6352 */ + +#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) + +#ifdef RT2883 +#define IS_RT2883(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x28830000) +#else +#define IS_RT2883(_pAd) (0) +#endif /* RT2883 */ + +#ifdef RT3883 +#define IS_RT3883(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x38830000) +#else +#define IS_RT3883(_pAd) (0) +#endif /* RT3883 */ + +#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)) /* 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) + +/* 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 + +/* RT3592BC8 (WiFi + BT) */ + + +#define IS_USB_INF(_pAd) ((_pAd)->infType == RTMP_DEV_INF_USB) +#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)) + +/* 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) + +/* ------------------------------------------------------ */ +/* 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 */ + +#if defined(RT2883) || defined(RT3883) +#define EEPROM_NIC3_OFFSET 0x38 /* The address is from NIC config 2, not BBP register ID */ +#endif /* defined(RT2883) || defined(RT3883) */ + +#if defined(RT2883) || defined(RT3883) +#define EEPROM_COUNTRY_REGION 0x3e +#else +#define EEPROM_COUNTRY_REGION 0x38 +#endif /* defined(RT2883) || defined(RT3883) */ + +#if defined(RT2883) || defined(RT3883) +#define EEPROM_DEFINE_MAX_TXPWR 0x40 +#else +#define EEPROM_DEFINE_MAX_TXPWR 0x4e +#endif /* defined(RT2883) || defined(RT3883) */ + +#if defined(RT2883) || defined(RT3883) +#ifdef RT2883 +#define EEPROM_FREQ_OFFSET 0x42 +#define EEPROM_LEDAG_CONF_OFFSET 0x44 +#define EEPROM_LEDACT_CONF_OFFSET 0x46 +#define EEPROM_LED_POLARITY_OFFSET 0x48 +#endif /* RT2883 */ +#ifdef RT3883 +#define EEPROM_FREQ_OFFSET 0x44 +#define EEPROM_LEDAG_CONF_OFFSET 0x46 +#define EEPROM_LEDACT_CONF_OFFSET 0x48 +#define EEPROM_LED_POLARITY_OFFSET 0x4a +#endif /* RT3883 */ +#else +#define EEPROM_FREQ_OFFSET 0x3a +#define EEPROM_LEDAG_CONF_OFFSET 0x3c +#define EEPROM_LEDACT_CONF_OFFSET 0x3e +#define EEPROM_LED_POLARITY_OFFSET 0x40 +#endif /* defined(RT2883) || defined(RT3883) */ + +#ifdef RT6352 +#define EEPROM_NIC3_OFFSET 0x42 +#endif /* RT6352 */ + +#if defined(RT2883) || defined(RT3883) +#define EEPROM_LNA_OFFSET 0x4c +#define EEPROM_LNA_OFFSET2 0x4e +#else +#define EEPROM_LNA_OFFSET 0x44 +#endif /* defined (RT2883) || defined (RT3883) */ + +#if defined(RT2883) || defined(RT3883) +#define EEPROM_RSSI_BG_OFFSET 0x50 +#define EEPROM_RSSI_A_OFFSET 0x54 +#else +#define EEPROM_RSSI_BG_OFFSET 0x46 +#define EEPROM_RSSI_A_OFFSET 0x4a +#define EEPROM_TXMIXER_GAIN_2_4G 0x48 +#define EEPROM_TXMIXER_GAIN_5G 0x4c +#endif /* defined(RT2883) || defined(RT3883) */ + +#define EEPROM_TXPOWER_DELTA 0x50 /* 20MHZ AND 40 MHZ use different power. This is delta in 40MHZ. */ + +#if defined(RT2883) || defined(RT3883) +#define EEPROM_G_TX_PWR_OFFSET 0x60 +#define EEPROM_G_TX2_PWR_OFFSET 0x6e +#define EEPROM_G_TX3_PWR_OFFSET 0x7c +#else +#define EEPROM_G_TX_PWR_OFFSET 0x52 +#define EEPROM_G_TX2_PWR_OFFSET 0x60 +#endif /* defined(RT2883) || defined(RT3883) */ + +#if defined(RT2883) || defined(RT3883) +#define EEPROM_G_TSSI_BOUND1 0x8a +#define EEPROM_G_TSSI_BOUND2 0x8c +#define EEPROM_G_TSSI_BOUND3 0x8e +#define EEPROM_G_TSSI_BOUND4 0x90 +#define EEPROM_G_TSSI_BOUND5 0x92 +#else +#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 +#endif /* defined(RT2883) || defined(RT3883) */ + +#if defined(RT2883) || defined(RT3883) +#define EEPROM_A_TX_PWR_OFFSET 0x96 +#define EEPROM_A_TX2_PWR_OFFSET 0xca +#define EEPROM_A_TX3_PWR_OFFSET 0xfe +#else +#define EEPROM_A_TX_PWR_OFFSET 0x78 +#define EEPROM_A_TX2_PWR_OFFSET 0xa6 +#endif /* defined (RT2883) || defined (RT3883) */ + +#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, +}; + +enum RXWI_FRQ_OFFSET_FIELD { + RXWI_FRQ_OFFSET_FIELD0, /* SNR1 */ + RXWI_FRQ_OFFSET_FIELD1, /* Frequency Offset */ +}; + + +#if defined(RT2883) || defined(RT3883) +#define EEPROM_A_TSSI_BOUND1 0x134 +#define EEPROM_A_TSSI_BOUND2 0x136 +#define EEPROM_A_TSSI_BOUND3 0x138 +#define EEPROM_A_TSSI_BOUND4 0x13a +#define EEPROM_A_TSSI_BOUND5 0x13c +#else +#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 +#endif /* defined(RT2883) || defined(RT3883) */ + +/* ITxBF calibration values EEPROM locations 0x1a0 to 0x1ab */ +#define EEPROM_ITXBF_CAL 0x1a0 + +#if defined(RT2883) || defined(RT3883) +#ifdef RT2883 +#define EEPROM_TXPOWER_BYRATE_CCK_OFDM 0x140 +#define EEPROM_TXPOWER_BYRATE_20MHZ_2_4G 0x146 /* 20MHZ 2.4G tx power. */ +#define EEPROM_TXPOWER_BYRATE_40MHZ_2_4G 0x156 /* 40MHZ 2.4G tx power. */ +#define EEPROM_TXPOWER_BYRATE_20MHZ_5G 0x166 /* 20MHZ 5G tx power. */ +#define EEPROM_TXPOWER_BYRATE_40MHZ_5G 0x176 /* 40MHZ 5G tx power. */ +#endif /* RT2883 */ +#ifdef RT3883 +#define EEPROM_TXPOWER_BYRATE_CCK_OFDM 0x140 +#define EEPROM_TXPOWER_BYRATE_40MHZ_OFDM_2_4G 0x150 +#define EEPROM_TXPOWER_BYRATE_20MHZ_OFDM_5G 0x160 +#define EEPROM_TXPOWER_BYRATE_40MHZ_OFDM_5G 0x170 +#define EEPROM_TXPOWER_BYRATE_20MHZ_2_4G 0x144 /* 20MHZ 2.4G tx power. */ +#define EEPROM_TXPOWER_BYRATE_40MHZ_2_4G 0x154 /* 40MHZ 2.4G tx power. */ +#define EEPROM_TXPOWER_BYRATE_20MHZ_5G 0x164 /* 20MHZ 5G tx power. */ +#define EEPROM_TXPOWER_BYRATE_40MHZ_5G 0x174 /* 40MHZ 5G tx power. */ +#endif /* RT3883 */ +#else +#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. */ +#endif /* defined(RT2883) || defined(RT3883) */ + +#if defined(RT2883) || defined(RT3883) +#define EEPROM_BBP_BASE_OFFSET 0x186 +#else +#define EEPROM_BBP_BASE_OFFSET 0xf0 /* The address is from NIC config 0, not BBP register ID */ +#endif /* defined(RT2883) || defined(RT3883) */ + +/* */ +/* 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 */ + + +/* + * 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)) + +/* ------------------------------------------------------------------- */ +/* 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_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 + +#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 */ + USHORT Rsv1:1; /* must be 0 */ + 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; /* */ + USHORT ExternalLNAForA:1; /* external LNA enable for 2.4G */ + 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 */ + USHORT Rsv1:1; /* must be 0 */ + 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 + + +/* */ +/* 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 + + +#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 */ + +#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) */ + +/* + 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; + + /* 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] */ + + UINT8 FlgIsVcoReCalMode; + + BOOLEAN FlgIsHwAntennaDiversitySup; +#ifdef STREAM_MODE_SUPPORT + BOOLEAN FlgHwStreamMode; +#endif /* STREAM_MODE_SUPPORT */ +#ifdef TXBF_SUPPORT + BOOLEAN FlgHwTxBfCap; +#endif /* TXBF_SUPPORT */ +#ifdef FIFO_EXT_SUPPORT + BOOLEAN FlgHwFifoExtCap; +#endif /* FIFO_EXT_SUPPORT */ + +#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 */ + + +#ifdef TXRX_SW_ANTDIV_SUPPORT + BOOLEAN bTxRxSwAntDiv; +#endif /* TXRX_SW_ANTDIV_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 MaxNss; /* maximum Nss, 3 for 3883 or 3593 */ + + BOOLEAN bTempCompTxALC; + + 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 RT305x +#if defined(RT3352) || defined(RT5350) + UINT8 TxPowerMaxCompenStep; + UINT8 TxPowerTableMaxIdx; +#endif /* defined(RT3352) || defined(RT5350) */ +#endif /* RT305x */ +#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) */ + + /* ---------------------------- 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; +#endif /* RTMP_EFUSE_SUPPORT */ + +#ifdef RTMP_FLASH_SUPPORT + UCHAR *eebuf; + 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 CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef MCS_LUT_SUPPORT + BOOLEAN bFlgHwTxLuCap; +#endif /* MCS_LUT_SUPPORT */ + INT16 DPDCalPassThres; + INT16 DPDCalPassLowThresTX0; + INT16 DPDCalPassLowThresTX1; + INT16 DPDCalPassHighThresTX0; + INT16 DPDCalPassHighThresTX1; +#ifdef HW_CALIBRATION_SUPPORT + BOOLEAN FlgRCalCap; + BOOLEAN FlgBwFilterCalCap; + BOOLEAN FlgDPDCalCap; + BOOLEAN FlgLoftTxIQCalCap; +#endif /* RF_CALIBRATION_SUPPORT */ +}; + +typedef VOID (*CHIP_SPEC_FUNC)(VOID *Adaptor, VOID *pData, ULONG Data); + +/* The chip specific function ID */ +typedef enum _CHIP_SPEC_ID +{ +#ifdef RT305x + RT305x_WLAN_MODE_CHANGE, + RT305x_INITIALIZATION, + RT305x_HT_MODE_CHANGE, +#endif /* RT305x */ + CHIP_SPEC_RESV_FUNC +} CHIP_SPEC_ID; + +#define CHIP_SPEC_ID_NUM CHIP_SPEC_RESV_FUNC + +struct _RTMP_CHIP_OP_ { + /* 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); + + /* MCU related callback functions */ + 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); */ + + 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)(IN struct _RTMP_ADAPTER *pAd, IN BOOLEAN ReduceCorePower); + VOID (*DisableAPMIMOPS)(IN struct _RTMP_ADAPTER *pAd); + + /* Chip tuning */ + VOID (*RxSensitivityTuning)(IN struct _RTMP_ADAPTER *pAd); + + /* MAC */ + VOID (*BeaconUpdate)( + IN struct _RTMP_ADAPTER *pAd, + IN USHORT Offset, + IN UINT32 Value, + IN UINT8 Unit); + + /* BBP adjust */ + VOID (*ChipBBPAdjust)(IN struct _RTMP_ADAPTER *pAd); + + /* AGC */ + VOID (*ChipAGCInit)( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR BandWidth); + UCHAR (*ChipAGCAdjust)( + IN struct _RTMP_ADAPTER *pAd, + IN CHAR Rssi, + IN UCHAR OrigR66Value); + + /* Channel */ + VOID (*ChipSwitchChannel)( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR Channel, + IN BOOLEAN bScan); + + /* IQ Calibration */ + VOID (*ChipIQCalibration)( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR Channel); + + UINT32 (*ChipGetCurrentTemp)( + IN struct _RTMP_ADAPTER *pAd); + +#ifdef THERMAL_PROTECT_SUPPORT + VOID (*ThermalProDefaultCond)( + IN struct _RTMP_ADAPTER *pAd); + + VOID (*ThermalPro1stCond)( + IN struct _RTMP_ADAPTER *pAd); + + VOID (*ThermalPro2ndCond)( + IN struct _RTMP_ADAPTER *pAd); +#endif /* THERMAL_PROTECT_SUPPORT */ + + /* TX ALC */ + UINT32 (*TSSIRatio)(IN INT32 delta_power); + + VOID (*InitDesiredTSSITable)(IN struct _RTMP_ADAPTER *pAd); + + int (*ATETssiCalibration)( + IN struct _RTMP_ADAPTER *pAd, + IN PSTRING arg); + + int (*ATETssiCalibrationExtend)( + IN struct _RTMP_ADAPTER *pAd, + IN PSTRING arg); + + VOID (*AsicTxAlcGetAutoAgcOffset)( + IN struct _RTMP_ADAPTER *pAd, + IN PCHAR pDeltaPwr, + IN PCHAR pTotalDeltaPwr, + IN PCHAR pAgcCompensate, + IN PCHAR pDeltaPowerByBbpR1); + + int (*ATEReadExternalTSSI)( + IN struct _RTMP_ADAPTER *pAd, + IN PSTRING arg); + + VOID (*AsicGetTxPowerOffset)( + IN struct _RTMP_ADAPTER *pAd, + IN PULONG TxPwr); + + VOID (*AsicExtraPowerOverMAC)( + IN struct _RTMP_ADAPTER *pAd); + + VOID (*AsicAdjustTxPower)( + IN struct _RTMP_ADAPTER *pAd); + + /* Antenna */ + VOID (*AsicAntennaDefaultReset)( + IN struct _RTMP_ADAPTER *pAd, + IN EEPROM_ANTENNA_STRUC *pAntenna); + + VOID (*SetRxAnt)( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR Ant); + + /* EEPROM */ + VOID (*NICInitAsicFromEEPROM)(IN struct _RTMP_ADAPTER *pAd); + + /* high power tuning */ + VOID (*HighPowerTuning)( + IN struct _RTMP_ADAPTER *pAd, + IN struct _RSSI_SAMPLE *pRssi); + + /* Others */ + VOID (*NetDevNickNameInit)(IN struct _RTMP_ADAPTER *pAd); + + /* 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)( + IN struct _RTMP_ADAPTER *pAd, + IN ULONG threshold); +#endif /* CARRIER_DETECTION_SUPPORT */ + VOID (*CckMrcStatusCtrl)( + IN struct _RTMP_ADAPTER *pAd); + VOID (*RadarGLRTCompensate)( + IN struct _RTMP_ADAPTER *pAd); + +#ifdef MICROWAVE_OVEN_SUPPORT + VOID (*AsicMeasureFalseCCA)( + IN struct _RTMP_ADAPTER *pAd); + VOID (*AsicMitigateMicrowave)( + IN struct _RTMP_ADAPTER *pAd); +#endif /* MICROWAVE_OVEN_SUPPORT */ +}; + +#define RTMP_CHIP_ENABLE_AP_MIMOPS(__pAd, __ReduceCorePower) \ + if (__pAd->chipOps.EnableAPMIMOPS != NULL) \ + __pAd->chipOps.EnableAPMIMOPS(__pAd, __ReduceCorePower) + +#define RTMP_CHIP_DISABLE_AP_MIMOPS(__pAd) \ + if (__pAd->chipOps.DisableAPMIMOPS != NULL) \ + __pAd->chipOps.DisableAPMIMOPS(__pAd) + +#define RTMP_CHIP_RX_SENSITIVITY_TUNING(__pAd) \ + if (__pAd->chipOps.RxSensitivityTuning != NULL) \ + __pAd->chipOps.RxSensitivityTuning(__pAd) + +#define RTMP_CHIP_ASIC_BBP_ADJUST(__pAd) \ + if (__pAd->chipOps.ChipBBPAdjust != NULL) \ + __pAd->chipOps.ChipBBPAdjust(__pAd) + +#define RTMP_CHIP_ASIC_AGC_ADJUST(__pAd, __Rssi, __R66) \ + if (__pAd->chipOps.ChipAGCAdjust != NULL) \ + __R66 = __pAd->chipOps.ChipAGCAdjust(__pAd, __Rssi, __R66) + +#define RTMP_CHIP_ASIC_AGC_INIT(__pAd, __Bandwidth) \ + if (__pAd->chipOps.ChipAGCInit != NULL) \ + __pAd->chipOps.ChipAGCInit(__pAd, __Bandwidth) + +#define RTMP_CHIP_ASIC_SWITCH_CHANNEL(__pAd, __Channel, __bScan) \ + if (__pAd->chipOps.ChipSwitchChannel != NULL) \ + __pAd->chipOps.ChipSwitchChannel(__pAd, __Channel, __bScan); \ + else \ + DBGPRINT(RT_DEBUG_ERROR, ("No switch channel function!!!\n")) + +#define RTMP_CHIP_ASIC_TSSI_TABLE_INIT(__pAd) \ + if (__pAd->chipOps.InitDesiredTSSITable != NULL) \ + __pAd->chipOps.InitDesiredTSSITable(__pAd) + +#define RTMP_CHIP_ATE_TSSI_CALIBRATION(__pAd, __pData) \ + if (__pAd->chipOps.ATETssiCalibration != NULL) \ + __pAd->chipOps.ATETssiCalibration(__pAd, __pData) + +#define RTMP_CHIP_ATE_TSSI_CALIBRATION_EXTEND(__pAd, __pData) \ + if (__pAd->chipOps.ATETssiCalibrationExtend != NULL) \ + __pAd->chipOps.ATETssiCalibrationExtend(__pAd, __pData) + +#define RTMP_CHIP_ATE_READ_EXTERNAL_TSSI(__pAd, __pData) \ + if (__pAd->chipOps.ATEReadExternalTSSI != NULL) \ + __pAd->chipOps.ATEReadExternalTSSI(__pAd, __pData) + +#define RTMP_CHIP_ASIC_TX_POWER_OFFSET_GET(__pAd, __pCfgOfTxPwrCtrlOverMAC) \ + if (__pAd->chipOps.AsicGetTxPowerOffset != NULL) \ + __pAd->chipOps.AsicGetTxPowerOffset(__pAd, __pCfgOfTxPwrCtrlOverMAC) + +#define RTMP_CHIP_ASIC_AUTO_AGC_OFFSET_GET( \ + __pAd, __pDeltaPwr, __pTotalDeltaPwr, __pAgcCompensate, __pDeltaPowerByBbpR1) \ + if (__pAd->chipOps.AsicTxAlcGetAutoAgcOffset != NULL) \ + __pAd->chipOps.AsicTxAlcGetAutoAgcOffset( \ + __pAd, __pDeltaPwr, __pTotalDeltaPwr, __pAgcCompensate, __pDeltaPowerByBbpR1) + +#define RTMP_CHIP_ASIC_EXTRA_POWER_OVER_MAC(__pAd) \ + if (__pAd->chipOps.AsicExtraPowerOverMAC != NULL) \ + __pAd->chipOps.AsicExtraPowerOverMAC(__pAd) + +#define RTMP_CHIP_ASIC_ADJUST_TX_POWER(__pAd) \ + if (__pAd->chipOps.AsicAdjustTxPower != NULL) \ + __pAd->chipOps.AsicAdjustTxPower(__pAd) + +#define RTMP_CHIP_ASIC_GET_TSSI_RATIO(__pAd, __DeltaPwr) \ + __pAd->chipOps.TSSIRatio(__DeltaPwr) + +#define RTMP_CHIP_GET_CURRENT_TEMP(__pAd) \ + if (__pAd->chipOps.ChipGetCurrentTemp != NULL) \ + __pAd->chipOps.ChipGetCurrentTemp(__pAd) + +#ifdef THERMAL_PROTECT_SUPPORT +#define RTMP_CHIP_THERMAL_PRO_DEFAULT_COND(__pAd) \ + if (__pAd->chipOps.ThermalProDefaultCond != NULL) \ + __pAd->chipOps.ThermalProDefaultCond(__pAd) + +#define RTMP_CHIP_THERMAL_PRO_1st_COND(__pAd) \ + if (__pAd->chipOps.ThermalPro1stCond != NULL) \ + __pAd->chipOps.ThermalPro1stCond(__pAd) + +#define RTMP_CHIP_THERMAL_PRO_2nd_COND(__pAd) \ + if (__pAd->chipOps.ThermalPro2ndCond != NULL) \ + __pAd->chipOps.ThermalPro2ndCond(__pAd) +#endif /* THERMAL_PROTECT_SUPPORT */ + +#define RTMP_CHIP_ASIC_FREQ_CAL_STOP(__pAd) \ + if (__pAd->chipOps.AsicFreqCalStop != NULL) \ + __pAd->chipOps.AsicFreqCalStop(__pAd) + +#define RTMP_CHIP_IQ_CAL(__pAd, __pChannel) \ + if (__pAd->chipOps.ChipIQCalibration != NULL) \ + __pAd->chipOps.ChipIQCalibration(__pAd, __pChannel) + +#define RTMP_CHIP_HIGH_POWER_TUNING(__pAd, __pRssi) \ + if (__pAd->chipOps.HighPowerTuning != NULL) \ + __pAd->chipOps.HighPowerTuning(__pAd, __pRssi) + +#define RTMP_CHIP_ANTENNA_INFO_DEFAULT_RESET(__pAd, __pAntenna) \ + if (__pAd->chipOps.AsicAntennaDefaultReset != NULL) \ + __pAd->chipOps.AsicAntennaDefaultReset(__pAd, __pAntenna) + +#define RTMP_NET_DEV_NICKNAME_INIT(__pAd) \ + if (__pAd->chipOps.NetDevNickNameInit != NULL) \ + __pAd->chipOps.NetDevNickNameInit(__pAd) + +#define RTMP_EEPROM_ASIC_INIT(__pAd) \ + if (__pAd->chipOps.NICInitAsicFromEEPROM != NULL) \ + __pAd->chipOps.NICInitAsicFromEEPROM(__pAd) + +#define RTMP_CHIP_SPECIFIC(__pAd, __FuncId, __pData, __Data) \ + if ((__FuncId >= 0) && (__FuncId < CHIP_SPEC_RESV_FUNC)) \ + { \ + if (__pAd->chipOps.ChipSpecFunc[__FuncId] != NULL) \ + __pAd->chipOps.ChipSpecFunc[__FuncId](__pAd, __pData, __Data); \ + } + +#define RTMP_CHIP_ASIC_RESET_BBP_AGENT( \ + __pAd) \ + if (__pAd->chipOps.AsicResetBbpAgent != NULL) \ + __pAd->chipOps.AsicResetBbpAgent( \ + __pAd) +#define RTMP_CHIP_UPDATE_BEACON(__pAd, Offset, Value, Unit) \ + if (__pAd->chipOps.BeaconUpdate != NULL) \ + __pAd->chipOps.BeaconUpdate(__pAd, Offset, Value, Unit) +#ifdef CARRIER_DETECTION_SUPPORT +#define RTMP_CHIP_CARRIER_PROGRAM(__pAd, threshold) \ + if(__pAd->chipOps.ToneRadarProgram != NULL) \ + __pAd->chipOps.ToneRadarProgram(__pAd, threshold) +#endif /* CARRIER_DETECTION_SUPPORT */ +#define RTMP_CHIP_CCK_MRC_STATUS_CTRL(__pAd) \ + if(__pAd->chipOps.CckMrcStatusCtrl != NULL) \ + __pAd->chipOps.CckMrcStatusCtrl(__pAd) +#define RTMP_CHIP_RADAR_GLRT_COMPENSATE(__pAd) \ + if(__pAd->chipOps.RadarGLRTCompensate != NULL) \ + __pAd->chipOps.RadarGLRTCompensate(__pAd) + + +/* function prototype */ +VOID RtmpChipOpsHook( + IN VOID *pCB); + +VOID RtmpChipBcnInit( + IN struct _RTMP_ADAPTER *pAd); + +VOID RtmpChipBcnSpecInit( + IN struct _RTMP_ADAPTER *pAd); + +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( + IN struct _RTMP_ADAPTER *pAd); + + +VOID NetDevNickNameInit(IN struct _RTMP_ADAPTER *pAd); + + + +#ifdef GREENAP_SUPPORT +VOID EnableAPMIMOPSv2( + IN struct _RTMP_ADAPTER *pAd, + IN BOOLEAN ReduceCorePower); + +VOID DisableAPMIMOPSv2( + IN struct _RTMP_ADAPTER *pAd); + +VOID EnableAPMIMOPSv1( + IN struct _RTMP_ADAPTER *pAd, + IN BOOLEAN ReduceCorePower); + +VOID DisableAPMIMOPSv1( + IN struct _RTMP_ADAPTER *pAd); +#endif /* GREENAP_SUPPORT */ + + +/* 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; + +#endif /* __RTMP_CHIP_H__ */ diff --git a/mt7620/src/include/rtmp_cmd.h b/mt7620/src/include/rtmp_cmd.h new file mode 100644 index 0000000..dee028b --- /dev/null +++ b/mt7620/src/include/rtmp_cmd.h @@ -0,0 +1,776 @@ +#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 */ + +/* 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 MESH_SUPPORT + SHOW_MESH_INFO = 12, + SHOW_NEIGHINFO_INFO = 13, + SHOW_MESH_ROUTE_INFO = 14, + SHOW_MESH_ENTRY_INFO = 15, + SHOW_MULPATH_INFO = 16, + SHOW_MCAST_AGEOUT_INFO = 17, + SHOW_MESH_PKTSIG_INFO = 18, + SHOW_MESH_PROXY_INFO = 19, +#endif /* MESH_SUPPORT */ +#ifdef QOS_DLS_SUPPORT + SHOW_DLS_ENTRY_INFO = 20, +#endif /* QOS_DLS_SUPPORT */ + SHOW_CFG_VALUE = 21, + SHOW_ADHOC_ENTRY_INFO = 22, +#ifdef DOT11Z_TDLS_SUPPORT + SHOW_TDLS_ENTRY_INFO = 25, +#endif /* DOT11Z_TDLS_SUPPORT */ +}; + +#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, +#ifdef CONFIG_APSTA_MIXED_SUPPORT + CMD_RTPRIV_IOCTL_MAX_IN_BIT, +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT +#ifdef CONFIG_PM +#ifdef USB_SUPPORT_SELECTIVE_SUSPEND + 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, +#ifdef WOW_SUPPORT +#endif /* WOW_SUPPORT */ +#endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ +#endif /* CONFIG_PM */ + 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 */ + + + /* 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, + + /* 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, + + 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_KEY_ADD, + CMD_RTPRIV_IOCTL_80211_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_END, +#endif /* RT_CFG80211_SUPPORT */ + + CMD_RTPRIV_IOCTL_ADAPTER_TSO_SUPPORT_TEST, + + /* 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_CHAN { + + UINT8 ChanId; + +#define RT_CMD_80211_IFTYPE_STATION 0x00 +#define RT_CMD_80211_IFTYPE_ADHOC 0x01 +#define RT_CMD_80211_IFTYPE_MONITOR 0x02 + UINT8 IfType; + +#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 + UINT8 ChanType; + + UINT32 MonFilterFlag; +} 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_IBSS { + + UINT32 BeaconInterval; + UCHAR *pSsid; +} CMD_RTPRIV_IOCTL_80211_IBSS; + +typedef struct __CMD_RTPRIV_IOCTL_80211_STA { + + UINT8 MAC[6]; + ULONG DataRate; + +#define RT_CMD_80211_TXRATE_LEGACY 0x01 +#define RT_CMD_80211_TXRATE_BW_40 0x02 +#define RT_CMD_80211_TXRATE_SHORT_GI 0x04 + UINT32 TxRateFlags; + + UINT32 TxRateMCS; + INT32 Signal; + UINT32 TxPacketCnt; + UINT32 InactiveTime; +} CMD_RTPRIV_IOCTL_80211_STA; + +typedef struct __CMD_RTPRIV_IOCTL_80211_KEY { + +#define RT_CMD_80211_KEY_WEP 0x00 +#define RT_CMD_80211_KEY_WPA 0x01 + UINT8 KeyType; + UINT8 KeyBuf[50]; + UINT8 KeyId; +} CMD_RTPRIV_IOCTL_80211_KEY; + +typedef struct __CMD_RTPRIV_IOCTL_80211_CONNECT { + + UINT8 WpaVer; + BOOLEAN FlgIs8021x; + BOOLEAN FlgIsAuthOpen; + +#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 + UINT8 PairwiseEncrypType; + UINT8 GroupwiseEncrypType; + + UINT8 *pKey; + UINT32 KeyLen; + UINT8 KeyIdx; + + UINT8 *pSsid; + UINT32 SsidLen; +} 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 UINT BulkInEpAddr; + IN USHORT BulkInMaxPacketSize; + IN UINT 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_STATS { + IN VOID *pNetDev; + OUT VOID *pStats; /* point to pAd->stats */ + + OUT unsigned long rx_packets; /* total packets received */ + OUT unsigned long tx_packets; /* total packets transmitted */ + OUT unsigned long rx_bytes; /* total bytes received */ + OUT unsigned long tx_bytes; /* total bytes 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_STATS; + +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 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 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 + 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; + +#endif /* __RTMP_CMD_H__ */ diff --git a/mt7620/src/include/rtmp_comm.h b/mt7620/src/include/rtmp_comm.h new file mode 100644 index 0000000..f46564e --- /dev/null +++ b/mt7620/src/include/rtmp_comm.h @@ -0,0 +1,488 @@ +/**************************************************************************** + + 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 +/*#define VENDOR_FEATURE3_SUPPORT */ + + +/*#define MONITOR_FLAG_11N_SNIFFER_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +/*#define AGS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef VENDOR_FEATURE3_SUPPORT +#ifdef DOT1X_SUPPORT +#undef DOT1X_SUPPORT +#endif /* DOT1X_SUPPORT */ +#ifdef SYSTEM_LOG_SUPPORT +#undef SYSTEM_LOG_SUPPORT +#endif /* SYSTEM_LOG_SUPPORT */ +#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 CONFIG_AP_SUPPORT + +#ifndef VENDOR_FEATURE3_SUPPORT +#define AP_QLOAD_SUPPORT +#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 */ +#define MAX_NUM_OF_CHS 54 + +/* 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" + + + + +/* ======================== 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 */ +}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 */ + +#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 + +/* associated with device interface */ +typedef struct _DEV_PRIV_INFO { + VOID *pPriv; /* pAd */ + UINT32 priv_flags; +} DEV_PRIV_INFO; + + + + +/*********************************************************************************** + * 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 + + + + +/* ======================== 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 */ + +/* */ +/* 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 */ +} PACKET_INFO, *PPACKET_INFO; + + +#define MAC_ADDR_LEN 6 + +/* 2-byte Frame control field */ + typedef struct GNU_PACKED { +#ifdef RT_BIG_ENDIAN + USHORT Order:1; /* Strict order expected */ + USHORT Wep:1; /* Wep data */ + USHORT MoreData:1; /* More data bit */ + USHORT PwrMgmt:1; /* Power management bit */ + USHORT Retry:1; /* Retry status bit */ + USHORT MoreFrag:1; /* More fragment bit */ + USHORT FrDs:1; /* From DS indication */ + USHORT ToDs:1; /* To DS indication */ + USHORT SubType:4; /* MSDU subtype */ + USHORT Type:2; /* MSDU type */ + USHORT Ver:2; /* Protocol version */ +#else + USHORT Ver:2; /* Protocol version */ + USHORT Type:2; /* MSDU type */ + USHORT SubType:4; /* MSDU subtype */ + USHORT ToDs:1; /* To DS indication */ + USHORT FrDs:1; /* From DS indication */ + USHORT MoreFrag:1; /* More fragment bit */ + USHORT Retry:1; /* Retry status bit */ + USHORT PwrMgmt:1; /* Power management bit */ + USHORT MoreData:1; /* More data bit */ + USHORT Wep:1; /* Wep data */ + USHORT Order:1; /* Strict order expected */ +#endif /* !RT_BIG_ENDIAN */ +} FRAME_CONTROL, *PFRAME_CONTROL; + + +typedef struct GNU_PACKED _HEADER_802_11 { + 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 Octet[0]; +} HEADER_802_11, *PHEADER_802_11; + +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 */ + + +#ifdef DPA_S +#define ETH_P_DPA_S_NOTIF 0x5572 +#endif /* DPA_S */ + +#endif /* __RT_COMM_H__ */ + +/* End of rt_comm.h */ diff --git a/mt7620/src/include/rtmp_def.h b/mt7620/src/include/rtmp_def.h new file mode 100644 index 0000000..3214c96 --- /dev/null +++ b/mt7620/src/include/rtmp_def.h @@ -0,0 +1,2050 @@ +/* + *************************************************************************** + * 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 NIC_TAG ((ULONG)'0682') +#define NIC_DBG_STRING ("**RT28xx**") + +#ifdef SNMP_SUPPORT +/* for snmp */ +/* to get manufacturer OUI, kathy, 2008_0220 */ +#define ManufacturerOUI_LEN 3 +#define ManufacturerNAME ("Ralink Technology Company.") +#define ResourceTypeIdName ("Ralink_ID") +#endif + +/*#define GNU_PACKED */ +#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 +#ifdef MESH_SUPPORT +#undef MAX_RX_PKT_LEN +/* Add Max Mesh Header Length (5 + 3 * Mac address Len) */ +#define MAX_RX_PKT_LEN 1520 + 5 + 18 +#endif /* MESH_SUPPORT */ + +/* */ +/* Entry number for each DMA descriptor ring */ +/* */ + + +#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 +#ifdef DESC_32B_SUPPORT +#define TXD_SIZE 32 +#define RXD_SIZE 32 +#else +#define TXD_SIZE 16 +#define RXD_SIZE 16 +#endif /* DESC_32B_SUPPORT */ + +/* 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_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) + +/* + 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; +*/ + +#define MAX_PACKETS_IN_MCAST_PS_QUEUE 32 +#define MAX_PACKETS_IN_PS_QUEUE 128 /*32 */ +#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 */ + +#ifdef RTMP_EFUSE_SUPPORT +#define MAX_EEPROM_BIN_FILE_SIZE 1024 +#define EFUSE_BUFFER_PATH "/tmp/RT30xxEEPROM.bin" +#endif /* RTMP_EFUSE_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_ADAPTER_HARDWARE_ERROR 0x00000004 +#define fRTMP_ADAPTER_SCATTER_GATHER 0x00000008 +#define fRTMP_ADAPTER_SEND_PACKET_ERROR 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_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 +#define fRTMP_ADAPTER_IDLE_RADIO_OFF 0x40000000 + +#define fRTMP_ADAPTER_DISABLE_DOT_11N 0x00000001 +#define fRTMP_ADAPTER_WSC_PBC_PIN0 0x00000002 +#define fRTMP_ADAPTER_TSO_SUPPORT 0x00000004 +#ifdef CONFIG_PM +#ifdef USB_SUPPORT_SELECTIVE_SUSPEND +#define fRTMP_ADAPTER_SUSPEND 0x00800000 +#endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ +#endif /* CONFIG_PM */ + +/* Lock bit for accessing different ring buffers */ +/*#define fRTMP_ADAPTER_TX_RING_BUSY 0x80000000 */ +/*#define fRTMP_ADAPTER_MGMT_RING_BUSY 0x40000000 */ +/*#define fRTMP_ADAPTER_ATIM_RING_BUSY 0x20000000 */ +/*#define fRTMP_ADAPTER_RX_RING_BUSY 0x10000000 */ + +/* Lock bit for accessing different queue */ +/*#define fRTMP_ADAPTER_TX_QUEUE_BUSY 0x08000000 */ +/*#define fRTMP_ADAPTER_MGMT_QUEUE_BUSY 0x04000000 */ + +/* */ +/* 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 P2P_SUPPORT +#define fOP_STATUS_P2P_GO 0x00080000 +#define fOP_STATUS_P2P_CLI 0x00100000 +#endif /* P2P_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 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 */ +#define fCLIENT_STATUS_RALINK_CHIPSET 0x00100000 + +#ifdef CLIENT_WDS +#define fCLIENT_STATUS_CLI_WDS 0x00200000 +#endif /* CLIENT_WDS */ + +#ifdef P2P_SUPPORT +#define fCLIENT_STATUS_P2P_CLI 0x00400000 +#endif /* P2P_SUPPORT */ + +/* */ +/* 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 4 +#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 +#ifdef MESH_SUPPORT +#undef MAX_MESH_NUM +#define MAX_MESH_NUM 1 /* please don't modify it */ +#endif /* MESH_SUPPORT */ + +#define MAX_APCLI_NUM 0 +#ifdef APCLI_SUPPORT +#undef MAX_APCLI_NUM +#define MAX_APCLI_NUM 1 +#endif /* APCLI_SUPPORT */ + +#define MAX_P2P_NUM 0 +#ifdef P2P_SUPPORT +#undef MAX_P2P_NUM +#define MAX_P2P_NUM 1 +#endif /* P2P_SUPPORT */ + +#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; } } + +#ifdef MAC_REPEATER_SUPPORT +#define MAX_MAC_TABLE_SIZE_WITH_REPEATER (MAX_LEN_OF_MAC_TABLE + ((MAX_EXT_MAC_ADDR_SIZE + 1) * MAX_APCLI_NUM)) +#define VALID_WCID(_wcid) ((_wcid) > 0 && (_wcid) < MAX_MAC_TABLE_SIZE_WITH_REPEATER) +#else +#define VALID_WCID(_wcid) ((_wcid) > 0 && (_wcid) < MAX_LEN_OF_MAC_TABLE ) +#endif /* MAC_REPEATER_SUPPORT */ + + +#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 MAC_ADDR_LEN 6 */ +#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 +#define SUPPORT_CCK_MODE 1 +#define SUPPORT_OFDM_MODE 2 +#define SUPPORT_HT_MODE 4 +/*============================================================ */ +/* 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 MAX_NUM_OF_ACL_LIST MAX_NUMBER_OF_ACL + +#define MAX_LEN_OF_MAC_TABLE MAX_NUMBER_OF_MAC /* if MAX_MBSSID_NUM is 8, this value can't be larger than 211 */ + +/*#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_TID 8 +#define MAX_AID_BA 4 +#ifdef MAC_REPEATER_SUPPORT +#define MAX_LEN_OF_BA_REC_TABLE ((NUM_OF_TID * MAX_MAC_TABLE_SIZE_WITH_REPEATER)/2) /* (NUM_OF_TID*MAX_AID_BA + 32) //Block ACK recipient */ +#define MAX_LEN_OF_BA_ORI_TABLE ((NUM_OF_TID * MAX_MAC_TABLE_SIZE_WITH_REPEATER)/2) /* (NUM_OF_TID*MAX_AID_BA + 32) // Block ACK originator */ +#else +#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 */ +#endif /* MAC_REPEATER_SUPPORT */ +#ifdef MEMORY_OPTIMIZATION +#define MAX_LEN_OF_BSS_TABLE 1 +#define MAX_REORDERING_MPDU_NUM 256 +#else +#define MAX_LEN_OF_BSS_TABLE 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_AUTO_SWITCH 0x03 */ +/*#define AUTH_MODE_DEAUTH 0x04 */ +/*#define AUTH_MODE_UPLAYER 0x05 // reserved for 802.11i use */ + +/* 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 + + +#define REASON_FT_INVALID_FTIE 55 + +/* Status code definitions */ +#define MLME_SUCCESS 0 +#define MLME_UNSPECIFY_FAIL 1 +#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 + + +#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_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_EXT_CAPABILITY 127 /* 802.11n D3.03 */ + +#define IE_WPA 221 /* WPA */ +#define IE_VENDOR_SPECIFIC 221 /* Wifi WMM (WME) */ +#define IE_WFA_WSC 221 + +#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 MESH_SUPPORT +#define MESH_CTRL_STATE_MACHINE 24 +#define MESH_LINK_MNG_STATE_MACHINE 25 +#endif /* MESH_SUPPORT */ + +#ifdef QOS_DLS_SUPPORT +#define DLS_STATE_MACHINE 26 +#endif /* QOS_DLS_SUPPORT */ + + +#ifdef DOT11Z_TDLS_SUPPORT +#define TDLS_STATE_MACHINE 29 +#endif /* DOT11Z_TDLS_SUPPORT */ + + +#ifdef P2P_SUPPORT +#define P2P_CTRL_STATE_MACHINE 31 +#define P2P_DISC_STATE_MACHINE 32 +#define P2P_GO_FORM_STATE_MACHINE 33 +#define P2P_ACTION_STATE_MACHINE 34 +#endif /* P2P_SUPPORT */ + + +#ifdef IWSC_SUPPORT +#define IWSC_STATE_MACHINE 38 +#endif // IWSC_SUPPORT // + +/* */ +/* 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 */ +#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 MAX_IEEE_STD_CATE 17 /* 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) + + +#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 DOT11Z_TDLS_SUPPORT +#define CATEGORY_TDLS 12 +#endif /* DOT11Z_TDLS_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_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 +#define HT_INFO_EXCHANGE 8 + +#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_CH_SWITCH_REQ 7 +#define MT2_MLME_TDLS_CH_SWITCH_RSP 8 +#define MT2_PEER_TDLS_CH_SWITCH_REQ 9 +#define MT2_PEER_TDLS_CH_SWITCH_RSP 10 +#define MT2_MLME_TDLS_PEER_PSM_REQ 11 +#define MT2_PEER_TDLS_PEER_PSM_REQ 12 +#define MT2_PEER_TDLS_PEER_PSM_RESP 13 +#define MT2_PEER_TDLS_TRAFFIC_RSP 14 /* for TDLS UAPSD */ +#define MT2_MLME_TDLS_DISCOVER_REQ 15 +#define MT2_PEER_TDLS_DISCOVER_REQ 16 +#define MT2_PEER_TDLS_DISCOVER_RSP 17 +#define MT2_MLME_TDLS_CH_SWITCH_REQ_DISABLE 18 +#define MAX_TDLS_MSG 19 + +#define TDLS_FUNC_SIZE (MAX_TDLS_STATE * MAX_TDLS_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_SCAN_PENDING 2 +#define AP_MAX_SYNC_STATE 3 +#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) + +/*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_PEER_PROBE_RSP 1 +#define APCLI_MT2_PEER_BEACON 2 +#define APCLI_MT2_PROBE_TIMEOUT 3 +#define APCLI_MAX_SYNC_MSG 4 + +#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 +#define APCLI_MAX_CTRL_STATE 7 + +#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 +#define APCLI_MAX_CTRL_MSG 14 + +#define APCLI_CTRL_FUNC_SIZE (APCLI_MAX_CTRL_STATE * APCLI_MAX_CTRL_MSG) + + +#endif /* APCLI_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#endif /* CONFIG_STA_SUPPORT */ + +/* ============================================================================= */ + + +/* 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_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_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_NULL_FUNC 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 + +/* 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 4 /* long preamble CCK 1Mbps. short is forbidden in 1Mbps */ +#define MCS_SHORTP_RATE_2 5 /* short preamble CCK 2Mbps */ +#define MCS_SHORTP_RATE_5_5 6 +#define MCS_SHORTP_RATE_11 7 +/* 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_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 +/* BW */ +#define BW_20 BAND_WIDTH_20 +#define BW_40 BAND_WIDTH_40 +#define BW_BOTH BAND_WIDTH_BOTH +#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. */ + +#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_ENABLE 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 +#ifdef CONFIG_SAMSUNG_REGULATORY_SUPPORT +#define REGION_30_A_BAND 30 +#define REGION_31_A_BAND 31 +#define REGION_32_A_BAND 32 +#define REGION_33_A_BAND 33 +#define REGION_34_A_BAND 34 +#define REGION_35_A_BAND 35 +#define REGION_36_A_BAND 36 +#define REGION_37_A_BAND 37 +#endif // CONFIG_SAMSUNG_REGULATORY_SUPPORT // +#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 + + +#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 + + +/* 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 33 /* 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 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 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_REPEATER 7 + +#ifdef P2P_SUPPORT +#define P2P_ENTRY_NONE 0 +#define P2P_GO_ENTRY 1 +#define P2P_CLI_ENTRY 2 +#endif /* P2P_SUPPORT */ + +#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 */ +#ifdef P2P_SUPPORT +#define IS_ENTRY_P2PCLI(_x) CLIENT_STATUS_TEST_FLAG((_x), fCLIENT_STATUS_P2P_CLI) +#define IS_P2P_ENTRY_NONE(_x) ((_x)->P2PEntryType == P2P_ENTRY_NONE) +#define IS_P2P_GO_ENTRY(_x) ((_x)->P2PEntryType == P2P_GO_ENTRY) +#define IS_P2P_CLI_ENTRY(_x) ((_x)->P2PEntryType == P2P_CLI_ENTRY) +#endif /* P2P_SUPPORT */ + +#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 */ +#ifdef P2P_SUPPORT +#define SET_ENTRY_P2PCLI(_x) CLIENT_STATUS_SET_FLAG((_x), fCLIENT_STATUS_P2P_CLI) +#define SET_P2P_GO_ENTRY(_x) ((_x)->P2PEntryType = P2P_GO_ENTRY) +#define SET_P2P_CLI_ENTRY(_x) ((_x)->P2PEntryType = P2P_CLI_ENTRY) +#define SET_P2P_ENTRY_NONE(_x) ((_x)->P2PEntryType = P2P_ENTRY_NONE) +#endif /* P2P_SUPPORT */ + +#define SET_OPMODE_AP(_x) ((_x)->OpMode = OPMODE_AP) +#define SET_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) + +#ifdef DPA_S +#define INF_MAIN_DEV_NAME "ra11n" +#define INF_MBSSID_DEV_NAME "ra11n" +#else +#ifdef ANDROID_SUPPORT +#define INF_MAIN_DEV_NAME "wlan" +#define INF_MBSSID_DEV_NAME "wlan" +#else +#define INF_MAIN_DEV_NAME "ra" +#define INF_MBSSID_DEV_NAME "ra" +#endif /* ANDROID_SUPPORT */ +#endif +#define INF_WDS_DEV_NAME "wds" +#define INF_APCLI_DEV_NAME "apcli" +#define INF_MESH_DEV_NAME "mesh" +#define INF_P2P_DEV_NAME "p2p" + +#ifdef RALINK_ATE +/* + Use bitmap to allow coexist of ATE_TXFRAME + and ATE_RXFRAME(i.e.,to support LoopBack mode). +*/ +#define fATE_IDLE 0x00 +#define fATE_TX_ENABLE 0x01 +#define fATE_RX_ENABLE 0x02 +#define fATE_TXCONT_ENABLE 0x04 +#define fATE_TXCARR_ENABLE 0x08 +#define fATE_TXCARRSUPP_ENABLE 0x10 +#define fATE_RESERVED_1 0x20 +#define fATE_RESERVED_2 0x40 +#define fATE_EXIT 0x80 + +/* Enter/Reset ATE */ +#define ATE_START (fATE_IDLE) +/* Stop/Exit ATE */ +#define ATE_STOP (fATE_EXIT) +/* Continuous Transmit Frames (without time gap) */ +#define ATE_TXCONT ((fATE_TX_ENABLE)|(fATE_TXCONT_ENABLE)) +/* Transmit Carrier */ +#define ATE_TXCARR ((fATE_TX_ENABLE)|(fATE_TXCARR_ENABLE)) +/* Transmit Carrier Suppression (information without carrier) */ +#define ATE_TXCARRSUPP ((fATE_TX_ENABLE)|(fATE_TXCARRSUPP_ENABLE)) +/* Transmit Frames */ +#define ATE_TXFRAME (fATE_TX_ENABLE) +/* Receive Frames */ +#define ATE_RXFRAME (fATE_RX_ENABLE) +#ifdef RALINK_QA +/* Stop Transmission */ +#define ATE_TXSTOP ((~(fATE_TX_ENABLE))&(~(fATE_TXCONT_ENABLE))&(~(fATE_TXCARR_ENABLE))&(~(fATE_TXCARRSUPP_ENABLE))) +/* Stop Receiving Frames */ +#define ATE_RXSTOP (~(fATE_RX_ENABLE)) + +/* NOTE : may be different with chipset in the future ++ */ +#define BBP22_TXFRAME 0x00 /* Transmit Frames */ +#define BBP22_TXCONT_OR_CARRSUPP 0x80 /* Continuous Transmit or Carrier Suppression */ +#define BBP22_TXCARR 0xc1 /* Transmit Carrier */ +#define BBP24_TXCONT 0x00 /* Continuous Transmit */ +#define BBP24_CARRSUPP 0x01 /* Carrier Suppression */ +/* NOTE : may be different with chipset in the future -- */ +#endif /* RALINK_QA */ +#endif /* RALINK_ATE */ + +/* 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, kathy */ +#define MAX_NUM_OF_INIT_DLS_ENTRY 1 +#define MAX_NUM_OF_DLS_ENTRY MAX_NUMBER_OF_DLS_ENTRY + +/*Block ACK, kathy */ +#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 +#endif /* MCAST_RATE_SPECIFIC */ + +/* For AsicRadioOff/AsicRadioOn function */ +#define DOT11POWERSAVE 0 +#define GUIRADIO_OFF 1 +#define RTMP_HALT 2 +#define GUI_IDLE_POWER_SAVE 3 +/* -- */ + +/* 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 + +/* 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 MICROWAVE_OVEN_SUPPORT +/* definition for mitigating microwave interference */ +#define MO_FALSE_CCA_TH 25 +#define MO_MEAS_PERIOD 0 /* 0 ~ 100 ms */ +#define MO_IDLE_PERIOD 1 /* 100 ~ 1000 ms */ +#endif /* MICROWAVE_OVEN_SUPPORT */ + + +#define ABS(_x, _y) ((_x) > (_y)) ? ((_x) -(_y)) : ((_y) -(_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/mt7620/src/include/rtmp_dot11.h b/mt7620/src/include/rtmp_dot11.h new file mode 100644 index 0000000..d8d6624 --- /dev/null +++ b/mt7620/src/include/rtmp_dot11.h @@ -0,0 +1,85 @@ +/* + +*/ + +#ifndef __DOT11_BASE_H__ +#define __DOT11_BASE_H__ + +#include "rtmp_type.h" + +#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; /*RDG / More PPDU */ + UINT32 ACConstraint:1; /*feedback request */ + UINT32 rsv2:5; /*calibration sequence */ + UINT32 NDPAnnounce:1; /* ZLF announcement */ + UINT32 CSISTEERING:2; /*CSI/ STEERING */ + UINT32 rsv1:2; /* Reserved */ + UINT32 CalSeq:2; /*calibration sequence */ + UINT32 CalPos:2; /* calibration position */ + UINT32 MFBorASC:7; /*Link adaptation feedback containing recommended MCS. 0x7f for no feedback or not available */ + UINT32 MFSI:3; /*SET to the received value of MRS. 0x111 for unsolicited MFB. */ + UINT32 MSI:3; /*MCS Request, MRQ Sequence identifier */ + UINT32 MRQ:1; /*MCS feedback. Request for a MCS feedback */ + UINT32 TRQ:1; /*sounding request */ + UINT32 rsv:1; /* Reserved */ +#else + UINT32 rsv:1; /* Reserved */ + 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 _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/mt7620/src/include/rtmp_iface.h b/mt7620/src/include/rtmp_iface.h new file mode 100644 index 0000000..6243b5a --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/rtmp_mcu.h b/mt7620/src/include/rtmp_mcu.h new file mode 100644 index 0000000..d2a6fa8 --- /dev/null +++ b/mt7620/src/include/rtmp_mcu.h @@ -0,0 +1,52 @@ +/* + *************************************************************************** + * 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.h + + Abstract: + Miniport header file for mcu related information + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RTMP_MCU_H__ +#define __RTMP_MCU_H__ + +INT RtmpAsicEraseFirmware( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS RtmpAsicLoadFirmware( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS isMCUnotReady( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS isMCUNeedToLoadFIrmware( + IN PRTMP_ADAPTER pAd); + +INT RtmpAsicSendCommandToMcu( + IN PRTMP_ADAPTER pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1, + IN BOOLEAN FlgIsNeedLocked); + +#endif /* __RTMP_MCU_H__ */ diff --git a/mt7620/src/include/rtmp_os.h b/mt7620/src/include/rtmp_os.h new file mode 100644 index 0000000..335d3b9 --- /dev/null +++ b/mt7620/src/include/rtmp_os.h @@ -0,0 +1,135 @@ +/**************************************************************************** + * 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; + +#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 */ + + + + + +/* + 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; + 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( + IN PNET_DEV pNetDev); +/*int RtmpOSIRQRelease(IN 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/mt7620/src/include/rtmp_osabl.h b/mt7620/src/include/rtmp_osabl.h new file mode 100644 index 0000000..fc00265 --- /dev/null +++ b/mt7620/src/include/rtmp_osabl.h @@ -0,0 +1,70 @@ +/**************************************************************************** + + 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__ */ + +/* End of rtmp_osabl.h */ diff --git a/mt7620/src/include/rtmp_timer.h b/mt7620/src/include/rtmp_timer.h new file mode 100644 index 0000000..5f9a760 --- /dev/null +++ b/mt7620/src/include/rtmp_timer.h @@ -0,0 +1,231 @@ +/* + *************************************************************************** + * 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 CONFIG_STA_SUPPORT +#ifdef ADHOC_WPA2PSK_SUPPORT +DECLARE_TIMER_FUNCTION(Adhoc_WpaRetryExec); +#endif /* ADHOC_WPA2PSK_SUPPORT */ +#endif /* CONFIG_STA_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 */ + +#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); +DECLARE_TIMER_FUNCTION(RadioOnExec); +#endif /* RTMP_PCI_SUPPORT */ +#ifdef QOS_DLS_SUPPORT +DECLARE_TIMER_FUNCTION(DlsTimeoutAction); +#endif /* QOS_DLS_SUPPORT */ + +#ifdef DOT11Z_TDLS_SUPPORT +DECLARE_TIMER_FUNCTION(TDLS_TimeoutAction); +#endif /* DOT11Z_TDLS_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 MESH_SUPPORT +DECLARE_TIMER_FUNCTION(MeshPathReqTimeoutAction); +#endif /* MESH_SUPPORT */ + + +#ifdef P2P_SUPPORT +DECLARE_TIMER_FUNCTION(P2PCTWindowTimer); +DECLARE_TIMER_FUNCTION(P2pSwNoATimeOut); +DECLARE_TIMER_FUNCTION(P2pPreAbsenTimeOut); +DECLARE_TIMER_FUNCTION(P2pWscTimeOut); +DECLARE_TIMER_FUNCTION(P2pReSendTimeOut); +DECLARE_TIMER_FUNCTION(P2pCliReConnectTimeOut); +#endif /* 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 APCLI_SUPPORT +DECLARE_TIMER_FUNCTION(ApCliWpaDisassocApAndBlockAssoc); +#endif /* APCLI_SUPPORT */ + +#ifdef PEER_DELBA_TX_ADAPT +DECLARE_TIMER_FUNCTION(PeerDelBATxAdaptTimeOut); +#endif /* PEER_DELBA_TX_ADAPT */ + +#endif /* __RTMP_TIMER_H__ */ diff --git a/mt7620/src/include/rtmp_type.h b/mt7620/src/include/rtmp_type.h new file mode 100644 index 0000000..930e445 --- /dev/null +++ b/mt7620/src/include/rtmp_type.h @@ -0,0 +1,165 @@ +/* + *************************************************************************** + * 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 { + ULONG Register; + ULONG 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; + +/* */ +/* 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; + ULONG Number; +} QUEUE_HEADER, *PQUEUE_HEADER; + +#endif /* __RTMP_TYPE_H__ */ diff --git a/mt7620/src/include/spectrum.h b/mt7620/src/include/spectrum.h new file mode 100644 index 0000000..6a2c1bd --- /dev/null +++ b/mt7620/src/include/spectrum.h @@ -0,0 +1,215 @@ + +#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); + + +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); +#endif /* __SPECTRUM_H__ */ + diff --git a/mt7620/src/include/spectrum_def.h b/mt7620/src/include/spectrum_def.h new file mode 100644 index 0000000..316956c --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/sta_cfg.h b/mt7620/src/include/sta_cfg.h new file mode 100644 index 0000000..9c8ef71 --- /dev/null +++ b/mt7620/src/include/sta_cfg.h @@ -0,0 +1,41 @@ +/* + *************************************************************************** + * 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); + +#ifdef WOW_SUPPORT +#endif /* WOW_SUPPORT */ + +#endif /* __STA_CFG_H__ */ diff --git a/mt7620/src/include/tdls.h b/mt7620/src/include/tdls.h new file mode 100644 index 0000000..815822e --- /dev/null +++ b/mt7620/src/include/tdls.h @@ -0,0 +1,842 @@ +/**************************************************************************** + * 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_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_TdlsCapableProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TdlsSetupProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_TdlsTearDownProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT +Set_TdlsDiscoveryReqProc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT +Set_TdlsTPKLifeTimeProc( + 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 */ + +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); + +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); + +#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_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); + +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_MlmeTearDownAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID +TDLS_PeerTearDownAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID +TDLS_MlmeDiscoveryReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID +TDLS_PeerDiscoveryReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +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); + +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, + 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[], + OUT UCHAR *pLinkIdentLen, + OUT TDLS_LINK_IDENT_ELEMENT *pLinkIdent); + +BOOLEAN +PeerTdlsSetupRspSanity( + 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 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[], + OUT UCHAR *pLinkIdentLen, + OUT TDLS_LINK_IDENT_ELEMENT *pLinkIdent); + +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[], + OUT UCHAR *pLinkIdentLen, + OUT TDLS_LINK_IDENT_ELEMENT *pLinkIdent, + OUT UCHAR *pAddHtInfoLen, + OUT ADD_HT_INFO_IE *pAddHtInfo); + +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[], + OUT UCHAR *pLinkIdentLen, + OUT TDLS_LINK_IDENT_ELEMENT *pLinkIdent); + +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[], + OUT UCHAR *pLinkIdentLen, + OUT TDLS_LINK_IDENT_ELEMENT *pLinkIdent); + +VOID +TDLS_TimeoutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +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, + 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); + +BOOLEAN +MlmeTdlsReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PRT_802_11_TDLS *pTDLS, + OUT PUINT16 pReason, + OUT BOOLEAN *pIsViaAP); + +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_MlmeSetupReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID +TDLS_LinkTimeoutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID +TDLS_InitChannelRelatedValue( + IN PRTMP_ADAPTER pAd, + IN HT_CAPABILITY_IE *pHtCapability); + +#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 // +#endif /* __TDLS_H */ +#endif /* DOT11Z_TDLS_SUPPORT */ diff --git a/mt7620/src/include/tdls_cmm.h b/mt7620/src/include/tdls_cmm.h new file mode 100644 index 0000000..8ee30a5 --- /dev/null +++ b/mt7620/src/include/tdls_cmm.h @@ -0,0 +1,202 @@ +/**************************************************************************** + * 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 + +#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. */ + +#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_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_LINK_MNG_FUNC_SIZE (TDLS_LINK_MNG_MAX_STATES * TDLS_LINK_MNG_MAX_EVENTS) + +#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; + + /* Channel Switch */ + UINT8 TdlsTargetChannel; + UINT8 TdlsTargetChannelBW; + BOOLEAN bDoingPeriodChannelSwitch; + BOOLEAN bChannelSwitchInitiator; + UCHAR ChannelSwitchCurrentState; + USHORT ChSwitchTime; + RALINK_TIMER_STRUCT ChannelSwitchTimer; // Use to channel switch + USHORT ChSwitchTimeout; + RALINK_TIMER_STRUCT ChannelSwitchTimeoutTimer; // Use to channel switch + BOOLEAN bEnableChSwitchTime; + ULONG ChannelSwitchTimerStartTime; + +} 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 sleep */ \ + 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, FALSE); \ +} +#endif /* __TDLS_CMM_H */ +#endif /* DOT11Z_TDLS_SUPPORT */ + diff --git a/mt7620/src/include/tdls_uapsd.h b/mt7620/src/include/tdls_uapsd.h new file mode 100644 index 0000000..cbe5a44 --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/uapsd.h b/mt7620/src/include/uapsd.h new file mode 100644 index 0000000..48857a5 --- /dev/null +++ b/mt7620/src/include/uapsd.h @@ -0,0 +1,770 @@ +/**************************************************************************** + * 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->Aid); \ + } \ + } \ + 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. +*/ +#define UAPSD_SP_ACCURATE /* use more accurate method to send EOSP */ +#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 APRxDoneInterruptHandle() + +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/mt7620/src/include/video.h b/mt7620/src/include/video.h new file mode 100644 index 0000000..54ec5e6 --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/vr_ikans.h b/mt7620/src/include/vr_ikans.h new file mode 100644 index 0000000..c5694cb --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/vrut_ubm.h b/mt7620/src/include/vrut_ubm.h new file mode 100644 index 0000000..fab13c4 --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/wapi.h b/mt7620/src/include/wapi.h new file mode 100644 index 0000000..2fbc79f --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/wapi_def.h b/mt7620/src/include/wapi_def.h new file mode 100644 index 0000000..774bdae --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/wapi_sms4.h b/mt7620/src/include/wapi_sms4.h new file mode 100644 index 0000000..ef90f2a --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/wfa_p2p.h b/mt7620/src/include/wfa_p2p.h new file mode 100644 index 0000000..8f5f5d5 --- /dev/null +++ b/mt7620/src/include/wfa_p2p.h @@ -0,0 +1,158 @@ +/**************************************************************************** + * 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 + +#define GNU_PACKED __attribute__ ((packed)) + +#ifdef P2P_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 + +#endif /* P2P_SUPPORT */ + +#endif /* __WFA_P2P_H */ + diff --git a/mt7620/src/include/wpa.h b/mt7620/src/include/wpa.h new file mode 100644 index 0000000..26134e2 --- /dev/null +++ b/mt7620/src/include/wpa.h @@ -0,0 +1,581 @@ +/* + *************************************************************************** + * 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) \ + { \ + _cipher = Ndis802_11WEPDisabled; \ + if ((_pAd)->OpMode == OPMODE_AP) \ + { \ + if (IS_ENTRY_APCLI(_pEntry) && \ + ((_pEntry)->MatchAPCLITabIdx < MAX_APCLI_NUM)) \ + _cipher = (_pAd)->ApCfg.ApCliTab[(_pEntry)->MatchAPCLITabIdx].GroupCipher; \ + else if ((_pEntry)->apidx < (_pAd)->ApCfg.BssidNum) \ + _cipher = (_pAd)->ApCfg.MBSSID[_pEntry->apidx].GroupKeyWepStatus;\ + } \ + else \ + _cipher = (_pAd)->StaCfg.GroupCipher; \ + } + +#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) \ + { \ + _cipher = Ndis802_11WEPDisabled; \ + if (IS_ENTRY_APCLI(_pEntry) && \ + ((_pEntry)->MatchAPCLITabIdx < MAX_APCLI_NUM)) \ + _cipher = (_pAd)->ApCfg.ApCliTab[(_pEntry)->MatchAPCLITabIdx].GroupCipher; \ + else if ((_pEntry)->apidx < (_pAd)->ApCfg.BssidNum) \ + _cipher = (_pAd)->ApCfg.MBSSID[_pEntry->apidx].GroupKeyWepStatus;\ + } + +#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) \ + { \ + _cipher = (_pAd)->StaCfg.GroupCipher; \ + } +#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 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); + +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); + +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 + ===================================== +*/ +BOOLEAN 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); + +#endif diff --git a/mt7620/src/include/wpa_cmm.h b/mt7620/src/include/wpa_cmm.h new file mode 100644 index 0000000..16ec350 --- /dev/null +++ b/mt7620/src/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/mt7620/src/include/wsc.h b/mt7620/src/include/wsc.h new file mode 100644 index 0000000..48e8789 --- /dev/null +++ b/mt7620/src/include/wsc.h @@ -0,0 +1,972 @@ +/* + *************************************************************************** + * 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( + IN PUCHAR pData) +{ + PWSC_FRAME pWsc; + + pWsc = (PWSC_FRAME) pData; + + /* Verify SMI first */ + if (((pWsc->SMI[0] * 256 + pWsc->SMI[1]) * 256 + pWsc->SMI[2]) != WSC_SMI) + { + /* Wrong WSC SMI Vendor ID, Update WSC status */ + return FALSE; + } + + /* Verify Vendor Type */ + if (cpu2be32(get_unaligned32(&pWsc->VendorType)) != WSC_VENDOR_TYPE) + { + /* Wrong WSC Vendor Type, Update WSC status */ + return FALSE; + } + 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 +#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 +#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 */ +#ifdef CONFIG_WIFI_LED_SHARE +#define WSC_WPS_FAIL_WIFI_LED_TIMEOUT 120000 /* 120 seconds */ +#define WSC_WPS_OVERLAP_WIFI_LED_TIMEOUT 120000 /* 120 seconds */ +#define WSC_WPS_PREPOST_WIFI_LED_TIMEOUT 3000 /* 3seconds */ +#endif /* CONFIG_WIFI_LED_SHARE */ +#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 */ + +#ifdef WSC_V2_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 +#endif /* WSC_V2_SUPPORT */ + +#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 + +/* 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 +#ifdef EASY_CONFIG_SETUP +#define MODULE_TV 0x00 +#define MODULE_BD 0x01 +#define MODULE_UNKNOW 0xFF + +#define INFRA_CONNECTION_TIMEOUT 12000 /* 12 seconds */ +#define ADHOC_CONNECTION_TIMEOUT 35000 /* 35 seconds */ +#endif /* EASY_CONFIG_SETUP */ +#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 + +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 */ +#ifdef CONFIG_STA_SUPPORT + WSC_PROFILE WscM7Profile; /* Saved WSC profile from AP Settings in M7 */ + BOOLEAN bConfiguredAP; /* True: AP is in the configured state. FALSE: others */ +#endif /* CONFIG_STA_SUPPORT */ + 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 CONFIG_AP_SUPPORT + BOOLEAN bWscAutoTriggerDisable; /* Default setting is FALSE */ +#endif /* CONFIG_AP_SUPPORT */ +} WSC_CTRL, *PWSC_CTRL; + +typedef struct GNU_PACKED _WSC_CONFIGURED_VALUE { + USHORT WscConfigured; /* 1 un-configured; 2 configured */ + UCHAR WscSsid[32]; + UCHAR WscSsidLen; + 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]; + 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, +}WSC_SECURITY_MODE; + +typedef struct _WSC_PEER_ENTRY { + struct _WSC_PEER_ENTRY *pNext; + ULONG receive_time; + UCHAR mac_addr[MAC_ADDR_LEN]; +#ifdef WAC_QOS_PRIORITY + UCHAR device_type; +#endif /* WAC_QOS_PRIORITY */ +#ifdef IWSC_SUPPORT + BOOLEAN bIWscSmpbcAccept; +#endif /* IWSC_SUPPORT */ +} WSC_PEER_ENTRY, *PWSC_PEER_ENTRY; + +#ifdef WAC_SUPPORT +#define OFC_SUCCESS 0x0000 +#define OFC_FAILED_NO_WAC_AP 0x0001 +#define OFC_FAILED_LOW_RSSI 0x0002 +#define OFC_FAILED_INVALID_PARAM 0x0003 +#define OFC_FAILED_REJECT 0x0004 +#define OFC_PROCEED_FIRST_PHASE 0x0005 +#define OFC_PROCEED_SECOND_PHASE 0x0006 + +#define WAC_CMD_ADD 0x00 +#define WAC_CMD_DEL 0x01 + +#define WAC_CMD_FOR_PROBE_REQ 0x00 +#define WAC_CMD_FOR_PROBE_RSP 0x01 +#define WAC_CMD_FOR_BEACON 0x02 +#endif /* WAC_SUPPORT */ + +#endif /* WSC_INCLUDED */ + +#endif /* __WSC_H__ */ + diff --git a/mt7620/src/include/wsc_tlv.h b/mt7620/src/include/wsc_tlv.h new file mode 100644 index 0000000..de72cf3 --- /dev/null +++ b/mt7620/src/include/wsc_tlv.h @@ -0,0 +1,289 @@ +/* + *************************************************************************** + * 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_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/mt7620/src/iwpriv_usage.txt b/mt7620/src/iwpriv_usage.txt new file mode 100755 index 0000000..940d646 --- /dev/null +++ b/mt7620/src/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/mt7620/src/load.4 b/mt7620/src/load.4 new file mode 100644 index 0000000..8b03a43 --- /dev/null +++ b/mt7620/src/load.4 @@ -0,0 +1,4 @@ +insmod UTIL/os/linux/rtutil3572sta.o +insmod MODULE/os/linux/rt3572sta.o +insmod NETIF/os/linux/rtnet3572sta.o +ifconfig ra0 up \ No newline at end of file diff --git a/mt7620/src/load.6 b/mt7620/src/load.6 new file mode 100644 index 0000000..d61c913 --- /dev/null +++ b/mt7620/src/load.6 @@ -0,0 +1,4 @@ +insmod UTIL/os/linux/rtutil3572sta.ko +insmod MODULE/os/linux/rt3572sta.ko +insmod NETIF/os/linux/rtnet3572sta.ko +ifconfig ra0 up diff --git a/mt7620/src/mbss_phy.readme b/mt7620/src/mbss_phy.readme new file mode 100755 index 0000000..6a7be3b --- /dev/null +++ b/mt7620/src/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/mt7620/src/os/linux/Kconfig.ap.soc b/mt7620/src/os/linux/Kconfig.ap.soc new file mode 100755 index 0000000..1484538 --- /dev/null +++ b/mt7620/src/os/linux/Kconfig.ap.soc @@ -0,0 +1,163 @@ +config RT2860V2_AP + tristate "Ralink RT2860 802.11n AP support" + depends on NET_RADIO + +config RT2860V2_AP_V24_DATA_STRUCTURE + bool + depends on RT2860V2_AP + default y + +config RT2860V2_AP_LED + bool "LED Support" + depends on RT2860V2_AP + +config RT2860V2_AP_WSC + bool "WSC (WiFi Simple Config)" + depends on RT2860V2_AP + +config RT2860V2_AP_LLTD + bool "LLTD (Link Layer Topology Discovery Protocol)" + depends on RT2860V2_AP + +config RT2860V2_AP_WDS + bool "WDS" + depends on RT2860V2_AP + +config RT2860V2_AP_NINTENDO + bool "Nintendo" + depends on RT2860V2_AP + +config RT2860V2_AP_WMM_ACM + bool "WMM ACM" + depends on RT2860V2_AP + +config RT2860V2_AP_MBSS + bool "MBSSID" + depends on RT2860V2_AP + +config NEW_MBSSID_MODE + bool "New MBSSID MODE" + depends on RT2860V2_AP + depends on RT2860V2_AP_MBSS + depends on RALINK_RT3883 || RALINK_RT3352 || RALINK_RT5350 + default n + +config RT2860V2_AP_APCLI + bool "AP-CLient Support" + depends on RT2860V2_AP + +config RT2860V2_AP_IGMP_SNOOP + bool "IGMP snooping" + depends on RT2860V2_AP + +config RT2860V2_AP_NETIF_BLOCK + bool "NETIF Block" + depends on RT2860V2_AP + help + Support Net interface block while Tx-Sw queue full + +config RT2860V2_AP_DFS + bool "DFS" + depends on RT2860V2_AP + select RALINK_TIMER_DFS + +config RT2860V2_AP_CARRIER + bool "Carrier Detect" + depends on RT2860V2_AP + select RALINK_TIMER_DFS + +config RT2860V2_AP_DLS + bool "DLS ((Direct-Link Setup) Support" + depends on RT2860V2_AP + +config RT2860V2_AP_IDS + bool "IDS (Intrusion Detection System) Support" + depends on RT2860V2_AP + +config RT2860V2_AP_MESH + bool "MESH Support" + depends on RT2860V2_AP + +config RT2860V2_HW_ANTENNA_DIVERSITY + bool "Antenna Diversity Support" + depends on RT2860V2_AP + depends on RALINK_RT5350 + +config RT2860V2_RT3XXX_AP_ANTENNA_DIVERSITY + bool "Antenna Diversity Support" + depends on RT2860V2_AP + +config RT2860V2_AP_WAPI + bool "WAPI Support" + depends on RT2860V2_AP + +config RT2860V2_AP_THERMAL_PROTECT + bool "Thermal Protect Support" + depends on RT2860V2_AP + +config RT2860V2_AP_COC + bool "CoC Support" + depends on RT2860V2_AP + +config RT2860V2_AP_MEMORY_OPTIMIZATION + bool "Memory Optimization" + depends on RT2860V2_AP + +config RT2860V2_AP_VIDEO_TURBINE + bool "Video Turbine support" + depends on RT2860V2_AP + +config RA_CLASSIFIER + tristate "Ralink Flow Classifier" + depends on RT2860V2_AP_VIDEO_TURBINE + default n + +config RT2860V2_80211N_DRAFT3 + bool "802.11n Draft3" + depends on RT2860V2_AP + +config RT2860V2_AP_INTELLIGENT_RATE_ADAPTION + bool "Intelligent Rate Adaption" + depends on RT2860V2_AP + +config RT2860V2_AP_TXBF + bool "Tx Beam Forming" + depends on RT2860V2_AP + depends on RALINK_RT3883 + +config RT2860V2_AP_RTMP_INTERNAL_TX_ALC + bool "TSSI Compensation" + depends on RT2860V2_AP + depends on RALINK_RT3350 || RALINK_RT3352 || RALINK_RT5350 + +#config RT2860V2_EXT_CHANNEL_LIST +# bool "Extension Channel List" +# depends on RT2860V2_AP + +#config RT2860V2_KTHREAD +# bool "Kernel Thread" +# depends on RT2860V2_AP + +#config RT2860V2_AUTO_CH_SELECT_ENHANCE +# bool "Auto Channel Selection Enhancement" +# depends on RT2860V2_AP + +#config RT2860V2_80211R_FT +# bool "802.11r Fast BSS Transition" +# depends on RT2860V2_AP + +#config RT2860V2_80211R_RR +# bool "802.11k Radio Resource Management" +# depends on RT2860V2_AP + +#config RT2860V2_SINGLE_SKU +# bool "Single SKU" +# depends on RT2860V2_AP + +#config RT2860V2_MCAST_RATE_SPECIFIC +# bool "User specific tx rate of mcast pkt" +# depends on RT2860V2_AP + +#config RT2860V2_SNMP +# bool "Net-SNMP Support" +# depends on RT2860V2_AP diff --git a/mt7620/src/os/linux/Kconfig.ap.usb b/mt7620/src/os/linux/Kconfig.ap.usb new file mode 100755 index 0000000..902fab9 --- /dev/null +++ b/mt7620/src/os/linux/Kconfig.ap.usb @@ -0,0 +1,111 @@ +config RTUSB_AP + tristate "Ralink WiFi USB combo driver AP module" + depends on m + default m + +config RTUSB_AP_WSC + bool "WPS support including WPS2.0" + depends on RTUSB_AP + default y + +config RTUSB_AP_MBSS + bool "MBSS support" + depends on RTUSB_AP + default y + +config RTUSB_AP_NEW_MBSS_MODE + bool "New MBSS support" + depends on RTUSB_AP_MBSS + +config RTUSB_WDS + bool "WDS support" + depends on RTUSB_AP + +config RTUSB_APCLI + bool "APClient support" + depends on RTUSB_AP + +config RTUSB_DFS + bool "DFS support" + depends on RTUSB_AP + +config RTUSB_CS + bool "CS support" + depends on RTUSB_AP + +config RTUSB_IGMP_SNOOP + bool "IGMP snoop support" + depends on RTUSB_AP + +config RTUSB_NETIF_BLOCK + bool "NETIF block support" + depends on RTUSB_AP + +config RTUSB_DLS + bool "DLS support" + depends on RTUSB_AP + +config RTUSB_IDS + bool "IDS support" + depends on RTUSB_AP + +config RTUSB_AP_FLASH_SUPPORT + bool "FLASH support" + depends on RTUSB_AP + +config RTUSB_AP_80211N_DRAFT3 + bool "802.11n Draft3 support" + depends on RTUSB_AP + default y + +# Chip related +config RT2870_AP + bool "RT2870 support" + depends on RTUSB_AP + +config RT3572_AP + bool "RT3572 support" + depends on RTUSB_AP + +config RT3573_AP + bool "RT3573 support" + depends on RTUSB_AP + +config RT5572_AP + bool "RT5572 support" + depends on RTUSB_AP + default y + +# ATE +config RTUSB_AP_ATE + bool "ATE support" + depends on RTUSB_AP + +config RT2870_AP_ATE + bool "RT2870 ATE support" + depends on RTUSB_AP_ATE && RT2870_AP + +config RT3572_AP_ATE + bool "RT3572 ATE support" + depends on RTUSB_AP_ATE && RT3572_AP + +config RT5572_AP_ATE + bool "RT5572 ATE support" + depends on RTUSB_AP_ATE && RT5572_AP + default y + +# QA +config RTUSB_AP_QA + bool "QA tool support" + depends on RTUSB_AP_ATE + default y + +config RTUSB_AP_WAPI + bool "WAPI support" + depends on RTUSB_AP + +# Platform specific +config RT5572_AP_WDS + bool + depends on RTUSB_WDS + default y diff --git a/mt7620/src/os/linux/Kconfig.sta.soc b/mt7620/src/os/linux/Kconfig.sta.soc new file mode 100755 index 0000000..18027ef --- /dev/null +++ b/mt7620/src/os/linux/Kconfig.sta.soc @@ -0,0 +1,89 @@ +config RT2860V2_STA + tristate "Ralink RT2860 802.11n STA support" + depends on NET_RADIO + +config RT2860V2_STA_WPA_SUPPLICANT + bool "WPA Supplicant" + depends on RT2860V2_STA + +config RT2860V2_STA_ETH_CONVERT + bool "Ethernet Convert Support" + depends on RT2860V2_STA + +config RT2860V2_STA_DPB + bool + depends on RT2860V2_STA_ETH_CONVERT + default y + +config RT2860V2_STA_WMM_ACM + bool "WMM ACM Support" + depends on RT2860V2_STA + +config RT2860V2_STA_LED + bool "LED Support" + depends on RT2860V2_STA + +config RT2860V2_STA_IDS + bool "IDS (Intrusion Detection System) Support" + depends on RT2860V2_STA + +config RT2860V2_STA_WSC + bool "WSC (WiFi Simple Config)" + depends on RT2860V2_STA + +config RT2860V2_STA_CARRIER + bool "Carrier Sense Support" + depends on RT2860V2_STA + select RALINK_TIMER + select RALINK_TIMER_DFS + +config RT2860V2_STA_DLS + bool "DLS ((Direct-Link Setup) Support" + depends on RT2860V2_STA + +config RT2860V2_STA_MESH + bool "MESH Support" + depends on RT2860V2_STA + +config RT2860V2_RT3XXX_STA_ANTENNA_DIVERSITY + bool "Antenna Diversity Support" + depends on RT2860V2_STA + +config RT2860V2_HW_STA_ANTENNA_DIVERSITY + bool "Antenna Diversity Support" + depends on RT2860V2_STA + depends on RALINK_RT5350 + +#config RT2860V2_STA_WAPI +# bool "WAPI Support" +# depends on RT2860V2_STA + +config RT2860V2_STA_VIDEO_TURBINE + bool "Video Turbine support" + depends on RT2860V2_STA + +config RT2860V2_STA_INTELLIGENT_RATE_ADAPTION + bool "Intelligent Rate Adaption" + depends on RT2860V2_STA + +config RT2860V2_STA_TXBF + bool "Tx Bean Forming Support (Only 3883)" + depends on RT2860V2_STA + depends on RALINK_RT3883 + +config RT2860V2_STA_RTMP_INTERNAL_TX_ALC + bool "TSSI Compensation" + depends on RT2860V2_STA + depends on RALINK_RT3350 || RALINK_RT3352 || RALINK_RT5350 + +config RT2860V2_STA_80211N_DRAFT3 + bool "802.11n Draft3" + depends on RT2860V2_STA + +#config RT2860V2_EXT_CHANNEL_LIST +# bool "Extension Channel List" +# depends on RT2860V2_STA + +#config RT2860V2_SNMP +# bool "Net-SNMP Support" +# depends on RT2860V2_STA diff --git a/mt7620/src/os/linux/Makefile.2880.ap b/mt7620/src/os/linux/Makefile.2880.ap new file mode 100755 index 0000000..0cfff99 --- /dev/null +++ b/mt7620/src/os/linux/Makefile.2880.ap @@ -0,0 +1,131 @@ +VPATH = ../rt2860v2/os/linux:../rt2860v2/ap:../rt2860v2/common:../rt2860v2/sta + +################### +# AP +################## + +O_TARGET := rt2860v2_ap.o + +RT2860_OBJ = md5.o mlme.o rtmp_wep.o action.o ba_action.o cmm_data.o cmm_data_pci.o \ + rtmp_init.o cmm_mac_pci.o rtmp_tkip.o cmm_sync.o cmm_sanity.o cmm_info.o cmm_cfg.o cmm_wpa.o cmm_asic.o\ + ap.o ap_assoc.o ap_auth.o ap_authrsp.o ap_connect.o ap_mlme.o ap_sanity.o \ + ap_sync.o ap_wpa.o ap_data.o uapsd.o ap_autoChSel.o \ + rt_linux.o rt_profile.o cmm_profile.o rt_main_dev.o pci_main_dev.o ap_ioctl.o rt_2860_rbus.o rt_eeprom.o \ + rt_ate.o + +ifeq ($(CONFIG_RT2860V2_AP_DLS),y) +RT2860_OBJ += ap_dls.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_IDS),y) +RT2860_OBJ += ap_ids.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_DFS),y) +RT2860_OBJ += dfs.o dfs_mcu.o +else +ifeq ($(CONFIG_RT2860V2_AP_CARRIER),y) +RT2860_OBJ += dfs.o dfs_mcu.o +endif +endif + +ifeq ($(CONFIG_RT2860V2_AP_LED),y) +RT2860_OBJ += rt_led.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_WSC),y) +RT2860_OBJ += wsc.o wsc_tlv.o sha2.o hmac.o dh_key.o evp_enc.o +endif + + +ifeq ($(CONFIG_RT2860V2_AP_WDS),y) +RT2860_OBJ += ap_wds.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_MBSS),y) +RT2860_OBJ += ap_mbss.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_APCLI),y) +RT2860_OBJ += ap_apcli.o apcli_assoc.o apcli_auth.o apcli_ctrl.o apcli_mlme.o apcli_sync.o +RT2860_OBJ += cmm_mat.o cmm_mat_iparp.o cmm_mat_pppoe.o cmm_mat_ipv6.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_IGMP_SNOOP),y) +RT2860_OBJ += igmp_snoop.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_NETIF_BLOCK),y) +RT2860_OBJ += netif_block.o +endif + +################### +# CFLAGS +################## +EXTRA_CFLAGS = -I../rt2860v2/include -DAGGREGATION_SUPPORT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT -DLINUX \ + -Wall -Wstrict-prototypes -Wno-trigraphs + +EXTRA_CFLAGS += -DCONFIG_AP_SUPPORT -DUAPSD_SUPPORT -DDBG -DRT2860 # -DDFS_DEBUG -DIAPP_SUPPORT +EXTRA_CFLAGS += -DRALINK_ATE -DRALINK_QA -DCONFIG_RT2880_ATE_CMD_NEW + +ifeq ($(CONFIG_RT2860V2_AP_DLS),y) +EXTRA_CFLAGS += -DQOS_DLS_SUPPORT +endif + + +ifeq ($(CONFIG_RT2860V2_AP_IDS),y) +EXTRA_CFLAGS += -DIDS_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_DFS),y) +EXTRA_CFLAGS += -DDFS_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_CARRIER),y) +EXTRA_CFLAGS += -DCARRIER_DETECTION_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_LED),y) +EXTRA_CFLAGS += -DAP_LED +endif + + +ifeq ($(CONFIG_RT2860V2_AP_WSC),y) +EXTRA_CFLAGS += -DWSC_AP_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_LLTD),y) +EXTRA_CFLAGS += -DLLTD_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_WDS),y) +EXTRA_CFLAGS += -DWDS_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_MBSS),y) +EXTRA_CFLAGS += -DMBSS_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_APCLI),y) +EXTRA_CFLAGS += -DAPCLI_SUPPORT +EXTRA_CFLAGS += -DMAT_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_IGMP_SNOOP),y) +EXTRA_CFLAGS += -DIGMP_SNOOP_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_NETIF_BLOCK),y) +EXTRA_CFLAGS += -DBLOCK_NET_IF +endif + +ifeq ($(CONFIG_RT2880_AP_BRIDGING_ONLY),y) +EXTRA_CFLAGS += -DCONFIG_RT2880_BRIDGING_ONLY +endif + + +obj-y := $(RT2860_OBJ) +obj-m := $(O_TARGET) + +include $(TOPDIR)/Rules.make + diff --git a/mt7620/src/os/linux/Makefile.2880.sta b/mt7620/src/os/linux/Makefile.2880.sta new file mode 100755 index 0000000..ade46be --- /dev/null +++ b/mt7620/src/os/linux/Makefile.2880.sta @@ -0,0 +1,52 @@ +VPATH = ../rt2860v2/os/linux:../rt2860v2/ap:../rt2860v2/common:../rt2860v2/sta + +################### +# STA +################## +O_TARGET := rt2860v2_sta.o + + +RT2860_OBJ = md5.o mlme.o rtmp_wep.o action.o ba_action.o cmm_data.o cmm_data_pci.o \ + rtmp_init.o cmm_mac_pci.o rtmp_tkip.o cmm_sync.o cmm_sanity.o cmm_info.o cmm_cfg.o cmm_asic.o\ + cmm_wpa.o assoc.o aironet.o auth.o auth_rsp.o sync.o sanity.o \ + rtmp_data.o connect.o wpa.o rt_linux.o rt_profile.o cmm_profile.o \ + rt_main_dev.o rt_ate.o sta_ioctl.o pci_main_dev.o rt_2860_rbus.o rt_eeprom.o \ + #netif_block.o + +################### +# CFLAGS +################## +EXTRA_CFLAGS = -I../rt2860v2/include -DAGGREGATION_SUPPORT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT -DLINUX \ + -Wall -Wstrict-prototypes -Wno-trigraphs + +EXTRA_CFLAGS += -DCONFIG_STA_SUPPORT -DDBG -DRALINK_ATE -DRALINK_QA -DRT2860 #-DBLOCK_NET_IF + +ifeq ($(CONFIG_RT2860V2_STA_CARRIER),y) +RT2860_OBJ += dfs.o dfs_mcu.o +EXTRA_CFLAGS += -DCARRIER_DETECTION_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_STA_WPA_SUPPLICANT),y) +EXTRA_CFLAGS += -DWPA_SUPPLICANT_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_STA_LED),y) +RT2860_OBJ += rt_led.o +EXTRA_CFLAGS += -DSTA_LED +endif + +ifeq ($(CONFIG_RT2860V2_STA_WIFI_TEST),y) +EXTRA_CFLAGS += -DWIFI_TEST +endif + +ifeq ($(CONFIG_RT2860V2_STA_WSC),y) +RT2860_OBJ += wsc.o wsc_tlv.o sha2.o hmac.o dh_key.o evp_enc.o +EXTRA_CFLAGS += -DWSC_INCLUDED -DWSC_STA_SUPPORT +endif + + +obj-y := $(RT2860_OBJ) +obj-m := $(O_TARGET) + +include $(TOPDIR)/Rules.make + diff --git a/mt7620/src/os/linux/Makefile.4 b/mt7620/src/os/linux/Makefile.4 new file mode 100644 index 0000000..01362fc --- /dev/null +++ b/mt7620/src/os/linux/Makefile.4 @@ -0,0 +1,1029 @@ +include $(RT28xx_DIR)/os/linux/config.mk + +#ifdef CONFIG_AP_SUPPORT +ifeq ($(RT28xx_MODE),AP) +MOD_NAME = rt$(MODULE)ap +DAT_PATH = /etc/Wireless/RT$(MODULE_DAT)AP +DAT_FILE_NAME = RT$(MODULE_DAT)AP.dat +endif +#endif // CONFIG_AP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT +ifeq ($(RT28xx_MODE), STA) +MOD_NAME = rt$(MODULE)sta +DAT_PATH = /etc/Wireless/RT$(MODULE_DAT)STA +DAT_FILE_NAME = RT$(MODULE_DAT)STA.dat +endif +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_APSTA_SUPPORT +ifeq ($(RT28xx_MODE), APSTA) +MOD_NAME = rt$(MODULE)apsta +endif +#endif // CONFIG_APSTA_SUPPORT // + +#ifdef WAPI_SUPPORT +ifeq ($(HAS_WAPI_SUPPORT),y) +OBJ := -DEXPORT_SYMTAB +endif +#endif // WAPI_SUPPORT // + +OBJ := $(MOD_NAME).o + +#ifdef CONFIG_AP_SUPPORT +RT28XX_AP_OBJ := \ + $(RT28xx_DIR)/common/crypt_md5.o\ + $(RT28xx_DIR)/common/crypt_sha2.o\ + $(RT28xx_DIR)/common/crypt_hmac.o\ + $(RT28xx_DIR)/common/crypt_aes.o\ + $(RT28xx_DIR)/common/crypt_arc4.o\ + $(RT28xx_DIR)/common/mlme.o\ + $(RT28xx_DIR)/common/cmm_wep.o\ + $(RT28xx_DIR)/common/action.o\ + $(RT28xx_DIR)/common/cmm_data.o\ + $(RT28xx_DIR)/common/rtmp_init.o\ + $(RT28xx_DIR)/common/rtmp_init_inf.o\ + $(RT28xx_DIR)/common/cmm_tkip.o\ + $(RT28xx_DIR)/common/cmm_aes.o\ + $(RT28xx_DIR)/common/cmm_sync.o\ + $(RT28xx_DIR)/common/eeprom.o\ + $(RT28xx_DIR)/common/cmm_sanity.o\ + $(RT28xx_DIR)/common/cmm_info.o\ + $(RT28xx_DIR)/common/cmm_cfg.o\ + $(RT28xx_DIR)/common/cmm_wpa.o\ + $(RT28xx_DIR)/common/dfs.o\ + $(RT28xx_DIR)/common/spectrum.o\ + $(RT28xx_DIR)/common/rtmp_timer.o\ + $(RT28xx_DIR)/common/rt_channel.o\ + $(RT28xx_DIR)/common/cmm_profile.o\ + $(RT28xx_DIR)/common/cmm_asic.o\ + $(RT28xx_DIR)/common/cmm_cmd.o\ + $(RT28xx_DIR)/rate_ctrl/ra_ctrl.o\ + $(RT28xx_DIR)/rate_ctrl/alg_legacy.o\ + $(RT28xx_DIR)/os/linux/rt_profile.o\ + $(RT28xx_DIR)/ap/ap_mbss.o\ + $(RT28xx_DIR)/chips/rtmp_chip.o\ + $(RT28xx_DIR)/ap/ap.o\ + $(RT28xx_DIR)/ap/ap_assoc.o\ + $(RT28xx_DIR)/ap/ap_auth.o\ + $(RT28xx_DIR)/ap/ap_connect.o\ + $(RT28xx_DIR)/ap/ap_mlme.o\ + $(RT28xx_DIR)/ap/ap_sanity.o\ + $(RT28xx_DIR)/ap/ap_sync.o\ + $(RT28xx_DIR)/ap/ap_wpa.o\ + $(RT28xx_DIR)/ap/ap_data.o\ + $(RT28xx_DIR)/common/uapsd.o\ + $(RT28xx_DIR)/ap/ap_autoChSel.o\ + $(RT28xx_DIR)/ap/ap_qload.o\ + $(RT28xx_DIR)/ap/ap_cfg.o + +ifeq ($(OSABL),NO) +RT28XX_AP_OBJ := \ + $(RT28xx_DIR)/ap/ap_mbss_inf.o\ + $(RT28xx_DIR)/common/rt_os_util.o\ + $(RT28xx_DIR)/os/linux/ap_ioctl.o\ + $(RT28xx_DIR)/os/linux/rt_linux.o\ + $(RT28xx_DIR)/os/linux/rt_main_dev.o +else +RT28XX_AP_OBJ := \ + $(RT28xx_DIR)/os/linux/rt_symb.o +endif + +ifeq ($(HAS_NEW_RATE_ADAPT_SUPPORT),y) +RT28XX_AP_OBJS += $(RT28xx_DIR)/rate_ctrl/alg_grp.o +endif + +#ifdef DOT11_N_SUPPORT +ifeq ($(HAS_DOT11_N_SUPPORT),y) +RT28XX_AP_OBJ += \ + $(RT28xx_DIR)/common/ba_action.o + +#ifdef TXBF_SUPPORT +ifeq ($(HAS_TXBF_SUPPORT),y) +rt$(MODULE)ap-objs += \ + $(RT28xx_DIR)/common/cmm_txbf.o\ + $(RT28xx_DIR)/common/cmm_txbf_cal.o +endif +#endif // TXBF_SUPPORT // +endif +#endif // DOT11_N_SUPPORT // + +#ifdef BG_FT_SUPPORT +ifeq ($(OSABL),NO) +ifeq ($(HAS_BGFP_SUPPORT),y) +RT28XX_AP_OBJ += \ + $(RT28xx_DIR)/os/linux/br_ftph.o +endif +endif +#endif // BG_FT_SUPPORT // + +#ifdef LED_CONTROL_SUPPORT +ifeq ($(HAS_LED_CONTROL_SUPPORT),y) +RT28XX_AP_OBJ += \ + $(RT28xx_DIR)/common/rt_led.o +endif +#endif // LED_CONTROL_SUPPORT // + +#ifdef RT2860 +ifneq ($(findstring 2860,$(CHIPSET)),) +RT28XX_AP_OBJ += \ + $(RT28xx_DIR)/common/cmm_mac_pci.o\ + $(RT28xx_DIR)/common/cmm_data_pci.o\ + $(RT28xx_DIR)/os/linux/rt_rbus_pci_drv.o\ + $(RT28xx_DIR)/common/rtmp_mcu.o\ + $(RT28xx_DIR)/common/ee_prom.o\ + $(RT28xx_DIR)/chips/rt28xx.o + +ifeq ($(HAS_ATE),y) +RT28XX_AP_OBJ += \ + $(RT28xx_DIR)/ate/chips/rt28xx_ate.o\ + $(RT28xx_DIR)/ate/common/ate_pci.o +endif + +ifeq ($(OSABL),NO) +RT28XX_AP_OBJ += \ + $(RT28xx_DIR)/os/linux/rt_pci_rbus.o\ + $(RT28xx_DIR)/os/linux/rt_rbus_pci_util.o\ + $(RT28xx_DIR)/os/linux/pci_main_dev.o +endif +endif +#endif // RT2860 // + + + + +#ifdef RT2880 +ifneq ($(findstring 2880,$(CHIPSET)),) +RT28XX_AP_OBJ += \ + $(RT28xx_DIR)/common/cmm_mac_pci.o\ + $(RT28xx_DIR)/common/cmm_data_pci.o\ + $(RT28xx_DIR)/os/linux/rt_rbus_pci_drv.o\ + $(RT28xx_DIR)/common/ee_flash.o\ + $(RT28xx_DIR)/common/rtmp_swmcu.o\ + $(RT28xx_DIR)/chips/rt2880.o + +ifeq ($(HAS_DFS_SUPPORT),y) +RT28XX_AP_OBJ += \ + $(RT28xx_DIR)/common/dfs_mcu.o +endif + +ifeq ($(HAS_ATE),y) +RT28XX_AP_OBJ += \ + $(RT28xx_DIR)/ate/chips/rt28xx_ate.o\ + $(RT28xx_DIR)/ate/common/ate_pci.o +endif + +ifeq ($(OSABL),NO) +RT28XX_AP_OBJ += \ + $(RT28xx_DIR)/os/linux/rt_pci_rbus.o\ + $(RT28xx_DIR)/os/linux/rt_rbus_pci_util.o\ + $(RT28xx_DIR)/os/linux/pci_main_dev.o +endif +endif +#endif // RT2880 // + + + + + + + +#ifdef RTMP_MAC_PCI +#endif // RTMP_MAC_PCI // + + +ifeq ($(HAS_RT2880_RT2860_COEXIST),y) +RT28XX_AP_OBJ += \ + $(RT28xx_DIR)/os/linux/rt_pci_rbus.o\ + $(RT28xx_DIR)/os/linux/rt_rbus_pci_util.o\ + $(RT28xx_DIR)/os/linux/pci_main_dev.o\ + $(RT28xx_DIR)/common/dfs.o +endif + +ifeq ($(HAS_ATE),y) +RT28XX_AP_OBJ += $(RT28xx_DIR)/ate/common/rt_ate.o +endif + +ifeq ($(HAS_QA_SUPPORT),y) +RT28XX_AP_OBJ += $(RT28xx_DIR)/ate/common/rt_qa.o +endif + +#ifdef WSC_INCLUDED +ifeq ($(HAS_WSC),y) +RT28XX_AP_OBJ += \ + $(RT28xx_DIR)/common/wsc.o\ + $(RT28xx_DIR)/common/wsc_tlv.o\ + $(RT28xx_DIR)/common/wsc_ufd.o\ + $(RT28xx_DIR)/common/crypt_biginteger.o\ + $(RT28xx_DIR)/common/crypt_dh.o +endif +ifeq ($(HAS_WSC_V2),y) +RT28XX_AP_OBJ += $(RT28xx_DIR)/common/wsc_v2.o +endif +#endif // WSC_INCLUDED // + +#ifdef EASY_CONFIG_SETUP +ifeq ($(HAS_EASY_CONFIG_SETUP_SUPPORT),y) +ifneq ($(PLATFORM),RALINK_3052) +RT28XX_AP_OBJ += $(RT28xx_DIR)/common/auto_provision.o +endif +endif +#endif // EASY_CONFIG_SETUP // + +#ifdef NINTENDO_AP +ifeq ($(HAS_NINTENDO),y) +RT28XX_AP_OBJ += $(RT28xx_DIR)/ap/ap_nintendo.o +endif +#endif // NINTENDO_AP // + +ifeq ($(HAS_WDS),y) +RT28XX_AP_OBJ += $(RT28xx_DIR)/ap/ap_wds.o + +ifeq ($(OSABL),NO) +RT28XX_AP_OBJ += \ + ../../ap/ap_wds_inf.o +endif +endif + +#ifdef APCLI_SUPPORT +ifeq ($(HAS_APCLI),y) +RT28XX_AP_OBJ += \ + $(RT28xx_DIR)/ap/ap_apcli.o \ + $(RT28xx_DIR)/ap/apcli_ctrl.o \ + $(RT28xx_DIR)/ap/apcli_sync.o \ + $(RT28xx_DIR)/ap/apcli_auth.o \ + $(RT28xx_DIR)/ap/apcli_assoc.o \ + $(RT28xx_DIR)/common/cmm_mat.o \ + $(RT28xx_DIR)/common/cmm_mat_iparp.o \ + $(RT28xx_DIR)/common/cmm_mat_pppoe.o \ + $(RT28xx_DIR)/common/cmm_mat_ipv6.o + +ifeq ($(OSABL),NO) +RT28XX_AP_OBJ += \ + ../../ap/ap_apcli_inf.o +endif +endif +#endif // APCLI_SUPPORT // + +ifeq ($(HAS_BLOCK_NET_IF),y) +RT28XX_AP_OBJ += $(RT28xx_DIR)/common/netif_block.o +endif + +ifeq ($(HAS_IGMP_SNOOP_SUPPORT),y) +RT28XX_AP_OBJ += $(RT28xx_DIR)/common/igmp_snoop.o +endif + + +ifeq ($(HAS_QOS_DLS_SUPPORT),y) +RT28XX_AP_OBJ += $(RT28xx_DIR)/ap/ap_dls.o +endif + +ifeq ($(HAS_IDS_SUPPORT),y) +RT28XX_AP_OBJ += $(RT28xx_DIR)/ap/ap_ids.o +endif + +ifeq ($(PLATFORM),IKANOS_V160) +RT28XX_AP_OBJ += $(RT28xx_DIR)/os/linux/vr_ikans.o +endif + +ifeq ($(PLATFORM),IKANOS_V180) +RT28XX_AP_OBJ += $(RT28xx_DIR)/os/linux/vr_ikans.o +endif + +#ifdef MESH_SUPPORT +ifeq ($(HAS_MESH_SUPPORT),y) +RT28XX_AP_OBJ += \ + $(RT28xx_DIR)/common/mesh_bmpkt.o \ + $(RT28xx_DIR)/common/mesh_ctrl.o \ + $(RT28xx_DIR)/common/mesh_link_mng.o \ + $(RT28xx_DIR)/common/mesh_sanity.o \ + $(RT28xx_DIR)/common/mesh_tlv.o \ + $(RT28xx_DIR)/common/mesh.o \ + $(RT28xx_DIR)/common/mesh_forwarding.o \ + $(RT28xx_DIR)/common/mesh_path_mng.o + +ifeq ($(OSABL),NO) +RT28XX_AP_OBJ += \ + ../../common/mesh_inf.o +endif +endif +#endif // MESH_SUPPORT // + +#ifdef WAPI_SUPPORT +ifeq ($(HAS_WAPI_SUPPORT),y) +RT28XX_AP_OBJ += \ + $(RT28xx_DIR)/common/wapi.o +endif +#endif // WAPI_SUPPORT // + + + + +ifeq ($(HAS_CLIENT_WDS_SUPPORT),y) +RT28XX_AP_OBJ += \ + $(RT28xx_DIR)/common/client_wds.o +endif +#endif // CONFIG_AP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT +RT28XX_STA_OBJ := \ + $(RT28xx_DIR)/common/crypt_md5.o\ + $(RT28xx_DIR)/common/crypt_sha2.o\ + $(RT28xx_DIR)/common/crypt_hmac.o\ + $(RT28xx_DIR)/common/crypt_aes.o\ + $(RT28xx_DIR)/common/crypt_arc4.o\ + $(RT28xx_DIR)/common/mlme.o\ + $(RT28xx_DIR)/common/cmm_wep.o\ + $(RT28xx_DIR)/common/action.o\ + $(RT28xx_DIR)/common/cmm_data.o\ + $(RT28xx_DIR)/common/rtmp_init.o\ + $(RT28xx_DIR)/common/rtmp_init_inf.o\ + $(RT28xx_DIR)/common/cmm_tkip.o\ + $(RT28xx_DIR)/common/cmm_aes.o\ + $(RT28xx_DIR)/common/cmm_sync.o\ + $(RT28xx_DIR)/common/eeprom.o\ + $(RT28xx_DIR)/common/cmm_sanity.o\ + $(RT28xx_DIR)/common/cmm_info.o\ + $(RT28xx_DIR)/common/cmm_cfg.o\ + $(RT28xx_DIR)/common/cmm_wpa.o\ + $(RT28xx_DIR)/common/dfs.o\ + $(RT28xx_DIR)/common/spectrum.o\ + $(RT28xx_DIR)/common/rtmp_timer.o\ + $(RT28xx_DIR)/common/rt_channel.o\ + $(RT28xx_DIR)/common/cmm_profile.o\ + $(RT28xx_DIR)/common/cmm_asic.o\ + $(RT28xx_DIR)/common/cmm_cmd.o\ + $(RT28xx_DIR)/rate_ctrl/ra_ctrl.o\ + $(RT28xx_DIR)/rate_ctrl/alg_legacy.o\ + $(RT28xx_DIR)/rate_ctrl/alg_ags.o\ + $(RT28xx_DIR)/os/linux/rt_profile.o\ + $(RT28xx_DIR)/chips/rtmp_chip.o\ + $(RT28xx_DIR)/sta/assoc.o\ + $(RT28xx_DIR)/sta/auth.o\ + $(RT28xx_DIR)/sta/auth_rsp.o\ + $(RT28xx_DIR)/sta/sync.o\ + $(RT28xx_DIR)/sta/sanity.o\ + $(RT28xx_DIR)/sta/rtmp_data.o\ + $(RT28xx_DIR)/sta/connect.o\ + $(RT28xx_DIR)/sta/wpa.o\ + $(RT28xx_DIR)/sta/sta_cfg.o + +ifeq ($(OSABL),NO) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/common/rt_os_util.o\ + $(RT28xx_DIR)/os/linux/sta_ioctl.o\ + $(RT28xx_DIR)/os/linux/rt_linux.o\ + $(RT28xx_DIR)/os/linux/rt_main_dev.o +else +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/os/linux/rt_symb.o +endif + +ifeq ($(HAS_NEW_RATE_ADAPT_SUPPORT),y) +RT28XX_STA_OBJS += $(RT28xx_DIR)/rate_ctrl/alg_grp.o +endif + +ifeq ($(HAS_ATE),y) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/ate/common/rt_ate.o +endif + +ifeq ($(HAS_QA_SUPPORT),y) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/ate/common/rt_qa.o +endif + +#ifdef DOT11_N_SUPPORT +ifeq ($(HAS_DOT11_N_SUPPORT),y) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/common/ba_action.o + +#ifdef TXBF_SUPPORT +ifeq ($(HAS_TXBF_SUPPORT),y) +rt$(MODULE)sta-objs += \ + $(RT28xx_DIR)/common/cmm_txbf.o\ + $(RT28xx_DIR)/common/cmm_txbf_cal.o +endif +#endif // TXBF_SUPPORT // +endif +#endif // DOT11_N_SUPPORT // + +#ifdef ETH_CONVERT +ifeq ($(HAS_ETH_CONVERT_SUPPORT), y) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/common/cmm_mat.o \ + $(RT28xx_DIR)/common/cmm_mat_iparp.o \ + $(RT28xx_DIR)/common/cmm_mat_pppoe.o \ + $(RT28xx_DIR)/common/cmm_mat_ipv6.o +endif +#endif // ETH_CONVERT // + +#ifdef ADHOC_WPA2PSK_SUPPORT +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/common/cmm_wpa_adhoc.o +#endif // ADHOC_WPA2PSK_SUPPORT // + +#ifdef WSC_INCLUDED +ifeq ($(HAS_WSC),y) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/common/wsc.o\ + $(RT28xx_DIR)/common/wsc_tlv.o\ + $(RT28xx_DIR)/common/crypt_biginteger.o\ + $(RT28xx_DIR)/common/crypt_dh.o +endif +ifeq ($(HAS_WSC_V2),y) +RT28XX_STA_OBJ += $(RT28xx_DIR)/common/wsc_v2.o +endif +#endif // WSC_INCLUDED // + + +ifeq ($(HAS_BLOCK_NET_IF),y) +RT28XX_STA_OBJ += $(RT28xx_DIR)/common/netif_block.o +endif + +ifeq ($(HAS_QOS_DLS_SUPPORT),y) +RT28XX_STA_OBJ += $(RT28xx_DIR)/sta/dls.o +endif + +#ifdef DOT11Z_TDLS_SUPPORT +ifeq ($(HAS_DOT11Z_TDLS_SUPPORT),y) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/sta/tdls.o\ + $(RT28xx_DIR)/sta/tdls_ctrl.o\ + $(RT28xx_DIR)/sta/tdls_tlv.o\ + $(RT28xx_DIR)/sta/tdls_link_mng.o +endif +#endif // DOT11Z_TDLS_SUPPORT // + +#ifdef LED_CONTROL_SUPPORT +ifeq ($(HAS_LED_CONTROL_SUPPORT),y) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/common/rt_led.o +endif +#endif // LED_CONTROL_SUPPORT // + +#ifdef RT2860 +ifneq ($(findstring 2860,$(CHIPSET)),) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/common/cmm_mac_pci.o\ + $(RT28xx_DIR)/common/cmm_data_pci.o\ + $(RT28xx_DIR)/common/ee_prom.o\ + $(RT28xx_DIR)/common/rtmp_mcu.o + +ifeq ($(HAS_ATE),y) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/ate/chips/rt28xx_ate.o\ + $(RT28xx_DIR)/ate/common/ate_pci.o +endif + +ifeq ($(OSABL),NO) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/os/linux/rt_pci_rbus.o\ + $(RT28xx_DIR)/os/linux/rt_rbus_pci_util.o\ + $(RT28xx_DIR)/os/linux/pci_main_dev.o +endif +endif +#endif // RT2860 // + + + + +#ifdef RT2880 +ifneq ($(findstring 2880,$(CHIPSET)),) +rt$(MODULE)sta-objs += \ + $(RT28xx_DIR)/os/linux/rbus_main_dev.o\ + $(RT28xx_DIR)/os/linux/rt_pci_rbus.o\ + $(RT28xx_DIR)/os/linux/rt_rbus_pci_util.o\ + $(RT28xx_DIR)/common/cmm_mac_pci.o\ + $(RT28xx_DIR)/common/cmm_data_pci.o\ + $(RT28xx_DIR)/os/linux/rt_rbus_pci_drv.o\ + $(RT28xx_DIR)/common/ee_flash.o\ + $(RT28xx_DIR)/common/rtmp_swmcu.o\ + $(RT28xx_DIR)/chips/rt2880.o +endif +ifeq ($(HAS_ATE),y) +rt$(MODULE)sta-objs += \ + $(RT28xx_DIR)/ate/common/rt_ate.o\ + $(RT28xx_DIR)/ate/common/ate_pci.o\ + $(RT28xx_DIR)/ate/chips/rt28xx_ate.o +endif +ifeq ($(HAS_QA_SUPPORT),y) +rt$(MODULE)sta-objs += \ + $(RT28xx_DIR)/ate/common/rt_qa.o +endif +#endif // RT2880 // + + +ifneq ($(findstring 3593,$(CHIPSET)),) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/common/cmm_mac_pci.o\ + $(RT28xx_DIR)/common/cmm_data_pci.o\ + $(RT28xx_DIR)/os/linux/rt_rbus_pci_drv.o\ + $(RT28xx_DIR)/common/rtmp_mcu.o\ + $(RT28xx_DIR)/common/ee_prom.o\ + $(RT28xx_DIR)/common/ee_efuse.o\ + $(RT28xx_DIR)/common/rt_rf.o\ + $(RT28xx_DIR)/common/frq_cal.o\ + $(RT28xx_DIR)/chips/rt30xx.o\ + $(RT28xx_DIR)/chips/rt35xx.o\ + $(RT28xx_DIR)/chips/rt28xx.o\ + $(RT28xx_DIR)/chips/rt3593.o + +ifeq ($(HAS_ATE),y) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/ate/chips/rt3593_ate.o\ + $(RT28xx_DIR)/ate/common/ate_pci.o +endif + +ifeq ($(OSABL),NO) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/os/linux/rt_pci_rbus.o\ + $(RT28xx_DIR)/os/linux/rt_rbus_pci_util.o\ + $(RT28xx_DIR)/os/linux/pci_main_dev.o +endif +endif + +ifneq ($(findstring 3390,$(CHIPSET)),) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/common/cmm_mac_pci.o\ + $(RT28xx_DIR)/common/cmm_data_pci.o\ + $(RT28xx_DIR)/os/linux/rt_rbus_pci_drv.o\ + $(RT28xx_DIR)/common/ee_prom.o\ + $(RT28xx_DIR)/common/ee_efuse.o\ + $(RT28xx_DIR)/common/rtmp_mcu.o\ + $(RT28xx_DIR)/common/rt_rf.o\ + $(RT28xx_DIR)/chips/rt30xx.o\ + $(RT28xx_DIR)/chips/rt3090.o\ + $(RT28xx_DIR)/chips/rt33xx.o\ + $(RT28xx_DIR)/chips/rt3390.o + +ifeq ($(HAS_ATE),y) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/ate/chips/rt33xx_ate.o\ + $(RT28xx_DIR)/ate/chips/rt30xx_ate.o\ + $(RT28xx_DIR)/ate/common/ate_pci.o +endif + +ifeq ($(OSABL),NO) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/os/linux/rt_pci_rbus.o\ + $(RT28xx_DIR)/os/linux/rt_rbus_pci_util.o\ + $(RT28xx_DIR)/os/linux/pci_main_dev.o +endif +endif + + + + + +#ifdef RTMP_MAC_PCI +#endif // RTMP_MAC_PCI // + + +#ifdef MESH_SUPPORT +ifeq ($(HAS_MESH_SUPPORT),y) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/common/mesh_bmpkt.o \ + $(RT28xx_DIR)/common/mesh_ctrl.o \ + $(RT28xx_DIR)/common/mesh_link_mng.o \ + $(RT28xx_DIR)/common/mesh_sanity.o \ + $(RT28xx_DIR)/common/mesh_tlv.o \ + $(RT28xx_DIR)/common/mesh.o \ + $(RT28xx_DIR)/common/mesh_forwarding.o \ + $(RT28xx_DIR)/common/mesh_path_mng.o + +ifeq ($(OSABL),NO) +RT28XX_STA_OBJ += \ + ../../common/mesh_inf.o +endif +endif +#endif // MESH_SUPPORT // + +#ifdef WAPI_SUPPORT +ifeq ($(HAS_WAPI_SUPPORT),y) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/common/wapi.o +endif +#endif // WAPI_SUPPORT // + + + +#ifdef P2P_SUPPORT +ifeq ($(OSABL),NO) +ifeq ($(HAS_P2P_SUPPORT),y) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/common/p2p_inf.o +endif +endif + +ifeq ($(HAS_P2P_SUPPORT),y) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/ap/ap_mbss.o\ + $(RT28xx_DIR)/ap/ap.o\ + $(RT28xx_DIR)/ap/ap_assoc.o\ + $(RT28xx_DIR)/ap/ap_auth.o\ + $(RT28xx_DIR)/ap/ap_connect.o\ + $(RT28xx_DIR)/ap/ap_mlme.o\ + $(RT28xx_DIR)/ap/ap_sanity.o\ + $(RT28xx_DIR)/ap/ap_sync.o\ + $(RT28xx_DIR)/ap/ap_wpa.o\ + $(RT28xx_DIR)/ap/ap_data.o\ + $(RT28xx_DIR)/common/uapsd.o\ + $(RT28xx_DIR)/ap/ap_autoChSel.o\ + $(RT28xx_DIR)/ap/ap_qload.o\ + $(RT28xx_DIR)/sta/p2pcli.o \ + $(RT28xx_DIR)/sta/p2pcli_ctrl.o \ + $(RT28xx_DIR)/sta/p2pcli_sync.o \ + $(RT28xx_DIR)/sta/p2pcli_auth.o \ + $(RT28xx_DIR)/sta/p2pcli_assoc.o \ + $(RT28xx_DIR)/common/cmm_mat.o \ + $(RT28xx_DIR)/common/cmm_mat_iparp.o \ + $(RT28xx_DIR)/common/cmm_mat_pppoe.o \ + $(RT28xx_DIR)/common/cmm_mat_ipv6.o \ + $(RT28xx_DIR)/common/p2p_dbg.o\ + $(RT28xx_DIR)/common/p2p.o\ + $(RT28xx_DIR)/common/p2p_packet.o\ + $(RT28xx_DIR)/common/p2p_action.o\ + $(RT28xx_DIR)/common/p2p_table.o\ + $(RT28xx_DIR)/common/p2p_ctrl.o\ + $(RT28xx_DIR)/common/p2p_disc_mng.o\ + $(RT28xx_DIR)/common/p2p_nego_mng.o\ + $(RT28xx_DIR)/common/p2p_dbg.o\ + $(RT28xx_DIR)/common/p2p.o\ + $(RT28xx_DIR)/common/p2p_packet.o\ + $(RT28xx_DIR)/common/p2p_action.o\ + $(RT28xx_DIR)/common/p2p_table.o\ + $(RT28xx_DIR)/common/p2p_ctrl.o\ + $(RT28xx_DIR)/common/p2p_disc_mng.o\ + $(RT28xx_DIR)/common/p2p_nego_mng.o\ + $(RT28xx_DIR)/common/p2p_cfg.o\ + $(RT28xx_DIR)/common/wsc.o\ + $(RT28xx_DIR)/common/wsc_tlv.o\ + $(RT28xx_DIR)/common/wsc_ufd.o\ + $(RT28xx_DIR)/common/crypt_biginteger.o\ + $(RT28xx_DIR)/common/crypt_dh.o + +ifeq ($(HAS_QOS_DLS_SUPPORT),y) +RT28XX_STA_OBJ += $(RT28xx_DIR)/ap/ap_dls.o +endif + +endif + +ifeq ($(HAS_P2P_SUPPORT),y) +ifeq ($(OSABL),NO) +RT28XX_STA_OBJ += \ + $(RT28xx_DIR)/ap/ap_mbss_inf.o\ + $(RT28xx_DIR)/common/rt_os_util.o\ + $(RT28xx_DIR)/os/linux/ap_ioctl.o\ + $(RT28xx_DIR)/os/linux/sta_ioctl.o\ + $(RT28xx_DIR)/os/linux/rt_linux.o\ + $(RT28xx_DIR)/os/linux/rt_main_dev.o +else +rt$(MODULE)sta-objs += \ + ../../os/linux/rt_symb.o +endif +endif +#endif // P2P_SUPPORT // + +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_APSTA_SUPPORT +RT28XX_APSTA_OBJ := \ + $(RT28xx_DIR)/common/crypt_md5.o\ + $(RT28xx_DIR)/common/crypt_sha2.o\ + $(RT28xx_DIR)/common/crypt_hmac.o\ + $(RT28xx_DIR)/common/crypt_aes.o\ + $(RT28xx_DIR)/common/crypt_arc4.o\ + $(RT28xx_DIR)/common/mlme.o\ + $(RT28xx_DIR)/common/cmm_wep.o\ + $(RT28xx_DIR)/common/action.o\ + $(RT28xx_DIR)/common/cmm_data.o\ + $(RT28xx_DIR)/common/rtmp_init.o\ + $(RT28xx_DIR)/common/cmm_tkip.o\ + $(RT28xx_DIR)/common/cmm_aes.o\ + $(RT28xx_DIR)/common/cmm_sync.o\ + $(RT28xx_DIR)/common/eeprom.o\ + $(RT28xx_DIR)/common/cmm_sanity.o\ + $(RT28xx_DIR)/common/cmm_info.o\ + $(RT28xx_DIR)/common/cmm_cfg.o\ + $(RT28xx_DIR)/common/cmm_wpa.o\ + $(RT28xx_DIR)/common/cmm_wpa_adhoc.o\ + $(RT28xx_DIR)/common/dfs.o\ + $(RT28xx_DIR)/common/spectrum.o\ + $(RT28xx_DIR)/common/rtmp_timer.o\ + $(RT28xx_DIR)/common/rt_channel.o\ + $(RT28xx_DIR)/common/cmm_profile.o\ + $(RT28xx_DIR)/common/cmm_asic.o\ + $(RT28xx_DIR)/common/cmm_cmd.o\ + $(RT28xx_DIR)/rate_ctrl/ra_ctrl.o\ + $(RT28xx_DIR)/rate_ctrl/alg_legacy.o\ + $(RT28xx_DIR)/ap/ap.o\ + $(RT28xx_DIR)/ap/ap_assoc.o\ + $(RT28xx_DIR)/ap/ap_auth.o\ + $(RT28xx_DIR)/ap/ap_connect.o\ + $(RT28xx_DIR)/ap/ap_mlme.o\ + $(RT28xx_DIR)/ap/ap_sanity.o\ + $(RT28xx_DIR)/ap/ap_sync.o\ + $(RT28xx_DIR)/ap/ap_wpa.o\ + $(RT28xx_DIR)/ap/ap_data.o\ + $(RT28xx_DIR)/common/uapsd.o\ + $(RT28xx_DIR)/sta/assoc.o\ + $(RT28xx_DIR)/sta/auth.o\ + $(RT28xx_DIR)/sta/auth_rsp.o\ + $(RT28xx_DIR)/sta/sync.o\ + $(RT28xx_DIR)/sta/sanity.o\ + $(RT28xx_DIR)/sta/rtmp_data.o\ + $(RT28xx_DIR)/sta/connect.o\ + $(RT28xx_DIR)/sta/wpa.o\ + $(RT28xx_DIR)/sta/sta_cfg.o\ + $(RT28xx_DIR)/ap/ap_autoChSel.o\ + $(RT28xx_DIR)/ap/ap_qload.o\ + $(RT28xx_DIR)/ap/ap_cfg.o + +ifeq ($(OSABL),NO) +RT28XX_APSTA_OBJ += \ + $(RT28xx_DIR)/common/rtmp_init_inf.o\ + $(RT28xx_DIR)/ap/ap_mbss.o\ + $(RT28xx_DIR)/os/linux/rt_profile.o\ + $(RT28xx_DIR)/os/linux/ap_ioctl.o\ + $(RT28xx_DIR)/os/linux/sta_ioctl.o\ + $(RT28xx_DIR)/os/linux/rt_linux.o\ + $(RT28xx_DIR)/os/linux/rt_main_dev.o +endif + +ifeq ($(HAS_NEW_RATE_ADAPT_SUPPORT),y) +RT28XX_APSTA_OBJS += $(RT28xx_DIR)/rate_ctrl/alg_grp.o +endif + +#ifdef DOT11_N_SUPPORT +ifeq ($(HAS_DOT11_N_SUPPORT),y) +RT28XX_APSTA_OBJ += \ + $(RT28xx_DIR)/common/ba_action.o + +#ifdef TXBF_SUPPORT +ifeq ($(HAS_TXBF_SUPPORT),y) +rt$(MODULE)apsta-objs += \ + $(RT28xx_DIR)/common/cmm_txbf.o\ + $(RT28xx_DIR)/common/cmm_txbf_cal.o +endif +#endif // TXBF_SUPPORT // +endif +#endif // DOT11_N_SUPPORT // + + +#ifdef LED_CONTROL_SUPPORT +ifeq ($(HAS_LED_CONTROL_SUPPORT),y) +RT28XX_APSTA_OBJ += \ + $(RT28xx_DIR)/common/rt_led.o +endif +#endif // LED_CONTROL_SUPPORT // + +#ifdef RT2860 +ifneq ($(findstring 2860,$(CHIPSET)),) +RT28XX_APSTA_OBJ += \ + $(RT28xx_DIR)/common/cmm_mac_pci.o\ + $(RT28xx_DIR)/common/cmm_data_pci.o\ + $(RT28xx_DIR)/common/rtmp_mcu.o\ + $(RT28xx_DIR)/common/ee_prom.o + +ifeq ($(OSABL),NO) +RT28XX_APSTA_OBJ += \ + $(RT28xx_DIR)/os/linux/rt_pci_rbus.o\ + $(RT28xx_DIR)/os/linux/rt_rbus_pci_util.o\ + $(RT28xx_DIR)/os/linux/pci_main_dev.o +endif +endif +#endif // RT2860 // + + + + + + + +ifneq ($(findstring 3573,$(CHIPSET)),) +RT28XX_APSTA_OBJ += \ + $(RT28xx_DIR)/common/cmm_mac_usb.o\ + $(RT28xx_DIR)/common/rtusb_io.o\ + $(RT28xx_DIR)/common/rtusb_data.o\ + $(RT28xx_DIR)/common/cmm_data_usb.o\ + $(RT28xx_DIR)/common/rtmp_mcu.o\ + $(RT28xx_DIR)/common/ee_prom.o\ + $(RT28xx_DIR)/common/ee_efuse.o\ + $(RT28xx_DIR)/common/rt_rf.o\ + $(RT28xx_DIR)/common/rtusb_bulk.o\ + $(RT28xx_DIR)/common/frq_cal.o\ + $(RT28xx_DIR)/os/linux/rt_usb.o\ + $(RT28xx_DIR)/chips/rt28xx.o\ + $(RT28xx_DIR)/chips/rt30xx.o\ + $(RT28xx_DIR)/chips/rt35xx.o\ + $(RT28xx_DIR)/chips/rt3593.o + +ifeq ($(OSABL),NO) +RT28XX_APSTA_OBJ += \ + $(RT28xx_DIR)/common/rtusb_dev_id.o\ + $(RT28xx_DIR)/os/linux/rt_usb_util.o\ + $(RT28xx_DIR)/os/linux/usb_main_dev.o +endif +ifeq ($(HAS_DFS_SUPPORT),y) +RT28XX_APSTA_OBJ += \ + $(RT28xx_DIR)/common/dfs_mcu.o +endif +endif + +ifneq ($(findstring 3593,$(CHIPSET)),) +RT28XX_APSTA_OBJ += \ + $(RT28xx_DIR)/common/cmm_mac_pci.o\ + $(RT28xx_DIR)/common/cmm_data_pci.o\ + $(RT28xx_DIR)/os/linux/rt_rbus_pci_drv.o\ + $(RT28xx_DIR)/common/rtmp_mcu.o\ + $(RT28xx_DIR)/common/ee_prom.o\ + $(RT28xx_DIR)/common/ee_efuse.o\ + $(RT28xx_DIR)/common/rt_rf.o\ + $(RT28xx_DIR)/common/frq_cal.o\ + $(RT28xx_DIR)/chips/rt30xx.o\ + $(RT28xx_DIR)/chips/rt35xx.o\ + $(RT28xx_DIR)/chips/rt28xx.o\ + $(RT28xx_DIR)/chips/rt3593.o + +ifeq ($(OSABL),NO) +RT28XX_APSTA_OBJ += \ + $(RT28xx_DIR)/os/linux/rt_pci_rbus.o\ + $(RT28xx_DIR)/os/linux/rt_rbus_pci_util.o\ + $(RT28xx_DIR)/os/linux/pci_main_dev.o +endif +ifeq ($(HAS_DFS_SUPPORT),y) +RT28XX_APSTA_OBJ += \ + $(RT28xx_DIR)/common/dfs_mcu.o +endif +endif + + + + +#ifdef RTMP_MAC_PCI +#endif // RTMP_MAC_PCI // + +#ifdef WSC_INCLUDED +ifeq ($(HAS_WSC),y) +RT28XX_APSTA_OBJ += \ + $(RT28xx_DIR)/common/wsc.o\ + $(RT28xx_DIR)/common/wsc_tlv.o\ + $(RT28xx_DIR)/common/crypt_biginteger.o\ + $(RT28xx_DIR)/common/crypt_dh.o +endif +#endif // WSC_INCLUDED // + +#ifdef NINTENDO_AP +ifeq ($(HAS_NINTENDO),y) +RT28XX_APSTA_OBJ += $(RT28xx_DIR)/ap/ap_nintendo.o +endif +#endif // NINTENDO_AP // + +ifeq ($(HAS_WDS),y) +RT28XX_APSTA_OBJ += $(RT28xx_DIR)/ap/ap_wds.o + +ifeq ($(OSABL),NO) +RT28XX_APSTA_OBJ += \ + ../../ap/ap_wds_inf.o +endif +endif + +ifeq ($(HAS_QOS_DLS_SUPPORT),y) +RT28XX_APSTA_OBJ += $(RT28xx_DIR)/ap/ap_dls.o +endif + +ifeq ($(HAS_IDS_SUPPORT),y) +RT28XX_APSTA_OBJ += $(RT28xx_DIR)/ap/ap_ids.o +endif + +#ifdef APCLI_SUPPORT +ifeq ($(HAS_APCLI),y) +RT28XX_APSTA_OBJ += \ + $(RT28xx_DIR)/ap/ap_apcli.o \ + $(RT28xx_DIR)/ap/apcli_ctrl.o \ + $(RT28xx_DIR)/ap/apcli_sync.o \ + $(RT28xx_DIR)/ap/apcli_auth.o \ + $(RT28xx_DIR)/ap/apcli_assoc.o \ + $(RT28xx_DIR)/common/cmm_mat.o \ + $(RT28xx_DIR)/common/cmm_mat_iparp.o \ + $(RT28xx_DIR)/common/cmm_mat_pppoe.o \ + $(RT28xx_DIR)/common/cmm_mat_ipv6.o + +ifeq ($(OSABL),NO) +RT28XX_APSTA_OBJ += \ + ../../ap/ap_apcli_inf.o +endif +endif +#endif // APCLI_SUPPORT // + +#ifdef ETH_CONVERT +ifeq ($(HAS_ETH_CONVERT_SUPPORT), y) +RT28XX_APSTA_OBJ += \ + $(RT28xx_DIR)/common/cmm_mat.o \ + $(RT28xx_DIR)/common/cmm_mat_iparp.o \ + $(RT28xx_DIR)/common/cmm_mat_pppoe.o \ + $(RT28xx_DIR)/common/cmm_mat_ipv6.o +endif +#endif // ETH_CONVERT // + +ifeq ($(HAS_BLOCK_NET_IF),y) +RT28XX_APSTA_OBJ += $(RT28xx_DIR)/common/netif_block.o +endif + +ifeq ($(HAS_IGMP_SNOOP_SUPPORT),y) +RT28XX_APSTA_OBJ += $(RT28xx_DIR)/common/igmp_snoop.o +endif + +#ifdef MESH_SUPPORT +ifeq ($(HAS_MESH_SUPPORT),y) +RT28XX_APSTA_OBJ += \ + $(RT28xx_DIR)/common/mesh_bmpkt.o \ + $(RT28xx_DIR)/common/mesh_ctrl.o \ + $(RT28xx_DIR)/common/mesh_link_mng.o \ + $(RT28xx_DIR)/common/mesh_sanity.o \ + $(RT28xx_DIR)/common/mesh_tlv.o \ + $(RT28xx_DIR)/common/mesh.o \ + $(RT28xx_DIR)/common/mesh_forwarding.o \ + $(RT28xx_DIR)/common/mesh_path_mng.o + +ifeq ($(OSABL),NO) +RT28XX_APSTA_OBJ += \ + ../../common/mesh_inf.o +endif +endif +#endif // MESH_SUPPORT // + +#ifdef WAPI_SUPPORT +ifeq ($(HAS_WAPI_SUPPORT),y) +RT28XX_APSTA_OBJ += \ + $(RT28xx_DIR)/common/wapi.o +endif +#endif // WAPI_SUPPORT // + + +ifeq ($(HAS_CLIENT_WDS_SUPPORT),y) +RT28XX_APSTA_OBJ += \ + $(RT28xx_DIR)/common/client_wds.o +endif +#endif // CONFIG_APSTA_SUPPORT // + +PHONY := all release clean install uninstall + +all:$(OBJ) + +rt$(MODULE)sta.o: $(RT28XX_STA_OBJ) + $(LD) -r $^ -o $@ + +rt$(MODULE)ap.o: $(RT28XX_AP_OBJ) + $(LD) -r $^ -o $@ + +rt$(MODULE)apsta.o: $(RT28XX_APSTA_OBJ) + $(LD) -r $^ -o $@ + +release: + echo "MAKE Linux Station Code Release" + +clean: + rm -f $(RT28xx_DIR)/common/*.o + rm -f $(RT28xx_DIR)/common/.*.{cmd,flags,d} + rm -f $(RT28xx_DIR)/os/linux/*.{o,ko,mod.{o,c}} + rm -f $(RT28xx_DIR)/os/linux/.*.{cmd,flags,d} + rm -fr $(RT28xx_DIR)/os/linux/.tmp_versions + rm -f $(RT28xx_DIR)/chips/*.o + rm -f $(RT28xx_DIR)/chips/.*.{cmd,flags,d} +ifeq ($(RT28xx_MODE),AP) + rm -f $(RT28xx_DIR)/ap/*.o + rm -f $(RT28xx_DIR)/ap/.*.{cmd,flags,d} +else +ifeq ($(RT28xx_MODE),STA) + rm -f $(RT28xx_DIR)/sta/*.o + rm -f $(RT28xx_DIR)/sta/.*.{cmd,flags,d} +else +ifeq ($(RT28xx_MODE),APSTA) + rm -f $(RT28xx_DIR)/ap/*.o + rm -f $(RT28xx_DIR)/ap/.*.{cmd,flags,d} + rm -f $(RT28xx_DIR)/sta/*.o + rm -f $(RT28xx_DIR)/sta/.*.{cmd,flags,d} +endif +endif +endif + +install: + rm -rf $(DAT_PATH) + $(shell [ ! -f /etc/Wireless ] && mkdir /etc/Wireless) + mkdir $(DAT_PATH) + cp $(RT28xx_DIR)/$(DAT_FILE_NAME) $(DAT_PATH)/. + install -d $(LINUX_SRC_MODULE) + install -m 644 -c $(addsuffix .o,$(MOD_NAME)) $(LINUX_SRC_MODULE) + /sbin/depmod -a ${shell uname -r} + +uninstall: +# rm -rf $(DAT_PATH) + rm -rf $(addprefix $(LINUX_SRC_MODULE),$(addsuffix .o,$(MOD_NAME))) + /sbin/depmod -a ${shell uname -r} + +# Declare the contents of the .PHONY variable as phony. We keep that +# information in a variable so we can use it in if_changed and friends. +.PHONY: $(PHONY) + diff --git a/mt7620/src/os/linux/Makefile.4.netif b/mt7620/src/os/linux/Makefile.4.netif new file mode 100644 index 0000000..3b2d1f7 --- /dev/null +++ b/mt7620/src/os/linux/Makefile.4.netif @@ -0,0 +1,217 @@ +include $(RT28xx_DIR)/os/linux/config.mk + +#ifdef CONFIG_AP_SUPPORT +ifeq ($(RT28xx_MODE),AP) +MOD_NAME = rtnet$(MODULE)ap +endif +#endif // CONFIG_AP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT +ifeq ($(RT28xx_MODE), STA) +MOD_NAME = rtnet$(MODULE)sta +endif +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_APSTA_SUPPORT +ifeq ($(RT28xx_MODE), APSTA) +MOD_NAME = rtnet$(MODULE)apsta +endif +#endif // CONFIG_APSTA_SUPPORT // + +OBJ := $(MOD_NAME).o + +#ifdef CONFIG_AP_SUPPORT + +RT28XX_AP_OBJ := \ + ../../ap/ap_mbss_inf.o\ + ../../os/linux/ap_ioctl.o\ + ../../os/linux/rt_main_dev.o + +ifeq ($(HAS_WDS),y) +RT28XX_AP_OBJ += \ + ../../ap/ap_wds_inf.o +endif + +ifeq ($(HAS_APCLI),y) +RT28XX_AP_OBJ += \ + ../../ap/ap_apcli_inf.o +endif + +ifeq ($(HAS_MESH_SUPPORT),y) +RT28XX_AP_OBJ += \ + ../../common/mesh_inf.o +endif + +#ifdef RT2860 +ifneq ($(findstring 2860,$(CHIPSET)),) +RT28XX_AP_OBJ += \ + ../../os/linux/rt_pci_rbus.o\ + ../../os/linux/pci_main_dev.o +endif +#endif // RT2860 // + + + + + +#ifdef RT2880 +ifneq ($(findstring 2880,$(CHIPSET)),) +RT28XX_AP_OBJ += \ + ../../os/linux/rt_pci_rbus.o\ + ../../os/linux/pci_main_dev.o +endif +#endif // RT2880 // + + + + + + + + + + +#endif // CONFIG_AP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT +RT28XX_STA_OBJ := \ + ../../os/linux/sta_ioctl.o\ + ../../os/linux/rt_main_dev.o + +ifeq ($(HAS_MESH_SUPPORT),y) +RT28XX_STA_OBJ += \ + ../../common/mesh_inf.o +endif + +ifeq ($(HAS_P2P_SUPPORT), y) +RT28XX_STA_OBJ += \ + ../../common/p2p_inf.o\ + ../../os/linux/ap_ioctl.o +endif + +#ifdef RT2860 +ifneq ($(findstring 2860,$(CHIPSET)),) +RT28XX_STA_OBJ += \ + ../../os/linux/rt_pci_rbus.o\ + ../../os/linux/pci_main_dev.o +endif +#endif // RT2860 // + + + + + +#ifdef RT2880 +ifneq ($(findstring 2880,$(CHIPSET)),) +RT28XX_STA_OBJ += \ + ../../os/linux/rt_pci_rbus.o\ + ../../os/linux/pci_main_dev.o +endif +#endif // RT2880 // + + + + + + + + + + + +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_APSTA_SUPPORT +RT28XX_APSTA_OBJ := \ + ../../ap/ap_mbss_inf.o\ + ../../common/p2p_inf.o\ + ../../os/linux/ap_ioctl.o\ + ../../os/linux/sta_ioctl.o\ + ../../os/linux/rt_main_dev.o + +ifeq ($(HAS_WDS),y) +RT28XX_APSTA_OBJ += \ + ../../ap/ap_wds_inf.o +endif + +ifeq ($(HAS_APCLI),y) +RT28XX_APSTA_OBJ += \ + ../../ap/ap_apcli_inf.o +endif + +ifeq ($(HAS_MESH_SUPPORT),y) +RT28XX_APSTA_OBJ += \ + ../../common/mesh_inf.o +endif + +#ifdef RT2860 +ifneq ($(findstring 2860,$(CHIPSET)),) +RT28XX_APSTA_OBJ += \ + ../../os/linux/rt_pci_rbus.o\ + ../../os/linux/pci_main_dev.o +endif +#endif // RT2860 // + + + + + + + + + + + + +#endif // CONFIG_APSTA_SUPPORT // + +PHONY := all clean + +all:$(OBJ) + +rtnet$(MODULE)sta.o: $(RT28XX_STA_OBJ) + $(LD) -r $^ -o $@ + +rtnet$(MODULE)ap.o: $(RT28XX_AP_OBJ) + $(LD) -r $^ -o $@ + +rtnet$(MODULE)apsta.o: $(RT28XX_APSTA_OBJ) + $(LD) -r $^ -o $@ + +clean: + rm -f $(RT28xx_DIR)/common/*.o + rm -f $(RT28xx_DIR)/common/.*.{cmd,flags,d} + rm -f $(RT28xx_DIR)/os/linux/*.{o,ko,mod.{o,c}} + rm -f $(RT28xx_DIR)/os/linux/.*.{cmd,flags,d} + rm -fr $(RT28xx_DIR)/os/linux/.tmp_versions + rm -f $(RT28xx_DIR)/chips/*.o + rm -f $(RT28xx_DIR)/chips/.*.{cmd,flags,d} +ifeq ($(RT28xx_MODE),AP) + rm -f $(RT28xx_DIR)/ap/*.o + rm -f $(RT28xx_DIR)/ap/.*.{cmd,flags,d} +else +ifeq ($(RT28xx_MODE),STA) + rm -f $(RT28xx_DIR)/sta/*.o + rm -f $(RT28xx_DIR)/sta/.*.{cmd,flags,d} +else +ifeq ($(RT28xx_MODE),APSTA) + rm -f $(RT28xx_DIR)/ap/*.o + rm -f $(RT28xx_DIR)/ap/.*.{cmd,flags,d} + rm -f $(RT28xx_DIR)/sta/*.o + rm -f $(RT28xx_DIR)/sta/.*.{cmd,flags,d} +endif +endif +endif + +install: + install -d $(LINUX_SRC_MODULE) + install -m 644 -c $(addsuffix .o,$(MOD_NAME)) $(LINUX_SRC_MODULE) + /sbin/depmod -a ${shell uname -r} + +uninstall: + rm -rf $(addprefix $(LINUX_SRC_MODULE),$(addsuffix .o,$(MOD_NAME))) + /sbin/depmod -a ${shell uname -r} + +# Declare the contents of the .PHONY variable as phony. We keep that +# # information in a variable so we can use it in if_changed and friends. +.PHONY: $(PHONY) diff --git a/mt7620/src/os/linux/Makefile.4.util b/mt7620/src/os/linux/Makefile.4.util new file mode 100644 index 0000000..209d59b --- /dev/null +++ b/mt7620/src/os/linux/Makefile.4.util @@ -0,0 +1,110 @@ +include $(RT28xx_DIR)/os/linux/config.mk + +#ifdef CONFIG_AP_SUPPORT +ifeq ($(RT28xx_MODE),AP) +MOD_NAME = rtutil$(MODULE)ap +endif +#endif // CONFIG_AP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT +ifeq ($(RT28xx_MODE), STA) +MOD_NAME = rtutil$(MODULE)sta +endif +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_APSTA_SUPPORT +ifeq ($(RT28xx_MODE), APSTA) +MOD_NAME = rtutil$(MODULE)apsta +endif +#endif // CONFIG_APSTA_SUPPORT // + +OBJ := $(MOD_NAME).o + +#ifdef CONFIG_AP_SUPPORT + +RT28XX_AP_OBJ := \ + ../../common/rt_os_util.o\ + ../../os/linux/rt_linux_symb.o\ + ../../os/linux/rt_rbus_pci_util.o\ + ../../os/linux/rt_usb_util.o\ + ../../os/linux/rt_linux.o + +ifeq ($(HAS_BGFP_SUPPORT),y) +RT28XX_AP_OBJ += \ + $(RT28xx_DIR)/os/linux/br_ftph.o +endif + +#endif // CONFIG_AP_SUPPORT // + + +#ifdef CONFIG_STA_SUPPORT + +RT28XX_STA_OBJ := \ + ../../common/rt_os_util.o\ + ../../os/linux/rt_linux_symb.o\ + ../../os/linux/rt_rbus_pci_util.o\ + ../../os/linux/rt_usb_util.o\ + ../../os/linux/rt_linux.o +#endif // CONFIG_STA_SUPPORT // + + +#ifdef CONFIG_APSTA_SUPPORT +RT28XX_APSTA_OBJ := \ + ../../common/rt_os_util.o\ + ../../os/linux/rt_linux_symb.o\ + ../../os/linux/rt_rbus_pci_util.o\ + ../../os/linux/rt_usb_util.o\ + ../../os/linux/rt_linux.o + +#endif // CONFIG_APSTA_SUPPORT // + +PHONY := all clean + +all:$(OBJ) + +rtutil$(MODULE)sta.o: $(RT28XX_STA_OBJ) + $(LD) -r $^ -o $@ + +rtutil$(MODULE)ap.o: $(RT28XX_AP_OBJ) + $(LD) -r $^ -o $@ + +rtutil$(MODULE)apsta.o: $(RT28XX_APSTA_OBJ) + $(LD) -r $^ -o $@ + +clean: + rm -f $(RT28xx_DIR)/common/*.o + rm -f $(RT28xx_DIR)/common/.*.{cmd,flags,d} + rm -f $(RT28xx_DIR)/os/linux/*.{o,ko,mod.{o,c}} + rm -f $(RT28xx_DIR)/os/linux/.*.{cmd,flags,d} + rm -fr $(RT28xx_DIR)/os/linux/.tmp_versions + rm -f $(RT28xx_DIR)/chips/*.o + rm -f $(RT28xx_DIR)/chips/.*.{cmd,flags,d} +ifeq ($(RT28xx_MODE),AP) + rm -f $(RT28xx_DIR)/ap/*.o + rm -f $(RT28xx_DIR)/ap/.*.{cmd,flags,d} +else +ifeq ($(RT28xx_MODE),STA) + rm -f $(RT28xx_DIR)/sta/*.o + rm -f $(RT28xx_DIR)/sta/.*.{cmd,flags,d} +else +ifeq ($(RT28xx_MODE),APSTA) + rm -f $(RT28xx_DIR)/ap/*.o + rm -f $(RT28xx_DIR)/ap/.*.{cmd,flags,d} + rm -f $(RT28xx_DIR)/sta/*.o + rm -f $(RT28xx_DIR)/sta/.*.{cmd,flags,d} +endif +endif +endif + +install: + install -d $(LINUX_SRC_MODULE) + install -m 644 -c $(addsuffix .o,$(MOD_NAME)) $(LINUX_SRC_MODULE) + /sbin/depmod -a ${shell uname -r} + +uninstall: + rm -rf $(addprefix $(LINUX_SRC_MODULE),$(addsuffix .o,$(MOD_NAME))) + /sbin/depmod -a ${shell uname -r} + +# Declare the contents of the .PHONY variable as phony. We keep that +# # information in a variable so we can use it in if_changed and friends. +.PHONY: $(PHONY) diff --git a/mt7620/src/os/linux/Makefile.6 b/mt7620/src/os/linux/Makefile.6 new file mode 100644 index 0000000..358d5be --- /dev/null +++ b/mt7620/src/os/linux/Makefile.6 @@ -0,0 +1,1063 @@ +include $(RT28xx_DIR)/os/linux/config.mk + +#ifdef CONFIG_AP_SUPPORT +ifeq ($(RT28xx_MODE),AP) +MOD_NAME = rt$(MODULE)ap +DAT_PATH = /etc/Wireless/RT$(CHIPSET_DAT)AP +DAT_FILE_NAME = RT$(CHIPSET_DAT)AP.dat +endif +#endif // CONFIG_AP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT +ifeq ($(RT28xx_MODE), STA) +MOD_NAME = rt$(MODULE)sta +DAT_PATH = /etc/Wireless/RT$(CHIPSET_DAT)STA +DAT_FILE_NAME = RT$(CHIPSET_DAT)STA.dat +endif +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_APSTA_SUPPORT +ifeq ($(RT28xx_MODE), APSTA) +MOD_NAME = rt$(MODULE)apsta +endif +#endif // CONFIG_APSTA_SUPPORT // + +obj-m := $(MOD_NAME).o + +#ifdef CONFIG_AP_SUPPORT +ifeq ($(RT28xx_MODE),AP) +$(MOD_NAME)-objs := \ + ../../common/crypt_md5.o\ + ../../common/crypt_sha2.o\ + ../../common/crypt_hmac.o\ + ../../common/crypt_aes.o\ + ../../common/crypt_arc4.o\ + ../../common/mlme.o\ + ../../common/cmm_wep.o\ + ../../common/action.o\ + ../../common/cmm_data.o\ + ../../common/rtmp_init.o\ + ../../common/rtmp_init_inf.o\ + ../../common/cmm_tkip.o\ + ../../common/cmm_aes.o\ + ../../common/cmm_sync.o\ + ../../common/eeprom.o\ + ../../common/cmm_sanity.o\ + ../../common/cmm_info.o\ + ../../common/cmm_cfg.o\ + ../../common/cmm_wpa.o\ + ../../common/cmm_radar.o\ + ../../common/spectrum.o\ + ../../common/rtmp_timer.o\ + ../../common/rt_channel.o\ + ../../common/cmm_profile.o\ + ../../common/cmm_asic.o\ + ../../common/cmm_cmd.o\ + ../../common/ps.o\ + ../../rate_ctrl/ra_ctrl.o\ + ../../rate_ctrl/alg_legacy.o\ + ../../rate_ctrl/alg_ags.o\ + ../../os/linux/rt_profile.o\ + ../../ap/ap_mbss.o\ + ../../chips/rtmp_chip.o\ + ../../ap/ap.o\ + ../../ap/ap_assoc.o\ + ../../ap/ap_auth.o\ + ../../ap/ap_connect.o\ + ../../ap/ap_mlme.o\ + ../../ap/ap_sanity.o\ + ../../ap/ap_sync.o\ + ../../ap/ap_wpa.o\ + ../../ap/ap_data.o\ + ../../common/uapsd.o\ + ../../ap/ap_autoChSel.o\ + ../../ap/ap_qload.o\ + ../../ap/ap_cfg.o + +ifeq ($(HAS_ATE),y) +$(MOD_NAME)-objs += ../../ate/common/rt_ate.o +endif + +ifeq ($(HAS_QA_SUPPORT),y) +$(MOD_NAME)-objs += ../../ate/common/rt_qa.o +endif + +ifeq ($(OSABL),NO) +$(MOD_NAME)-objs += \ + ../../ap/ap_mbss_inf.o\ + ../../common/rt_os_util.o\ + ../../os/linux/ap_ioctl.o\ + ../../os/linux/rt_linux.o\ + ../../os/linux/rt_main_dev.o +else +$(MOD_NAME)-objs += \ + ../../os/linux/rt_symb.o +endif + + +ifeq ($(HAS_NEW_RATE_ADAPT_SUPPORT),y) +$(MOD_NAME)-objs += ../../rate_ctrl/alg_grp.o +endif + +#ifdef DOT11_N_SUPPORT +ifeq ($(HAS_DOT11_N_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/ba_action.o + +#ifdef TXBF_SUPPORT +ifeq ($(HAS_TXBF_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/cmm_txbf.o\ + ../../common/cmm_txbf_cal.o +endif +#endif // TXBF_SUPPORT // +endif +#endif // DOT11_N_SUPPORT // + +#ifdef BG_FT_SUPPORT +ifeq ($(OSABL),NO) +ifeq ($(HAS_BGFP_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../os/linux/br_ftph.o +endif +endif +#endif // BG_FT_SUPPORT // + + +#ifdef CRDA_SUPPORT +ifeq ($(OSABL),NO) +ifeq ($(HAS_CFG80211_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../os/linux/cfg80211.o\ + ../../os/linux/cfg80211drv.o +endif +endif + +ifeq ($(OSABL),YES) +ifeq ($(HAS_CFG80211_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../os/linux/cfg80211drv.o +endif +endif +#endif // CRDA_SUPPORT // + +#ifdef LED_CONTROL_SUPPORT +ifeq ($(HAS_LED_CONTROL_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/rt_led.o +endif +#endif // LED_CONTROL_SUPPORT // + + +ifeq ($(HAS_RT2880_RT2860_COEXIST),y) +RT28XX_AP_OBJ += \ + ../../os/linux/rt_pci_rbus.o\ + ../../os/linux/rt_rbus_pci_util.o\ + ../../os/linux/pci_main_dev.o\ + ../../common/dfs.o +endif + +#ifdef WSC_INCLUDED +ifeq ($(HAS_WSC),y) +$(MOD_NAME)-objs += \ + ../../common/wsc.o\ + ../../common/wsc_tlv.o\ + ../../common/wsc_ufd.o\ + ../../common/crypt_biginteger.o\ + ../../common/crypt_dh.o +endif +ifeq ($(HAS_WSC_V2),y) +$(MOD_NAME)-objs += ../../common/wsc_v2.o +endif +#endif // WSC_INCLUDED // + +#ifdef EASY_CONFIG_SETUP +ifeq ($(HAS_EASY_CONFIG_SETUP_SUPPORT),y) +ifneq ($(PLATFORM),RALINK_3052) +$(MOD_NAME)-objs += ../../common/auto_provision.o +endif +endif +#endif // EASY_CONFIG_SETUP // + +#ifdef NINTENDO_AP +ifeq ($(HAS_NINTENDO),y) +$(MOD_NAME)-objs += ../../ap/ap_nintendo.o +endif +#endif // NINTENDO_AP // + +ifeq ($(HAS_WDS),y) +$(MOD_NAME)-objs += ../../ap/ap_wds.o + +ifeq ($(OSABL),NO) +$(MOD_NAME)-objs += \ + ../../ap/ap_wds_inf.o +endif +endif + +#ifdef APCLI_SUPPORT +ifeq ($(HAS_APCLI),y) +$(MOD_NAME)-objs += \ + ../../ap/ap_apcli.o \ + ../../ap/apcli_ctrl.o \ + ../../ap/apcli_sync.o \ + ../../ap/apcli_auth.o \ + ../../ap/apcli_assoc.o \ + ../../common/cmm_mat.o \ + ../../common/cmm_mat_iparp.o \ + ../../common/cmm_mat_pppoe.o \ + ../../common/cmm_mat_ipv6.o + +ifeq ($(OSABL),NO) +$(MOD_NAME)-objs += \ + ../../ap/ap_apcli_inf.o +endif +endif +#endif // APCLI_SUPPORT // + +ifeq ($(HAS_BLOCK_NET_IF),y) +$(MOD_NAME)-objs += ../../common/netif_block.o +endif + +ifeq ($(HAS_IGMP_SNOOP_SUPPORT),y) +$(MOD_NAME)-objs += ../../common/igmp_snoop.o +endif + + +ifeq ($(HAS_QOS_DLS_SUPPORT),y) +$(MOD_NAME)-objs += ../../ap/ap_dls.o +endif + +ifeq ($(HAS_IDS_SUPPORT),y) +$(MOD_NAME)-objs += ../../ap/ap_ids.o +endif + +ifeq ($(PLATFORM),IKANOS_V160) +$(MOD_NAME)-objs += ../../os/linux/vr_ikans.o +endif + +ifeq ($(PLATFORM),IKANOS_V180) +$(MOD_NAME)-objs += ../../os/linux/vr_ikans.o +endif + +ifeq ($(PLATFORM),BL2348) +ifeq ($(OSABL),NO) +$(MOD_NAME)-objs += ../../os/linux/vr_bdlt.o +endif +endif +#ifdef PLATFORM_BL23570 +ifeq ($(PLATFORM),BL23570) +rt$(CHIPSET)ap-objs += \ + ../../os/linux/vr_bdlt.o +endif +#endif // PLATFORM_BL23570 // + +#ifdef MESH_SUPPORT +ifeq ($(HAS_MESH_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/mesh_bmpkt.o \ + ../../common/mesh_ctrl.o \ + ../../common/mesh_link_mng.o \ + ../../common/mesh_sanity.o \ + ../../common/mesh_tlv.o \ + ../../common/mesh.o \ + ../../common/mesh_forwarding.o \ + ../../common/mesh_path_mng.o + +ifeq ($(OSABL),NO) +$(MOD_NAME)-objs += \ + ../../common/mesh_inf.o +endif +endif +#endif // MESH_SUPPORT // + +#ifdef WAPI_SUPPORT +ifeq ($(HAS_WAPI_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/wapi.o +endif +#endif // WAPI_SUPPORT // + + + + + +ifeq ($(HAS_CLIENT_WDS_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/client_wds.o +endif + +ifeq ($(HAS_EASY_CONFIG_SETUP_SUPPORT),y) +ifeq ($(PLATFORM),RALINK_3052) +$(MOD_NAME)-objs += lib.a +endif +endif + +ifeq ($(HAS_DFS_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/cmm_dfs.o +endif + +ifeq ($(HAS_CS_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/cmm_cs.o +endif + +endif +#endif // CONFIG_AP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT +ifeq ($(RT28xx_MODE), STA) +$(MOD_NAME)-objs := \ + ../../common/crypt_md5.o\ + ../../common/crypt_sha2.o\ + ../../common/crypt_hmac.o\ + ../../common/crypt_aes.o\ + ../../common/crypt_arc4.o\ + ../../common/mlme.o\ + ../../common/cmm_wep.o\ + ../../common/action.o\ + ../../common/cmm_data.o\ + ../../common/rtmp_init.o\ + ../../common/rtmp_init_inf.o\ + ../../common/cmm_tkip.o\ + ../../common/cmm_aes.o\ + ../../common/cmm_sync.o\ + ../../common/eeprom.o\ + ../../common/cmm_sanity.o\ + ../../common/cmm_info.o\ + ../../common/cmm_cfg.o\ + ../../common/cmm_wpa.o\ + ../../common/cmm_radar.o\ + ../../common/spectrum.o\ + ../../common/rtmp_timer.o\ + ../../common/rt_channel.o\ + ../../common/cmm_profile.o\ + ../../common/cmm_asic.o\ + ../../common/cmm_cmd.o\ + ../../common/ps.o\ + ../../common/uapsd.o\ + ../../rate_ctrl/ra_ctrl.o\ + ../../rate_ctrl/alg_legacy.o\ + ../../rate_ctrl/alg_ags.o\ + ../../os/linux/rt_profile.o\ + ../../chips/rtmp_chip.o\ + ../../sta/assoc.o\ + ../../sta/auth.o\ + ../../sta/auth_rsp.o\ + ../../sta/sync.o\ + ../../sta/sanity.o\ + ../../sta/rtmp_data.o\ + ../../sta/connect.o\ + ../../sta/wpa.o\ + ../../sta/sta_cfg.o + +ifeq ($(OSABL),NO) +$(MOD_NAME)-objs += \ + ../../common/rt_os_util.o\ + ../../os/linux/sta_ioctl.o\ + ../../os/linux/rt_linux.o\ + ../../os/linux/rt_main_dev.o +else +$(MOD_NAME)-objs += \ + ../../os/linux/rt_symb.o +endif + +ifeq ($(HAS_NEW_RATE_ADAPT_SUPPORT),y) +$(MOD_NAME)-objs += ../../rate_ctrl/alg_grp.o +endif + +#ifdef DOT11_N_SUPPORT +ifeq ($(HAS_DOT11_N_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/ba_action.o + +#ifdef TXBF_SUPPORT +ifeq ($(HAS_TXBF_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/cmm_txbf.o\ + ../../common/cmm_txbf_cal.o +endif +#endif // TXBF_SUPPORT // +endif +#endif // DOT11_N_SUPPORT // + +#ifdef ETH_CONVERT +ifeq ($(HAS_ETH_CONVERT_SUPPORT), y) +$(MOD_NAME)-objs += \ + ../../common/cmm_mat.o \ + ../../common/cmm_mat_iparp.o \ + ../../common/cmm_mat_pppoe.o \ + ../../common/cmm_mat_ipv6.o +endif +#endif // ETH_CONVERT // + +#ifdef ADHOC_WPA2PSK_SUPPORT +$(MOD_NAME)-objs += \ + ../../common/cmm_wpa_adhoc.o +#endif // ADHOC_WPA2PSK_SUPPORT // + +#ifdef WSC_INCLUDED +ifeq ($(HAS_WSC),y) +$(MOD_NAME)-objs += \ + ../../common/wsc.o\ + ../../common/wsc_tlv.o\ + ../../common/crypt_biginteger.o\ + ../../common/crypt_dh.o +endif +ifeq ($(HAS_WSC_V2),y) +$(MOD_NAME)-objs += ../../common/wsc_v2.o + +ifeq ($(HAS_WIDI_SUPPORT),y) +$(MOD_NAME)-objs += ../../common/l2sd_ta_mod.o +endif + +ifeq ($(HAS_IWSC_SUPPORT),y) +$(MOD_NAME)-objs += ../../sta/sta_iwsc.o +endif + +endif +#endif // WSC_INCLUDED // + + + +ifeq ($(HAS_BLOCK_NET_IF),y) +$(MOD_NAME)-objs += ../../common/netif_block.o +endif + +ifeq ($(HAS_QOS_DLS_SUPPORT),y) +$(MOD_NAME)-objs += ../../sta/dls.o +endif + +#ifdef DOT11Z_TDLS_SUPPORT +ifeq ($(HAS_DOT11Z_TDLS_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../sta/tdls.o\ + ../../sta/tdls_ctrl.o\ + ../../sta/tdls_tlv.o\ + ../../sta/tdls_link_mng.o\ + ../../sta/tdls_uapsd.o +endif +#endif // DOT11Z_TDLS_SUPPORT // + + +#ifdef LED_CONTROL_SUPPORT +ifeq ($(HAS_LED_CONTROL_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/rt_led.o +endif +#endif // LED_CONTROL_SUPPORT // + + +ifeq ($(HAS_ATE),y) +$(MOD_NAME)-objs += ../../ate/common/rt_ate.o +endif + +ifeq ($(HAS_QA_SUPPORT),y) +$(MOD_NAME)-objs += ../../ate/common/rt_qa.o +endif + + +#ifdef MESH_SUPPORT +ifeq ($(HAS_MESH_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/mesh_bmpkt.o \ + ../../common/mesh_ctrl.o \ + ../../common/mesh_link_mng.o \ + ../../common/mesh_sanity.o \ + ../../common/mesh_tlv.o \ + ../../common/mesh.o \ + ../../common/mesh_forwarding.o \ + ../../common/mesh_path_mng.o + +ifeq ($(OSABL),NO) +$(MOD_NAME)-objs += \ + ../../common/mesh_inf.o +endif +endif +#endif // MESH_SUPPORT // + +#ifdef WAPI_SUPPORT +ifeq ($(HAS_WAPI_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/wapi.o +endif +#endif // WAPI_SUPPORT // + + + +#ifdef P2P_SUPPORT +ifeq ($(OSABL),NO) +ifeq ($(HAS_P2P_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/p2p_inf.o +endif +endif + +ifeq ($(HAS_P2P_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../ap/ap_mbss.o\ + ../../ap/ap.o\ + ../../ap/ap_assoc.o\ + ../../ap/ap_auth.o\ + ../../ap/ap_connect.o\ + ../../ap/ap_mlme.o\ + ../../ap/ap_sanity.o\ + ../../ap/ap_sync.o\ + ../../ap/ap_wpa.o\ + ../../ap/ap_data.o\ + ../../common/uapsd.o\ + ../../ap/ap_autoChSel.o\ + ../../ap/ap_qload.o\ + ../../sta/p2pcli.o \ + ../../sta/p2pcli_ctrl.o \ + ../../sta/p2pcli_sync.o \ + ../../sta/p2pcli_auth.o \ + ../../sta/p2pcli_assoc.o \ + ../../common/cmm_mat.o \ + ../../common/cmm_mat_iparp.o \ + ../../common/cmm_mat_pppoe.o \ + ../../common/cmm_mat_ipv6.o \ + ../../common/p2p_dbg.o\ + ../../common/p2p_cfg.o\ + ../../common/p2p.o\ + ../../common/p2p_packet.o\ + ../../common/p2p_action.o\ + ../../common/p2p_table.o\ + ../../common/p2p_ctrl.o\ + ../../common/p2p_disc_mng.o\ + ../../common/p2p_nego_mng.o\ + ../../common/p2p_dbg.o\ + ../../common/p2p.o\ + ../../common/p2p_packet.o\ + ../../common/p2p_action.o\ + ../../common/p2p_table.o\ + ../../common/p2p_ctrl.o\ + ../../common/p2p_disc_mng.o\ + ../../common/p2p_nego_mng.o\ + ../../common/wsc.o\ + ../../common/wsc_tlv.o\ + ../../common/wsc_ufd.o\ + ../../common/crypt_biginteger.o\ + ../../common/crypt_dh.o + +ifeq ($(HAS_QOS_DLS_SUPPORT),y) +$(MOD_NAME)-objs += ../../ap/ap_dls.o +endif + +endif + +ifeq ($(HAS_P2P_SUPPORT),y) +ifeq ($(OSABL),NO) +$(MOD_NAME)-objs += \ + ../../ap/ap_mbss_inf.o\ + ../../common/rt_os_util.o\ + ../../os/linux/ap_ioctl.o\ + ../../os/linux/sta_ioctl.o\ + ../../os/linux/rt_linux.o\ + ../../os/linux/rt_main_dev.o +else +$(MOD_NAME)-objs += \ + ../../os/linux/rt_symb.o +endif +endif +#endif // P2P_SUPPORT // + +#ifdef CRDA_SUPPORT +ifeq ($(OSABL),NO) +ifeq ($(HAS_CFG80211_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../os/linux/cfg80211.o \ + ../../os/linux/cfg80211drv.o +endif +endif + +ifeq ($(OSABL),YES) +ifeq ($(HAS_CFG80211_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../os/linux/cfg80211drv.o +endif +endif +#endif // CRDA_SUPPORT // + + +ifeq ($(HAS_DFS_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/cmm_dfs.o +endif + +ifeq ($(HAS_CS_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/cmm_cs.o +endif + +endif +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_APSTA_SUPPORT +ifeq ($(RT28xx_MODE), APSTA) +$(MOD_NAME)-objs := \ + ../../common/crypt_md5.o\ + ../../common/crypt_sha2.o\ + ../../common/crypt_hmac.o\ + ../../common/crypt_aes.o\ + ../../common/crypt_arc4.o\ + ../../common/mlme.o\ + ../../common/cmm_wep.o\ + ../../common/action.o\ + ../../common/cmm_data.o\ + ../../common/rtmp_init.o\ + ../../common/rtmp_init_inf.o\ + ../../common/cmm_tkip.o\ + ../../common/cmm_aes.o\ + ../../common/cmm_sync.o\ + ../../common/eeprom.o\ + ../../common/cmm_sanity.o\ + ../../common/cmm_info.o\ + ../../common/cmm_cfg.o\ + ../../common/cmm_wpa.o\ + ../../common/cmm_wpa_adhoc.o\ + ../../common/dfs.o\ + ../../common/spectrum.o\ + ../../common/rtmp_timer.o\ + ../../common/rt_channel.o\ + ../../common/cmm_profile.o\ + ../../common/cmm_asic.o\ + ../../common/cmm_cmd.o\ + ../../common/ps.o\ + ../../rate_ctrl/ra_ctrl.o\ + ../../rate_ctrl/alg_legacy.o\ + ../../rate_ctrl/alg_ags.o\ + ../../os/linux/rt_profile.o\ + ../../ap/ap_mbss.o\ + ../../chips/rtmp_chip.o\ + ../../ap/ap.o\ + ../../ap/ap_assoc.o\ + ../../ap/ap_auth.o\ + ../../ap/ap_connect.o\ + ../../ap/ap_mlme.o\ + ../../ap/ap_sanity.o\ + ../../ap/ap_sync.o\ + ../../ap/ap_wpa.o\ + ../../ap/ap_data.o\ + ../../common/uapsd.o\ + ../../sta/assoc.o\ + ../../sta/auth.o\ + ../../sta/auth_rsp.o\ + ../../sta/sync.o\ + ../../sta/sanity.o\ + ../../sta/rtmp_data.o\ + ../../sta/connect.o\ + ../../sta/wpa.o\ + ../../ap/ap_autoChSel.o\ + ../../ap/ap_qload.o\ + ../../ap/ap_cfg.o\ + ../../sta/sta_cfg.o + +ifeq ($(OSABL),NO) +$(MOD_NAME)-objs += \ + ../../ap/ap_mbss_inf.o\ + ../../common/rt_os_util.o\ + ../../os/linux/ap_ioctl.o\ + ../../os/linux/sta_ioctl.o\ + ../../os/linux/rt_linux.o\ + ../../os/linux/rt_main_dev.o +else +$(MOD_NAME)-objs += \ + ../../os/linux/rt_symb.o +endif + +ifeq ($(HAS_NEW_RATE_ADAPT_SUPPORT),y) +$(MOD_NAME)-objs += ../../rate_ctrl/alg_grp.o +endif + +#ifdef DOT11_N_SUPPORT +ifeq ($(HAS_DOT11_N_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/ba_action.o + +#ifdef TXBF_SUPPORT +ifeq ($(HAS_TXBF_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/cmm_txbf.o\ + ../../common/cmm_txbf_cal.o +endif +#endif // TXBF_SUPPORT // +endif +#endif // DOT11_N_SUPPORT // + + +#ifdef LED_CONTROL_SUPPORT +ifeq ($(HAS_LED_CONTROL_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/rt_led.o +endif +#endif // LED_CONTROL_SUPPORT // + +#ifdef WSC_INCLUDED +ifeq ($(HAS_WSC),y) +$(MOD_NAME)-objs += \ + ../../common/wsc.o\ + ../../common/wsc_tlv.o\ + ../../common/crypt_biginteger.o\ + ../../common/wsc_ufd.o\ + ../../common/crypt_dh.o +endif +#endif // WSC_INCLUDED // + + +#ifdef NINTENDO_AP +ifeq ($(HAS_NINTENDO),y) +$(MOD_NAME)-objs += ../../ap/ap_nintendo.o +endif +#endif // NINTENDO_AP // + +ifeq ($(HAS_WDS),y) +$(MOD_NAME)-objs += ../../ap/ap_wds.o + +ifeq ($(OSABL),NO) +$(MOD_NAME)-objs += \ + ../../ap/ap_wds_inf.o +endif +endif + +ifeq ($(HAS_QOS_DLS_SUPPORT),y) +$(MOD_NAME)-objs += ../../ap/ap_dls.o +endif + +ifeq ($(HAS_IDS_SUPPORT),y) +$(MOD_NAME)-objs += ../../ap/ap_ids.o +endif + +#ifdef APCLI_SUPPORT +ifeq ($(HAS_APCLI),y) +$(MOD_NAME)-objs += \ + ../../ap/ap_apcli.o \ + ../../ap/apcli_ctrl.o \ + ../../ap/apcli_sync.o \ + ../../ap/apcli_auth.o \ + ../../ap/apcli_assoc.o \ + ../../common/cmm_mat.o \ + ../../common/cmm_mat_iparp.o \ + ../../common/cmm_mat_pppoe.o \ + ../../common/cmm_mat_ipv6.o + +ifeq ($(OSABL),NO) +$(MOD_NAME)-objs += \ + ../../ap/ap_apcli_inf.o +endif +endif +#endif // APCLI_SUPPORT // + +#ifdef ETH_CONVERT +ifeq ($(HAS_ETH_CONVERT_SUPPORT), y) +$(MOD_NAME)-objs += \ + ../../common/cmm_mat.o \ + ../../common/cmm_mat_iparp.o \ + ../../common/cmm_mat_pppoe.o \ + ../../common/cmm_mat_ipv6.o +endif +#endif // ETH_CONVERT // + +ifeq ($(HAS_BLOCK_NET_IF),y) +$(MOD_NAME)-objs += ../../common/netif_block.o +endif + +ifeq ($(HAS_IGMP_SNOOP_SUPPORT),y) +$(MOD_NAME)-objs += ../../common/igmp_snoop.o +endif + +#ifdef MESH_SUPPORT +ifeq ($(HAS_MESH_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/mesh_bmpkt.o \ + ../../common/mesh_ctrl.o \ + ../../common/mesh_link_mng.o \ + ../../common/mesh_sanity.o \ + ../../common/mesh_tlv.o \ + ../../common/mesh.o \ + ../../common/mesh_forwarding.o \ + ../../common/mesh_path_mng.o + +ifeq ($(OSABL),NO) +$(MOD_NAME)-objs += \ + ../../common/mesh_inf.o +endif +endif +#endif // MESH_SUPPORT // + +#ifdef WAPI_SUPPORT +ifeq ($(HAS_WAPI_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/libwapi.a\ + ../../common/wapi.o +endif +#endif // WAPI_SUPPORT // + + +ifeq ($(HAS_CLIENT_WDS_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/client_wds.o +endif + +#ifdef CRDA_SUPPORT +ifeq ($(OSABL),NO) +ifeq ($(HAS_CFG80211_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../os/linux/cfg80211.o +endif +endif +#endif // CRDA_SUPPORT // + +#ifdef P2P_SUPPORT +ifeq ($(OSABL),NO) +ifeq ($(HAS_P2P_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/p2p_inf.o +endif +endif + +ifeq ($(HAS_P2P_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../sta/p2pcli.o \ + ../../sta/p2pcli_ctrl.o \ + ../../sta/p2pcli_sync.o \ + ../../sta/p2pcli_auth.o \ + ../../sta/p2pcli_assoc.o \ + ../../common/cmm_mat.o \ + ../../common/cmm_mat_iparp.o \ + ../../common/cmm_mat_pppoe.o \ + ../../common/cmm_mat_ipv6.o \ + ../../common/p2p_dbg.o\ + ../../common/p2p.o\ + ../../common/p2p_packet.o\ + ../../common/p2p_action.o\ + ../../common/p2p_table.o\ + ../../common/p2p_ctrl.o\ + ../../common/p2p_disc_mng.o\ + ../../common/p2p_nego_mng.o +endif +#endif // P2P_SUPPORT // +endif +#endif // CONFIG_APSTA_SUPPORT // + + +#chip releated + +#ifdef RT2860 +ifneq ($(findstring 2860,$(CHIPSET)),) +$(MOD_NAME)-objs += \ + ../../common/cmm_mac_pci.o\ + ../../common/cmm_data_pci.o\ + ../../os/linux/rt_rbus_pci_drv.o\ + ../../common/rtmp_mcu.o\ + ../../common/ee_prom.o\ + ../../chips/rt28xx.o + +ifeq ($(HAS_ATE),y) +$(MOD_NAME)-objs += \ + ../../ate/chips/rt28xx_ate.o\ + ../../ate/common/ate_pci.o +endif + +ifeq ($(OSABL),NO) +$(MOD_NAME)-objs += \ + ../../os/linux/rt_pci_rbus.o\ + ../../os/linux/rt_rbus_pci_util.o\ + ../../os/linux/pci_main_dev.o +endif +endif +#endif // RT2860 // + + + + +#ifdef RT2880 +ifneq ($(findstring 2880,$(CHIPSET)),) +$(MOD_NAME)-objs += \ + ../../common/cmm_mac_pci.o\ + ../../common/cmm_data_pci.o\ + ../../os/linux/rt_rbus_pci_drv.o\ + ../../common/ee_flash.o\ + ../../common/rtmp_swmcu.o\ + ../../chips/rt2880.o + +ifeq ($(HAS_ATE),y) +$(MOD_NAME)-objs += \ + ../../ate/chips/rt28xx_ate.o\ + ../../ate/common/ate_pci.o +endif + +ifeq ($(OSABL),NO) +$(MOD_NAME)-objs += \ + ../../os/linux/rt_pci_rbus.o\ + ../../os/linux/rt_rbus_pci_util.o\ + ../../os/linux/pci_main_dev.o +endif + +endif +#endif // RT2880 // + +#ifdef RT3052 +ifneq ($(findstring 3052,$(CHIPSET)),) +$(MOD_NAME)-objs += \ + ../../common/cmm_mac_pci.o\ + ../../common/cmm_data_pci.o\ + ../../common/ee_flash.o\ + ../../common/rtmp_swmcu.o\ + ../../common/rt_rf.o\ + ../../chips/rt305x.o + +ifeq ($(HAS_ATE),y) +$(MOD_NAME)-objs += \ + ../../ate/chips/rt305x_ate.o\ + ../../ate/common/ate_pci.o +endif + +ifeq ($(OSABL),NO) +$(MOD_NAME)-objs += \ + ../../os/linux/rt_pci_rbus.o\ + ../../os/linux/rt_proc.o\ + ../../os/linux/rt_rbus_pci_util.o\ + ../../os/linux/rt_rbus_pci_drv.o\ + ../../os/linux/rbus_main_dev.o +endif + +endif +#endif // RT3052 // + +#ifdef RT3352 +ifneq ($(findstring 3352,$(CHIPSET)),) +$(MOD_NAME)-objs += \ + ../../common/cmm_mac_pci.o\ + ../../common/cmm_data_pci.o\ + ../../common/ee_flash.o\ + ../../common/rtmp_swmcu.o\ + ../../common/rt_rf.o\ + ../../chips/rt305x.o\ + ../../chips/rt3352.o + +ifeq ($(HAS_ATE),y) +$(MOD_NAME)-objs += \ + ../../ate/chips/rt305x_ate.o\ + ../../ate/chips/rt3352_ate.o + ../../ate/common/ate_pci.o +endif + +ifeq ($(OSABL),NO) +$(MOD_NAME)-objs += \ + ../../os/linux/rt_pci_rbus.o\ + ../../os/linux/rt_proc.o\ + ../../os/linux/rt_rbus_pci_util.o\ + ../../os/linux/rt_rbus_pci_drv.o\ + ../../os/linux/rbus_main_dev.o +endif + +endif +#endif // RT3352 // + + +#ifdef RT5350 +ifneq ($(findstring 5350,$(CHIPSET)),) +$(MOD_NAME)-objs += \ + ../../common/cmm_mac_pci.o\ + ../../common/cmm_data_pci.o\ + ../../common/ee_flash.o\ + ../../common/rtmp_swmcu.o\ + ../../common/rt_rf.o\ + ../../chips/rt305x.o\ + ../../chips/rt5350.o + +ifeq ($(OSABL),NO) +$(MOD_NAME)-objs += \ + ../../os/linux/rt_pci_rbus.o\ + ../../os/linux/rt_proc.o\ + ../../os/linux/rt_rbus_pci_util.o\ + ../../os/linux/rt_rbus_pci_drv.o\ + ../../os/linux/rbus_main_dev.o +endif + +ifneq ($(findstring $(RT28xx_MODE),STA APSTA),) +$(MOD_NAME)-objs += \ + ../../common/frq_cal.o +endif + +ifeq ($(HAS_ATE),y) +$(MOD_NAME)-objs += \ +#not need to include it yet. +# ../../ate/chips/rt305x_ate.o\ + ../../ate/chips/rt5350_ate.o\ + ../../ate/common/ate_pci.o +endif + +endif +#endif // RT5350 // + + + + + + + +#ifdef RTMP_MAC_PCI +#endif // RTMP_MAC_PCI // + + + + + + + +#ifdef RTMP_MAC_PCI +#endif //RTMP_MAC_PCI// + + +PHONY := clean install uninstall + +clean: + rm -f ../../common/*.o + rm -f ../../common/.*.{cmd,flags,d} + rm -f ../../os/linux/*.{o,ko,mod.{o,c}} + rm -f ../../os/linux/.*.{cmd,flags,d} + rm -fr ../../os/linux/.tmp_versions +#Must clean Module.symvers; or you will suffer symbol version not match +#when OS_ABL = YES. + rm -f ../../os/linux/Module.symvers + rm -f ../../os/linux/Modules.symvers + rm -f ../../os/linux/Module.markers + rm -f ../../os/linux/modules.order + rm -f ../../chips/*.o + rm -f ../../chips/.*.{cmd,flags,d} +ifeq ($(RT28xx_MODE),AP) + rm -f ../../ap/*.o + rm -f ../../ap/.*.{cmd,flags,d} +else +ifeq ($(RT28xx_MODE),STA) + rm -f ../../sta/*.o + rm -f ../../sta/.*.{cmd,flags,d} +else +ifeq ($(RT28xx_MODE),APSTA) + rm -f ../../ap/*.o + rm -f ../../ap/.*.{cmd,flags,d} + rm -f ../../sta/*.o + rm -f ../../sta/.*.{cmd,flags,d} +endif +endif +endif + +install: + rm -rf $(DAT_PATH) + $(shell [ ! -f /etc/Wireless ] && mkdir /etc/Wireless) + mkdir $(DAT_PATH) + cp $(RT28xx_DIR)/$(DAT_FILE_NAME) $(DAT_PATH)/. + install -d $(LINUX_SRC_MODULE) + install -m 644 -c $(addsuffix .ko,$(MOD_NAME)) $(LINUX_SRC_MODULE) + /sbin/depmod -a ${shell uname -r} + +uninstall: +# rm -rf $(DAT_PATH) + rm -rf $(addprefix $(LINUX_SRC_MODULE),$(addsuffix .ko,$(MOD_NAME))) + /sbin/depmod -a ${shell uname -r} + +# Declare the contents of the .PHONY variable as phony. We keep that +# information in a variable so we can use it in if_changed and friends. +.PHONY: $(PHONY) diff --git a/mt7620/src/os/linux/Makefile.6.netif b/mt7620/src/os/linux/Makefile.6.netif new file mode 100644 index 0000000..ce76b35 --- /dev/null +++ b/mt7620/src/os/linux/Makefile.6.netif @@ -0,0 +1,175 @@ +include $(RT28xx_DIR)/os/linux/config.mk + +#ifdef CONFIG_AP_SUPPORT +ifeq ($(RT28xx_MODE),AP) +MOD_NAME = rtnet$(MODULE)ap +endif +#endif // CONFIG_AP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT +ifeq ($(RT28xx_MODE), STA) +MOD_NAME = rtnet$(MODULE)sta +endif +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_APSTA_SUPPORT +ifeq ($(RT28xx_MODE), APSTA) +MOD_NAME = rtnet$(MODULE)apsta +endif +#endif // CONFIG_APSTA_SUPPORT // + +obj-m := $(MOD_NAME).o + +#ifdef CONFIG_AP_SUPPORT +ifeq ($(RT28xx_MODE),AP) +$(MOD_NAME)-objs := \ + ../../ap/ap_mbss_inf.o\ + ../../os/linux/ap_ioctl.o\ + ../../os/linux/rt_main_dev.o + +ifeq ($(HAS_CFG80211_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../os/linux/cfg80211.o +endif + +ifeq ($(HAS_WDS),y) +$(MOD_NAME)-objs += \ + ../../ap/ap_wds_inf.o +endif + +ifeq ($(HAS_APCLI),y) +$(MOD_NAME)-objs += \ + ../../ap/ap_apcli_inf.o +endif + +ifeq ($(HAS_MESH_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/mesh_inf.o +endif + +endif +#endif // CONFIG_AP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT +ifeq ($(RT28xx_MODE), STA) +$(MOD_NAME)-objs := \ + ../../os/linux/sta_ioctl.o\ + ../../os/linux/rt_main_dev.o + +ifeq ($(HAS_CFG80211_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../os/linux/cfg80211.o +endif + +ifeq ($(HAS_MESH_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/mesh_inf.o +endif + +ifeq ($(HAS_P2P_SUPPORT), y) +$(MOD_NAME)-objs += \ + ../../common/p2p_inf.o\ + ../../os/linux/ap_ioctl.o +endif + +endif +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_APSTA_SUPPORT +ifeq ($(RT28xx_MODE), APSTA) +$(MOD_NAME)-objs := \ + ../../ap/ap_mbss_inf.o\ + ../../common/p2p_inf.o\ + ../../os/linux/ap_ioctl.o\ + ../../os/linux/sta_ioctl.o\ + ../../os/linux/rt_main_dev.o + +ifeq ($(HAS_CFG80211_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../os/linux/cfg80211.o +endif + +ifeq ($(HAS_WDS),y) +$(MOD_NAME)-objs += \ + ../../ap/ap_wds_inf.o +endif + +ifeq ($(HAS_APCLI),y) +$(MOD_NAME)-objs += \ + ../../ap/ap_apcli_inf.o +endif + +ifeq ($(HAS_MESH_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../common/mesh_inf.o +endif + + +endif +#endif // CONFIG_APSTA_SUPPORT // + +#chip related +#ifdef RT2860 +ifneq ($(findstring 2860,$(CHIPSET)),) +$(MOD_NAME)-objs += \ + ../../os/linux/rt_pci_rbus.o\ + ../../os/linux/pci_main_dev.o +endif +#endif // RT2860 // + + + + + +#ifdef RT2880 +ifneq ($(findstring 2880,$(CHIPSET)),) +$(MOD_NAME)-objs += \ + ../../os/linux/rt_pci_rbus.o\ + ../../os/linux/pci_main_dev.o +endif +#endif // RT2880 // + + + + + + + +#ifdef RTMP_MAC_PCI +#endif // RTMP_MAC_PCI // + + + +#ifdef RTMP_MAC_PCI +#endif // RTMP_MAC_PCI // + +clean: + rm -f ../../common/*.o + rm -f ../../common/.*.{cmd,flags,d} + rm -f ../../os/linux/*.{o,ko,mod.{o,c}} + rm -f ../../os/linux/.*.{cmd,flags,d} + rm -fr ../../os/linux/.tmp_versions + rm -f ../../os/linux/Module.symvers + rm -f ../../os/linux/Modules.symvers + rm -f ../../os/linux/Module.markers + rm -f ../../os/linux/modules.order + rm -f ../../chips/*.o + rm -f ../../chips/.*.{cmd,flags,d} +ifeq ($(RT28xx_MODE),AP) + rm -f ../../ap/*.o + rm -f ../../ap/.*.{cmd,flags,d} +else +ifeq ($(RT28xx_MODE),STA) + rm -f ../../sta/*.o + rm -f ../../sta/.*.{cmd,flags,d} +endif +endif + +install: + install -d $(LINUX_SRC_MODULE) + install -m 644 -c $(addsuffix .ko,$(MOD_NAME)) $(LINUX_SRC_MODULE) + /sbin/depmod -a ${shell uname -r} + +uninstall: + rm -rf $(addprefix $(LINUX_SRC_MODULE),$(addsuffix .ko,$(MOD_NAME))) + /sbin/depmod -a ${shell uname -r} diff --git a/mt7620/src/os/linux/Makefile.6.util b/mt7620/src/os/linux/Makefile.6.util new file mode 100644 index 0000000..db97f8f --- /dev/null +++ b/mt7620/src/os/linux/Makefile.6.util @@ -0,0 +1,117 @@ +include $(RT28xx_DIR)/os/linux/config.mk + +#ifdef CONFIG_AP_SUPPORT +ifeq ($(RT28xx_MODE),AP) +MOD_NAME = rtutil$(MODULE)ap +endif +#endif // CONFIG_AP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT +ifeq ($(RT28xx_MODE), STA) +MOD_NAME = rtutil$(MODULE)sta +endif +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_APSTA_SUPPORT +ifeq ($(RT28xx_MODE), APSTA) +MOD_NAME = rtutil$(MODULE)apsta +endif +#endif // CONFIG_APSTA_SUPPORT // + +obj-m := $(MOD_NAME).o + +#ifdef CONFIG_AP_SUPPORT +ifeq ($(RT28xx_MODE),AP) +$(MOD_NAME)-objs := \ + ../../common/rt_os_util.o\ + ../../os/linux/rt_linux_symb.o\ + ../../os/linux/rt_rbus_pci_util.o\ + ../../os/linux/rt_usb_util.o\ + ../../os/linux/rt_linux.o + +ifeq ($(PLATFORM),BL2348) +$(MOD_NAME)-objs += \ + ../../os/linux/vr_bdlt.o +endif + +ifeq ($(PLATFORM),BLUBB) +$(MOD_NAME)-objs += \ + ../../os/linux/vr_bdlt.o +endif + +ifeq ($(HAS_BGFP_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../os/linux/br_ftph.o +endif +endif +#endif // CONFIG_AP_SUPPORT // + + +#ifdef CONFIG_STA_SUPPORT +ifeq ($(RT28xx_MODE), STA) +$(MOD_NAME)-objs := \ + ../../common/rt_os_util.o\ + ../../os/linux/rt_linux_symb.o\ + ../../os/linux/rt_rbus_pci_util.o\ + ../../os/linux/rt_usb_util.o\ + ../../os/linux/rt_linux.o +endif +#endif // CONFIG_STA_SUPPORT // + + +#ifdef CONFIG_APSTA_SUPPORT +ifeq ($(RT28xx_MODE), APSTA) +$(MOD_NAME)-objs := \ + ../../common/rt_os_util.o\ + ../../os/linux/rt_linux_symb.o\ + ../../os/linux/rt_rbus_pci_util.o\ + ../../os/linux/rt_usb_util.o\ + ../../os/linux/rt_linux.o + +ifeq ($(PLATFORM),BL2348) +$(MOD_NAME)-objs += \ + ../../os/linux/vr_bdlt.o +endif + +ifeq ($(PLATFORM),BLUBB) +$(MOD_NAME)-objs += \ + ../../os/linux/vr_bdlt.o +endif + +ifeq ($(HAS_BGFP_SUPPORT),y) +$(MOD_NAME)-objs += \ + ../../os/linux/br_ftph.o +endif +endif +#endif // CONFIG_APSTA_SUPPORT // + +clean: + rm -f ../../common/*.o + rm -f ../../common/.*.{cmd,flags,d} + rm -f ../../os/linux/*.{o,ko,mod.{o,c}} + rm -f ../../os/linux/.*.{cmd,flags,d} + rm -fr ../../os/linux/.tmp_versions + rm -f ../../os/linux/Module.symvers + rm -f ../../os/linux/Modules.symvers + rm -f ../../os/linux/Module.markers + rm -f ../../os/linux/modules.order + rm -f ../../chips/*.o + rm -f ../../chips/.*.{cmd,flags,d} +ifeq ($(RT28xx_MODE),AP) + rm -f ../../ap/*.o + rm -f ../../ap/.*.{cmd,flags,d} +else +ifeq ($(RT28xx_MODE),STA) + rm -f ../../sta/*.o + rm -f ../../sta/.*.{cmd,flags,d} +endif +endif + +install: + install -d $(LINUX_SRC_MODULE) + install -m 644 -c $(addsuffix .ko,$(MOD_NAME)) $(LINUX_SRC_MODULE) + /sbin/depmod -a ${shell uname -r} + +uninstall: + rm -rf $(addprefix $(LINUX_SRC_MODULE),$(addsuffix .ko,$(MOD_NAME))) + /sbin/depmod -a ${shell uname -r} \ No newline at end of file diff --git a/mt7620/src/os/linux/Makefile.ap.soc b/mt7620/src/os/linux/Makefile.ap.soc new file mode 100755 index 0000000..b717d64 --- /dev/null +++ b/mt7620/src/os/linux/Makefile.ap.soc @@ -0,0 +1,406 @@ +ifeq ($(CONFIG_SUPPORT_OPENWRT),y) +EXTRA_CFLAGS = -I$(src)/../src/include -I$(src)/../src/ate/include +DRV_NAME = mt7620 +SRC_DIR = ../src +else +EXTRA_CFLAGS = -Idrivers/net/wireless/rt2860v2/include -Idrivers/net/wireless/rt2860v2/ate/include +DRV_NAME = rt2860v2_ap +SRC_DIR = $(SRC_DIR) +endif + +obj-$(CONFIG_RT2860V2_AP) += rt2860v2_ap.o + +$(DRV_NAME)-objs += $(SRC_DIR)/common/crypt_md5.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/crypt_sha2.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/crypt_hmac.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/crypt_aes.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/crypt_arc4.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/mlme.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_wep.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/action.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/ba_action.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_data.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/rtmp_init.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/rtmp_init_inf.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_tkip.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_aes.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_sync.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_sanity.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_info.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_cfg.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_wpa.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/dfs.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/dfs_mcu.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/spectrum.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/rtmp_timer.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/rt_channel.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_profile.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_asic.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_cmd.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/rtmp_swmcu.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/rt_os_util.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/eeprom.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/ee_flash.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_mac_pci.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_data_pci.o + +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rtmp_chip.o + +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_assoc.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_auth.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_connect.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_mlme.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_sanity.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_sync.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_wpa.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_data.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_uapsd.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_autoChSel.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_qload.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_cfg.o + +$(DRV_NAME)-objs += $(SRC_DIR)/os/linux/rt_proc.o +$(DRV_NAME)-objs += $(SRC_DIR)/os/linux/rt_linux.o +$(DRV_NAME)-objs += $(SRC_DIR)/os/linux/rt_profile.o +$(DRV_NAME)-objs += $(SRC_DIR)/os/linux/rt_main_dev.o +$(DRV_NAME)-objs += $(SRC_DIR)/os/linux/ap_ioctl.o +$(DRV_NAME)-objs += $(SRC_DIR)/os/linux/rt_pci_rbus.o +$(DRV_NAME)-objs += $(SRC_DIR)/os/linux/rt_rbus_pci_util.o +$(DRV_NAME)-objs += $(SRC_DIR)/os/linux/rt_rbus_pci_drv.o +$(DRV_NAME)-objs += $(SRC_DIR)/os/linux/rbus_main_dev.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/rt_ate.o + +ifeq ($(CONFIG_RT2860V2_AP_WMM_ACM),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/acm_edca.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/acm_comm.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/acm_iocl.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_LED),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/rt_led.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_WSC),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/wsc.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/wsc_tlv.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/crypt_dh.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/crypt_biginteger.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/wsc_ufd.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/wsc_v2.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_NINTENDO),y) +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_nintendo.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_WDS),y) +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_wds.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_wds_inf.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/client_wds.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_MBSS),y) +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_mbss.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_mbss_inf.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_APCLI),y) +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_apcli.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_apcli_inf.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/apcli_assoc.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/apcli_auth.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/apcli_ctrl.o +$(DRV_NAME)-objs += $(SRC_DIR)/ap/apcli_sync.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_mat.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_mat_iparp.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_mat_pppoe.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_mat_ipv6.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_IGMP_SNOOP),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/igmp_snoop.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_NETIF_BLOCK),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/netif_block.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_DLS),y) +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_dls.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_IDS),y) +$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_ids.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_MESH),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/mesh_bmpkt.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/mesh_ctrl.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/mesh_link_mng.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/mesh_sanity.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/mesh_tlv.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/mesh.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/mesh_inf.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/mesh_forwarding.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/mesh_path_mng.o +endif + +ifeq ($(CONFIG_RT2860V2_RT3XXX_AP_ANTENNA_DIVERSITY),y) +$(DRV_NAME)-objs += $(SRC_DIR)/os/linux/ap_diversity.o +endif + +ifeq ($(CONFIG_RT2860V2_AP_WAPI),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/wapi.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/wapi_crypt.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/wapi_sms4.o +endif + +#ifeq ($(CONFIG_RT2860V2_80211R_FT),y) +#$(DRV_NAME)-objs += $(SRC_DIR)/common/ft.o +#$(DRV_NAME)-objs += $(SRC_DIR)/common/ft_tlv.o +#$(DRV_NAME)-objs += $(SRC_DIR)/common/ft_ioctl.o +#$(DRV_NAME)-objs += $(SRC_DIR)/common/ft_rc.o +#$(DRV_NAME)-objs += $(SRC_DIR)/ap/ap_ftkd.o +#endif + +#ifeq ($(CONFIG_RT2860V2_80211K_RR),y) +#$(DRV_NAME)-objs += $(SRC_DIR)/common/rrm_tlv.o +#$(DRV_NAME)-objs += $(SRC_DIR)/common/rrm_sanity.o +#$(DRV_NAME)-objs += $(SRC_DIR)/common/rrm.o +#endif + +ifeq ($(CONFIG_RT2860V2_AP_VIDEO_TURBINE),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_video.o +endif + +ifeq ($(CONFIG_RALINK_RT2880),y) +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rt2880.o +endif + +ifeq ($(CONFIG_RALINK_RT3052),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/rt_rf.o +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rt305x.o +endif + +ifeq ($(CONFIG_RALINK_RT3352),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/rt_rf.o +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rt305x.o +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rt3352.o +endif + +ifeq ($(CONFIG_RT3x52),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/rt_rf.o +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rt305x.o +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rt3352.o +endif + +ifeq ($(CONFIG_RALINK_RT5350),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/rt_rf.o +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rt305x.o +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rt5350.o +endif + +ifeq ($(CONFIG_RALINK_RT3883),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/rt_rf.o +$(DRV_NAME)-objs += $(SRC_DIR)/chips/rt3883.o +ifeq ($(CONFIG_RT2860V2_AP_TXBF),y) +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_txbf.o +$(DRV_NAME)-objs += $(SRC_DIR)/common/cmm_txbf_cal.o +endif +endif + +################### +# CFLAGS +################## +EXTRA_CFLAGS += -DAGGREGATION_SUPPORT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT -DLINUX \ + -Wall -Wstrict-prototypes -Wno-trigraphs + +EXTRA_CFLAGS += -DCONFIG_AP_SUPPORT -DAP_SCAN_SUPPORT -DUAPSD_AP_SUPPORT -DRTMP_RBUS_SUPPORT -DRTMP_MAC_PCI +EXTRA_CFLAGS += -DDOT11_N_SUPPORT -DSTATS_COUNT_SUPPORT -DRELASE_EXCLUDE -DIAPP_SUPPORT -DDOT1X_SUPPORT +EXTRA_CFLAGS += -DRALINK_ATE -DRALINK_QA -DCONFIG_RT2880_ATE_CMD_NEW -DNEW_TXCONT -DNEW_TXCARRSUPP +EXTRA_CFLAGS += -DCONFIG_RA_NAT_NONE + +#provide busy time statistics for every TBTT */ +#EXTRA_CFLAGS += -DQLOAD_FUNC_BUSY_TIME_STATS + +# provide busy time alarm mechanism +# use the function to avoid to locate in some noise environments +#EXTRA_CFLAGS += -DQLOAD_FUNC_BUSY_TIME_ALARM + +ifeq ($(CONFIG_RALINK_RT2880),y) +EXTRA_CFLAGS += -DRT2880 +endif + +ifeq ($(CONFIG_RALINK_RT3052),y) +ifeq ($(CONFIG_RALINK_RT3350),y) +EXTRA_CFLAGS += -DRT3350 -DRT305x -DRTMP_RF_RW_SUPPORT +else +EXTRA_CFLAGS += -DRT3052 -DRT305x -DRTMP_RF_RW_SUPPORT +endif +endif + +ifeq ($(CONFIG_RALINK_RT3352),y) +EXTRA_CFLAGS += -DRT3352 -DRT305x -DRTMP_RF_RW_SUPPORT -DSPECIFIC_BCN_BUF_SUPPORT -DVCORECAL_SUPPORT +endif + +ifeq ($(CONFIG_RT3x52),y) +EXTRA_CFLAGS += -DRT3052 -DRT3352 -DRT305x -DRTMP_RF_RW_SUPPORT -DSPECIFIC_BCN_BUF_SUPPORT -DVCORECAL_SUPPORT +endif + +ifeq ($(CONFIG_RALINK_RT5350),y) +EXTRA_CFLAGS += -DRT5350 -DRT305x -DRTMP_RF_RW_SUPPORT -DSPECIFIC_BCN_BUF_SUPPORT -DVCORECAL_SUPPORT +endif + +ifeq ($(CONFIG_RALINK_RT3883),y) +EXTRA_CFLAGS += -DRT3883 -DDOT11N_SS3_SUPPORT -DA_BAND_SUPPORT -DRTMP_RF_RW_SUPPORT -DSPECIFIC_BCN_BUF_SUPPORT -DVCORECAL_SUPPORT +ifeq ($(CONFIG_RT2860V2_AP_TXBF),y) +EXTRA_CFLAGS += -DTXBF_SUPPORT +endif +EXTRA_CFLAGS += -DSTREAM_MODE_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_DLS),y) +EXTRA_CFLAGS += -DQOS_DLS_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_IDS),y) +EXTRA_CFLAGS += -DIDS_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_DFS),y) +EXTRA_CFLAGS += -DDFS_SUPPORT +EXTRA_CFLAGS += -DNEW_DFS +endif + +ifeq ($(CONFIG_RT2860V2_AP_CARRIER),y) +EXTRA_CFLAGS += -DCARRIER_DETECTION_SUPPORT +ifeq ($(CONFIG_RALINK_RT3052),y) +EXTRA_CFLAGS += -DTONE_RADAR_DETECT_SUPPORT +endif +endif + +ifeq ($(CONFIG_RT2860V2_AUTO_CH_SELECT_ENCANCE),y) +EXTRA_CFLAGS += -DAUTO_CH_SELECT_ENHANCE +endif + +ifeq ($(CONFIG_RT2860V2_80211N_DRAFT3),y) +EXTRA_CFLAGS += -DDOT11N_DRAFT3 +endif + +ifeq ($(CONFIG_SINGLE_SKU),y) +EXTRA_CFLAGS += -DSINGLE_SKU +endif + +ifeq ($(CONFIG_RT2860V2_SNMP),y) +EXTRA_CFLAGS += -DSNMP_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_MCAST_RATE_SPECIFIC),y) +EXTRA_CFLAGS += -DMCAST_RATE_SPECIFIC +endif + +ifeq ($(CONFIG_RT2860V2_AP_WMM_ACM),y) +EXTRA_CFLAGS += -DWMM_ACM_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_LED),y) +EXTRA_CFLAGS += -DLED_CONTROL_SUPPORT -DCONFIG_SWMCU_SUPPORT +ifeq ($(CONFIG_RT2860V2_AP_WSC),y) +EXTRA_CFLAGS += -DWSC_LED_SUPPORT +endif +endif + +ifeq ($(CONFIG_RT2860V2_AP_NINTENDO),y) +EXTRA_CFLAGS += -DNINTENDO_AP +endif + +ifeq ($(CONFIG_RT2860V2_AP_WSC),y) +EXTRA_CFLAGS += -DWSC_AP_SUPPORT -DWSC_V2_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_LLTD),y) +EXTRA_CFLAGS += -DLLTD_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_WDS),y) +EXTRA_CFLAGS += -DWDS_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_MBSS),y) +EXTRA_CFLAGS += -DMBSS_SUPPORT +endif + +ifeq ($(CONFIG_NEW_MBSSID_MODE),y) +EXTRA_CFLAGS += -DNEW_MBSSID_MODE +endif + +ifeq ($(CONFIG_RT2860V2_AP_APCLI),y) +EXTRA_CFLAGS += -DAPCLI_SUPPORT +EXTRA_CFLAGS += -DMAT_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_IGMP_SNOOP),y) +EXTRA_CFLAGS += -DIGMP_SNOOP_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_NETIF_BLOCK),y) +EXTRA_CFLAGS += -DBLOCK_NET_IF +endif + +ifeq ($(CONFIG_RT2860V2_AP_MESH),y) +EXTRA_CFLAGS += -DMESH_SUPPORT -DINTEL_CMPC +endif + +ifeq ($(CONFIG_RT2860V2_RT3XXX_AP_ANTENNA_DIVERSITY),y) +EXTRA_CFLAGS += -DRT3XXX_ANTENNA_DIVERSITY_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_HW_ANTENNA_DIVERSITY),y) +EXTRA_CFLAGS += -DHW_ANTENNA_DIVERSITY_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_THERMAL_PROTECT),y) +EXTRA_CFLAGS += -DTHERMAL_PROTECT_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_WAPI),y) +EXTRA_CFLAGS += -DWAPI_SUPPORT +ifeq ($(CONFIG_RALINK_RT3052),y) +EXTRA_CFLAGS += -DSOFT_ENCRYPT +endif +endif + +ifeq ($(CONFIG_RT2860V2_AP_COC),y) +EXTRA_CFLAGS += -DCOC_SUPPORT -DGREENAP_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_EXT_CHANNEL_LIST),y) +EXTRA_CFLAGS += -DEXT_BUILD_CHANNEL_LIST +endif + +ifeq ($(CONFIG_KTHREAD),y) +EXTRA_CFLAGS += -DKTHREAD_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_AP_MEMORY_OPTIMIZATION),y) +EXTRA_CFLAGS += -DMEMORY_OPTIMIZATION +else +EXTRA_CFLAGS += -DDBG +endif + +ifeq ($(CONFIG_RT2860V2_AP_VIDEO_TURBINE),y) +EXTRA_CFLAGS += -DVIDEO_TURBINE_SUPPORT +endif + +ifeq ($(CONFIG_RA_NETWORK_WORKQUEUE_BH),y) +EXTRA_CFLAGS += -DWORKQUEUE_BH +endif + +ifeq ($(CONFIG_RT2860V2_AP_RTMP_INTERNAL_TX_ALC),y) +EXTRA_CFLAGS += -DRTMP_INTERNAL_TX_ALC +endif + +#ifeq ($(CONFIG_RT2860V2_AP_INTELLIGENT_RATE_ADAPTION),y) +#EXTRA_CFLAGS += -DNEW_RATE_ADAPT_SUPPORT +#endif diff --git a/mt7620/src/os/linux/Makefile.ap.usb b/mt7620/src/os/linux/Makefile.ap.usb new file mode 100755 index 0000000..7adec8c --- /dev/null +++ b/mt7620/src/os/linux/Makefile.ap.usb @@ -0,0 +1,334 @@ +# In-Tree Makefile for USB combo +EXTRA_CFLAGS += -Idrivers/net/wireless/RT5572_ap/MODULE/include +EXTRA_CFLAGS += -Idrivers/net/wireless/RT5572_ap/UTIL/include +EXTRA_CFLAGS += -Idrivers/net/wireless/RT5572_ap/NETIF/include +EXTRA_CFLAGS += -Idrivers/net/wireless/RT5572_ap/MODULE/ate/include + +# UTIL module +obj-$(CONFIG_RTUSB_AP) += RT5572_ap_util.o +RT5572_ap_util-y += UTIL/common/rt_os_util.o +RT5572_ap_util-y += UTIL/os/linux/rt_linux_symb.o +RT5572_ap_util-y += UTIL/os/linux/rt_rbus_pci_util.o +RT5572_ap_util-y += UTIL/os/linux/rt_usb_util.o +RT5572_ap_util-y += UTIL/os/linux/rt_linux.o + +# MODULE module +obj-$(CONFIG_RTUSB_AP) += RT5572_ap.o +RT5572_ap-y += MODULE/common/crypt_md5.o +RT5572_ap-y += MODULE/common/crypt_sha2.o +RT5572_ap-y += MODULE/common/crypt_hmac.o +RT5572_ap-y += MODULE/common/crypt_aes.o +RT5572_ap-y += MODULE/common/crypt_arc4.o +RT5572_ap-y += MODULE/common/mlme.o +RT5572_ap-y += MODULE/common/cmm_wep.o +RT5572_ap-y += MODULE/common/action.o +RT5572_ap-y += MODULE/common/cmm_data.o +RT5572_ap-y += MODULE/common/rtmp_init.o +RT5572_ap-y += MODULE/common/rtmp_init_inf.o +RT5572_ap-y += MODULE/common/cmm_tkip.o +RT5572_ap-y += MODULE/common/cmm_aes.o +RT5572_ap-y += MODULE/common/cmm_sync.o +RT5572_ap-y += MODULE/common/eeprom.o +RT5572_ap-y += MODULE/common/cmm_sanity.o +RT5572_ap-y += MODULE/common/cmm_info.o +RT5572_ap-y += MODULE/common/cmm_cfg.o +RT5572_ap-y += MODULE/common/cmm_wpa.o +RT5572_ap-y += MODULE/common/cmm_radar.o +RT5572_ap-y += MODULE/common/spectrum.o +RT5572_ap-y += MODULE/common/rtmp_timer.o +RT5572_ap-y += MODULE/common/rt_channel.o +RT5572_ap-y += MODULE/common/cmm_profile.o +RT5572_ap-y += MODULE/common/cmm_asic.o +RT5572_ap-y += MODULE/common/cmm_cmd.o +RT5572_ap-y += MODULE/rate_ctrl/ra_ctrl.o +RT5572_ap-y += MODULE/rate_ctrl/alg_legacy.o +RT5572_ap-y += MODULE/rate_ctrl/alg_ags.o +RT5572_ap-y += MODULE/os/linux/rt_profile.o +RT5572_ap-y += MODULE/chips/rtmp_chip.o +RT5572_ap-y += MODULE/ap/ap.o +RT5572_ap-y += MODULE/ap/ap_assoc.o +RT5572_ap-y += MODULE/ap/ap_auth.o +RT5572_ap-y += MODULE/ap/ap_connect.o +RT5572_ap-y += MODULE/ap/ap_mlme.o +RT5572_ap-y += MODULE/ap/ap_sanity.o +RT5572_ap-y += MODULE/ap/ap_sync.o +RT5572_ap-y += MODULE/ap/ap_wpa.o +RT5572_ap-y += MODULE/ap/ap_data.o +RT5572_ap-y += MODULE/common/uapsd.o +RT5572_ap-y += MODULE/ap/ap_autoChSel.o +RT5572_ap-y += MODULE/ap/ap_qload.o +RT5572_ap-y += MODULE/ap/ap_cfg.o +RT5572_ap-y += MODULE/common/ba_action.o +RT5572_ap-y += MODULE/common/cmm_mac_usb.o +RT5572_ap-y += MODULE/common/rtusb_io.o +RT5572_ap-y += MODULE/common/rtusb_data.o +RT5572_ap-y += MODULE/common/cmm_data_usb.o +RT5572_ap-y += MODULE/common/rtmp_mcu.o +RT5572_ap-y += MODULE/common/rtusb_bulk.o +RT5572_ap-y += MODULE/os/linux/rt_usb.o +RT5572_ap-y += MODULE/common/ee_prom.o +RT5572_ap-y += MODULE/common/cmm_dfs.o +RT5572_ap-y += MODULE/common/cmm_cs.o +RT5572_ap-y += MODULE/common/ee_prom.o +RT5572_ap-y += MODULE/common/ee_efuse.o +RT5572_ap-y += MODULE/common/rt_rf.o +RT5572_ap-y += MODULE/os/linux/rt_symb.o +RT5572_ap-y += MODULE/common/rt_led.o + +# NET module +obj-$(CONFIG_RTUSB_AP) += RT5572_ap_net.o +RT5572_ap_net-y += NETIF/common/rtusb_dev_id.o +RT5572_ap_net-y += NETIF/os/linux/ap_ioctl.o +RT5572_ap_net-y += NETIF/os/linux/rt_main_dev.o +RT5572_ap_net-y += NETIF/os/linux/usb_main_dev.o + +# By feature +ifeq ($(CONFIG_RTUSB_AP_WSC),y) +RT5572_ap-y += MODULE/common/wsc.o +RT5572_ap-y += MODULE/common/wsc_tlv.o +RT5572_ap-y += MODULE/common/wsc_ufd.o +RT5572_ap-y += MODULE/common/crypt_biginteger.o +RT5572_ap-y += MODULE/common/crypt_dh.o +RT5572_ap-y += MODULE/common/wsc_v2.o +endif + +ifeq ($(CONFIG_RTUSB_WDS),y) +RT5572_ap-y += MODULE/ap/ap_wds.o +RT5572_ap-y += MODULE/common/client_wds.o +RT5572_ap_net-y += NETIF/ap/ap_wds_inf.o +endif + +ifeq ($(CONFIG_RTUSB_AP_MBSS),y) +RT5572_ap-y += MODULE/ap/ap_mbss.o +RT5572_ap_net-y += NETIF/ap/ap_mbss_inf.o +endif + +ifeq ($(CONFIG_RTUSB_APCLI),y) +RT5572_ap-y += MODULE/ap/ap_apcli.o +RT5572_ap-y += MODULE/ap/apcli_ctrl.o +RT5572_ap-y += MODULE/ap/apcli_sync.o +RT5572_ap-y += MODULE/ap/apcli_auth.o +RT5572_ap-y += MODULE/ap/apcli_assoc.o +RT5572_ap-y += MODULE/common/cmm_mat.o +RT5572_ap-y += MODULE/common/cmm_mat_iparp.o +RT5572_ap-y += MODULE/common/cmm_mat_pppoe.o +RT5572_ap-y += MODULE/common/cmm_mat_ipv6.o +RT5572_ap_net-y += NETIF/ap/ap_apcli_inf.o +endif + +ifeq ($(CONFIG_RTUSB_DFS),y) +RT5572_ap-y += MODULE/common/cmm_dfs.o +endif + +ifeq ($(CONFIG_RTUSB_CS),y) +RT5572_ap-y += MODULE/common/cmm_cs.o +endif + +ifeq ($(CONFIG_RTUSB_IGMP_SNOOP),y) +RT5572_ap-y += MODULE/common/igmp_snoop.o +endif + +ifeq ($(CONFIG_RTUSB_NETIF_BLOCK),y) +RT5572_ap-y += MODULE/common/netif_block.o +endif + +ifeq ($(CONFIG_RTUSB_DLS),y) +RT5572_ap-y += MODULE/ap/ap_dls.o +endif + +ifeq ($(CONFIG_RTUSB_IDS),y) +RT5572_ap-y += MODULE/ap/ap_ids.o +endif + +ifeq ($(CONFIG_RTUSB_AP_FLASH_SUPPORT),y) +RT5572_ap-y += MODULE/common/ee_flash.o +endif + +# WAPI +ifeq ($(CONFIG_RTUSB_AP_WAPI),y) +RT5572_ap-y += MODULE/common/wapi.o +RT5572_ap-y += MODULE/common/wapi_sms4.o +RT5572_ap-y += MODULE/common/wapi_crypt.o +endif + +# Chip related +ifeq ($(CONFIG_RT2870_AP),y) +RT5572_ap-y += MODULE/chips/rt28xx.o +endif + +ifeq ($(CONFIG_RT3572_AP),y) +RT5572_ap-y += MODULE/chips/rt28xx.o +RT5572_ap-y += MODULE/chips/rt30xx.o +RT5572_ap-y += MODULE/chips/rt35xx.o +endif + +ifeq ($(CONFIG_RT3573_AP),y) +RT5572_ap-y += MODULE/chips/rt28xx.o +RT5572_ap-y += MODULE/chips/rt30xx.o +RT5572_ap-y += MODULE/chips/rt35xx.o +RT5572_ap-y += MODULE/chips/rt3593.o +endif + +ifeq ($(CONFIG_RT5572_AP),y) +RT5572_ap-y += MODULE/chips/rt30xx.o +RT5572_ap-y += MODULE/chips/rt5592.o +endif + +# ATE +ifeq ($(CONFIG_RTUSB_AP_ATE),y) +RT5572_ap-y += MODULE/ate/common/rt_ate.o +RT5572_ap-y += MODULE/ate/common/ate_usb.o +endif + +ifeq ($(CONFIG_RT2870_AP_ATE),y) +RT5572_ap-y += MODULE/ate/chips/rt28xx_ate.o +endif + +ifeq ($(CONFIG_RT3572_AP_ATE),y) +RT5572_ap-y += MODULE/ate/chips/rt28xx_ate.o +RT5572_ap-y += MODULE/ate/chips/rt35xx_ate.o +endif + +ifeq ($(CONFIG_RT5572_AP_ATE),y) +RT5572_ap-y += MODULE/ate/chips/rt5592_ate.o +endif + +# QA tool +ifeq ($(CONFIG_RTUSB_AP_QA),y) +RT5572_ap-y += MODULE/ate/common/rt_qa.o +endif +################### +# CFLAGS +################### +EXTRA_CFLAGS += -DAGGREGATION_SUPPORT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT -DLINUX\ + -Wall -Wstrict-prototypes -Wno-trigraphs +EXTRA_CFLAGS += -DSYSTEM_LOG_SUPPORT -DKTHREAD_SUPPORT +EXTRA_CFLAGS += -DCONFIG_AP_SUPPORT -DUAPSD_SUPPORT -DIAPP_SUPPORT -DDBG\ + -DDOT1X_SUPPORT -DAP_SCAN_SUPPORT +EXTRA_CFLAGS += -DRTMP_MAC_USB -DRTMP_USB_SUPPORT +EXTRA_CFLAGS += -DSTATS_COUNT_SUPPORT -DDOT11_N_SUPPORT -DRTDEV_SUPPORT + + +ifeq ($(CONFIG_RTUSB_AP),m) +EXTRA_CFLAGS += -DOS_ABL_SUPPORT +EXTRA_CFLAGS += -DOS_ABL_FUNC_SUPPORT +EXTRA_CFLAGS += -DOS_ABL_OS_PCI_SUPPORT +EXTRA_CFLAGS += -DOS_ABL_OS_USB_SUPPORT +EXTRA_CFLAGS += -DOS_ABL_OS_AP_SUPPORT +endif + +ifeq ($(CONFIG_RTUSB_AP_WSC),y) +EXTRA_CFLAGS += -DWSC_AP_SUPPORT -DWSC_INCLUDED -DWSC_V2_SUPPORT +endif + +ifeq ($(CONFIG_RTUSB_WDS),y) +EXTRA_CFLAGS += -DWDS_SUPPORT +endif + +ifeq ($(CONFIG_RTUSB_MBSS),y) +EXTRA_CFLAGS += -DMBSS_SUPPORT +endif + +ifeq ($(CONFIG_RTUSB_APCLI),y) +EXTRA_CFLAGS += -DAPCLI_SUPPORT +EXTRA_CFLAGS += -DMAT_SUPPORT +EXTRA_CFLAGS += -DAP_SCAN_SUPPORT +endif + +ifeq ($(CONFIG_RTUSB_AP_DLS),y) +EXTRA_CFLAGS += -DQOS_DLS_SUPPORT +endif + +ifeq ($(CONFIG_RTUSB_IDS),y) +EXTRA_CFLAGS += -DIDS_SUPPORT +endif + +ifeq ($(CONFIG_RTUSB_AP_FLASH_SUPPORT), y) +EXTRA_CFLAGS += -DRTMP_FLASH_SUPPORT +endif + +ifeq ($(CONFIG_RTUSB_AP_80211N_DRAFT3),y) +EXTRA_CFLAGS += -DDOT11N_DRAFT3 +endif + +ifeq ($(CONFIG_RTUSB_LLTD),y) +EXTRA_CFLAGS += -DLLTD_SUPPORT +endif + +ifeq ($(CONFIG_RTUSB_IGMP_SNOOP),y) +EXTRA_CFLAGS += -DIGMP_SNOOP_SUPPORT +endif + +ifeq ($(CONFIG_RTUSB_NETIF_BLOCK),y) +EXTRA_CFLAGS += -DBLOCK_NET_IF +endif + +# Chip related +ifeq ($(CONFIG_RT2870_AP), y) +EXTRA_CFLAGS += -DRT2870 -DRT28xx -DRTMP_TIMER_TASK_SUPPORT -DA_BAND_SUPPORT + +ifeq ($(CONFIG_RTUSB_DFS), y) +EXTRA_CFLAGS += -DDFS_SOFTWARE_SUPPORT +endif + +endif + +ifeq ($(CONFIG_RT3572_AP), y) +EXTRA_CFLAGS += -DRT2870 -DRT28xx -DRT30xx -DRT35xx -DRT3572 -DRTMP_TIMER_TASK_SUPPORT -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT -DA_BAND_SUPPORT -DVCORECAL_SUPPORT + +ifeq ($(CONFIG_RTUSB_DFS), y) +EXTRA_CFLAGS += -DDFS_DEBUG +endif + +ifeq ($(CONFIG_RTUSB_CS_SUPPORT), y) +EXTRA_CFLAGS += -DCARRIER_DETECTION_FIRMWARE_SUPPORT +endif + +endif + +ifeq ($(CONFIG_RT3573_AP), y) +EXTRA_CFLAGS += -DRT30xx -DRT35xx -DRT3593 -DRT3573 -DA_BAND_SUPPORT -DDOT11N_SS3_SUPPORT -DVCORECAL_SUPPORT +endif + +ifeq ($(CONFIG_RT5572_AP), y) +EXTRA_CFLAGS += -DRT30xx -DRT5572 -DRT5592 -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT -DRTMP_TIMER_TASK_SUPPORT -DA_BAND_SUPPORT -DIQ_CAL_SUPPORT -DVCORECAL_SUPPORT -DRTMP_TEMPERATURE_COMPENSATION + +ifeq ($(CONFIG_RTUSB_DFS), y) +EXTRA_CFLAGS += -DDFS_SOFTWARE_SUPPORT -DDFS_HARDWARE_SUPPORT -DDFS_DEBUG +endif + +ifeq ($(CONFIG_RTUSB_CS_SUPPORT), y) +EXTRA_CFLAGS += -DCARRIER_DETECTION_FIRMWARE_SUPPORT +endif + +endif + +# ATE +ifeq ($(CONFIG_RTUSB_AP_ATE), y) +EXTRA_CFLAGS += -DRALINK_ATE -DCONFIG_RT2880_ATE_CMD_NEW +endif + +# QA +ifeq ($(CONFIG_RTUSB_AP_QA), y) +EXTRA_CFLAGS += -DRALINK_QA +endif + +# WAPI +ifeq ($(CONFIG_RTUSB_AP_WAPI), y) +EXTRA_CFLAGS += -DWAPI_SUPPORT -DSOFT_ENCRYPT -DEXPORT_SYMTAB +endif + +# NEW MBSS +ifeq ($(CONFIG_RTUSB_AP_NEW_MBSS_MODE), y) +EXTRA_CFLAGS += -DNEW_MBSSID_MODE +endif + +clean: + @rm -f common/*.o + @rm -f ap/*.o + @rm -f sta/*.o + @rm -f os/linux/*.o + @rm -f chips/*.o + @rm -f `find ./ -name *.o.cmd` + @rm -f *.ko + @rm -f *.o diff --git a/mt7620/src/os/linux/Makefile.clean b/mt7620/src/os/linux/Makefile.clean new file mode 100755 index 0000000..790a3ac --- /dev/null +++ b/mt7620/src/os/linux/Makefile.clean @@ -0,0 +1,59 @@ +include $(RT28xx_DIR)/os/linux/config.mk + +PHONY := clean install uninstall + +clean: + rm -f ../../common/*.o + rm -f ../../common/.*.o.cmd + rm -f ../../common/.*.{cmd,flags,d} + rm -f ../../os/linux/*.o + rm -f ../../os/linux/.*.o.cmd + rm -f ../../os/linux/*.{o,ko,mod.{o,c}} + rm -f ../../os/linux/.*.{cmd,flags,d} + rm -fr ../../os/linux/.tmp_versions +#Must clean Module.symvers; or you will suffer symbol version not match +#when OS_ABL = YES. + rm -f ../../os/linux/Module.symvers + rm -f ../../os/linux/Modules.symvers + rm -f ../../os/linux/Module.markers + rm -f ../../os/linux/modules.order + rm -f ../../chips/*.o + rm -f ../../chips/.*.o.cmd + rm -f ../../chips/.*.{cmd,flags,d} + rm -f ../../rate_ctrl/*.o + rm -f ../../rate_ctrl/.*.o.cmd + rm -f ../../rate_ctrl/.*.{cmd,flags,d} + rm -f ../../ate/common/*.o + rm -f ../../ate/common/.*.o.cmd + rm -f ../../ate/common/.*.{cmd,flags,d} + rm -f ../../ate/chips/*.o + rm -f ../../ate/chips/.*.o.cmd + rm -f ../../ate/chips/.*.{cmd,flags,d} +ifeq ($(RT28xx_MODE),AP) + rm -f ../../ap/*.o + rm -f ../../ap/.*.o.cmd + rm -f ../../ap/.*.{cmd,flags,d} +else +ifeq ($(RT28xx_MODE),STA) + rm -f ../../sta/*.o + rm -f ../../sta/.*.o.cmd + rm -f ../../sta/.*.{cmd,flags,d} +ifeq ($(HAS_P2P_SUPPORT),y) + rm -f ../../ap/*.o + rm -f ../../ap/.*.{cmd,flags,d} +endif +else +ifeq ($(RT28xx_MODE),APSTA) + rm -f ../../ap/*.o + rm -f ../../ap/.*.o.cmd + rm -f ../../ap/.*.{cmd,flags,d} + rm -f ../../sta/*.o + rm -f ../../sta/.*.o.cmd + rm -f ../../sta/.*.{cmd,flags,d} +endif +endif +endif + +# Declare the contents of the .PHONY variable as phony. We keep that +# information in a variable so we can use it in if_changed and friends. +.PHONY: $(PHONY) diff --git a/mt7620/src/os/linux/Makefile.libautoprovision.6 b/mt7620/src/os/linux/Makefile.libautoprovision.6 new file mode 100644 index 0000000..e285006 --- /dev/null +++ b/mt7620/src/os/linux/Makefile.libautoprovision.6 @@ -0,0 +1,9 @@ +include $(RT28xx_DIR)/os/linux/config.mk + +#ifdef CONFIG_AP_SUPPORT + +ifeq ($(HAS_SAMSUNG_EASY_CONFIG_SUPPORT),y) +lib-y := ../../common/auto_provision.o +endif + +#endif // CONFIG_AP_SUPPORT // diff --git a/mt7620/src/os/linux/Makefile.libwapi.4 b/mt7620/src/os/linux/Makefile.libwapi.4 new file mode 100644 index 0000000..51c5f95 --- /dev/null +++ b/mt7620/src/os/linux/Makefile.libwapi.4 @@ -0,0 +1,23 @@ +# +# Release file for AP Mode +# +include $(RT28xx_DIR)/os/linux/config.mk + +MOD_NAME = wapi_module + +OBJ := $(MOD_NAME).o + +WAPI_M_OBJ := \ + $(RT28xx_DIR)/common/wapi_sms4.o\ + $(RT28xx_DIR)/common/wapi_crypt.o + +PHONY := all + +all:$(OBJ) + +$(MOD_NAME).o: $(WAPI_M_OBJ) + $(LD) -r $^ -o $@ + +# Declare the contents of the .PHONY variable as phony. We keep that +# information in a variable so we can use it in if_changed and friends. +.PHONY: $(PHONY) \ No newline at end of file diff --git a/mt7620/src/os/linux/Makefile.libwapi.6 b/mt7620/src/os/linux/Makefile.libwapi.6 new file mode 100644 index 0000000..8ce3d92 --- /dev/null +++ b/mt7620/src/os/linux/Makefile.libwapi.6 @@ -0,0 +1,11 @@ +# +# Release file for AP Mode +# +include $(RT28xx_DIR)/os/linux/config.mk + +obj-m := wapi_module.o + +wapi_module-objs := \ + ../../common/wapi_sms4.o\ + ../../common/wapi_crypt.o + \ No newline at end of file diff --git a/mt7620/src/os/linux/Makefile.sta.soc b/mt7620/src/os/linux/Makefile.sta.soc new file mode 100755 index 0000000..74d8eb8 --- /dev/null +++ b/mt7620/src/os/linux/Makefile.sta.soc @@ -0,0 +1,275 @@ +EXTRA_CFLAGS = -Idrivers/net/wireless/rt2860v2/include -Idrivers/net/wireless/rt2860v2/ate/include + +obj-$(CONFIG_RT2860V2_STA) += rt2860v2_sta.o + +rt2860v2_sta-objs += ../rt2860v2/common/crypt_md5.o +rt2860v2_sta-objs += ../rt2860v2/common/crypt_sha2.o +rt2860v2_sta-objs += ../rt2860v2/common/crypt_hmac.o +rt2860v2_sta-objs += ../rt2860v2/common/mlme.o +rt2860v2_sta-objs += ../rt2860v2/common/cmm_wep.o +rt2860v2_sta-objs += ../rt2860v2/common/action.o +rt2860v2_sta-objs += ../rt2860v2/common/ba_action.o +rt2860v2_sta-objs += ../rt2860v2/common/cmm_data.o +rt2860v2_sta-objs += ../rt2860v2/common/rtmp_init.o +rt2860v2_sta-objs += ../rt2860v2/common/rtmp_init_inf.o +rt2860v2_sta-objs += ../rt2860v2/common/cmm_tkip.o +rt2860v2_sta-objs += ../rt2860v2/common/cmm_aes.o +rt2860v2_sta-objs += ../rt2860v2/common/cmm_sync.o +rt2860v2_sta-objs += ../rt2860v2/common/cmm_sanity.o +rt2860v2_sta-objs += ../rt2860v2/common/cmm_info.o +rt2860v2_sta-objs += ../rt2860v2/common/cmm_wpa.o +rt2860v2_sta-objs += ../rt2860v2/common/dfs.o +#rt2860v2_sta-objs += ../rt2860v2/common/dfs_mcu.o +rt2860v2_sta-objs += ../rt2860v2/common/spectrum.o +rt2860v2_sta-objs += ../rt2860v2/common/rt_os_util.o + +rt2860v2_sta-objs += ../rt2860v2/common/rtmp_timer.o +rt2860v2_sta-objs += ../rt2860v2/common/rt_channel.o +rt2860v2_sta-objs += ../rt2860v2/common/cmm_profile.o +rt2860v2_sta-objs += ../rt2860v2/common/cmm_asic.o +rt2860v2_sta-objs += ../rt2860v2/common/rtmp_swmcu.o +rt2860v2_sta-objs += ../rt2860v2/common/cmm_cfg.o +rt2860v2_sta-objs += ../rt2860v2/common/eeprom.o +rt2860v2_sta-objs += ../rt2860v2/common/ee_flash.o +#rt2860v2_sta-objs += ../rt2860v2/common/rtmp_mcu.o + +rt2860v2_sta-objs += ../rt2860v2/common/cmm_mac_pci.o +rt2860v2_sta-objs += ../rt2860v2/common/cmm_data_pci.o +rt2860v2_sta-objs += ../rt2860v2/common/crypt_aes.o +rt2860v2_sta-objs += ../rt2860v2/common/crypt_arc4.o +rt2860v2_sta-objs += ../rt2860v2/common/cmm_cmd.o +rt2860v2_sta-objs += ../rt2860v2/common/cmm_wpa_adhoc.o + +rt2860v2_sta-objs += ../rt2860v2/sta/assoc.o +rt2860v2_sta-objs += ../rt2860v2/sta/auth.o +rt2860v2_sta-objs += ../rt2860v2/sta/auth_rsp.o +rt2860v2_sta-objs += ../rt2860v2/sta/sync.o +rt2860v2_sta-objs += ../rt2860v2/sta/sanity.o +rt2860v2_sta-objs += ../rt2860v2/sta/rtmp_data.o +rt2860v2_sta-objs += ../rt2860v2/sta/connect.o +rt2860v2_sta-objs += ../rt2860v2/sta/wpa.o +rt2860v2_sta-objs += ../rt2860v2/sta/sta_cfg.o + +rt2860v2_sta-objs += ../rt2860v2/os/linux/rt_proc.o +rt2860v2_sta-objs += ../rt2860v2/os/linux/rt_linux.o +rt2860v2_sta-objs += ../rt2860v2/os/linux/rt_profile.o +rt2860v2_sta-objs += ../rt2860v2/os/linux/rt_main_dev.o +rt2860v2_sta-objs += ../rt2860v2/os/linux/sta_ioctl.o +rt2860v2_sta-objs += ../rt2860v2/common/rt_ate.o +rt2860v2_sta-objs += ../rt2860v2/chips/rtmp_chip.o + +rt2860v2_sta-objs += ../rt2860v2/os/linux/rbus_main_dev.o +rt2860v2_sta-objs += ../rt2860v2/os/linux/rt_pci_rbus.o +rt2860v2_sta-objs += ../rt2860v2/os/linux/rt_rbus_pci_util.o +rt2860v2_sta-objs += ../rt2860v2/os/linux/rt_rbus_pci_drv.o + +ifeq ($(CONFIG_RALINK_RT2880),y) +rt2860v2_sta-objs += ../rt2860v2/chips/rt2880.o +endif + +ifeq ($(CONFIG_RALINK_RT3052),y) +rt2860v2_sta-objs += ../rt2860v2/common/rt_rf.o +rt2860v2_sta-objs += ../rt2860v2/chips/rt305x.o +endif + +ifeq ($(CONFIG_RALINK_RT3352),y) +rt2860v2_sta-objs += ../rt2860v2/common/rt_rf.o +rt2860v2_sta-objs += ../rt2860v2/chips/rt305x.o +rt2860v2_sta-objs += ../rt2860v2/chips/rt3352.o +endif + +ifeq ($(CONFIG_RT3x52),y) +rt2860v2_sta-objs += ../rt2860v2/common/rt_rf.o +rt2860v2_sta-objs += ../rt2860v2/chips/rt305x.o +rt2860v2_sta-objs += ../rt2860v2/chips/rt3352.o +endif + +ifeq ($(CONFIG_RALINK_RT5350),y) +rt2860v2_sta-objs += ../rt2860v2/common/rt_rf.o +rt2860v2_sta-objs += ../rt2860v2/chips/rt305x.o +rt2860v2_sta-objs += ../rt2860v2/chips/rt5350.o +endif + +ifeq ($(CONFIG_RALINK_RT3883),y) +rt2860v2_ap-objs += ../rt2860v2/common/rt_rf.o +rt2860v2_ap-objs += ../rt2860v2/chips/rt3883.o +ifeq ($(CONFIG_RT2860V2_STA_TXBF),y) +rt2860v2_ap-objs += ../rt2860v2/common/cmm_txbf.o +rt2860v2_ap-objs += ../rt2860v2/common/cmm_txbf_cal.o +endif +endif + +ifeq ($(CONFIG_RT2860V2_STA_LED),y) +rt2860v2_sta-objs += ../rt2860v2/common/rt_led.o +endif + +ifeq ($(CONFIG_RT2860V2_STA_WMM_ACM),y) +rt2860v2_sta-objs += ../rt2860v2/common/acm_edca.o +rt2860v2_sta-objs += ../rt2860v2/common/acm_comm.o +rt2860v2_sta-objs += ../rt2860v2/common/acm_iocl.o +endif + +#ifeq ($(CONFIG_RT2860V2_STA_WAPI),y) +#rt2860v2_sta-objs += wapi.obj +#rt2860v2_sta-objs += wapi_sms4.obj +#rt2860v2_sta-objs += wapi_crypt.obj +#endif + +#ifeq ($(CONFIG_RT2860V2_RT3XXX_STA_ANTENNA_DIVERSITY),y) +#rt2860v2_sta-objs += ../rt2860v2/os/linux/ap_diversity.o +#endif + +ifeq ($(CONFIG_RT2860V2_STA_MESH),y) +rt2860v2_sta-objs += ../rt2860v2/common/mesh_bmpkt.o +rt2860v2_sta-objs += ../rt2860v2/common/mesh_ctrl.o +rt2860v2_sta-objs += ../rt2860v2/common/mesh_link_mng.o +rt2860v2_sta-objs += ../rt2860v2/common/mesh_sanity.o +rt2860v2_sta-objs += ../rt2860v2/common/mesh_tlv.o +rt2860v2_sta-objs += ../rt2860v2/common/mesh.o +rt2860v2_sta-objs += ../rt2860v2/common/mesh_inf.o +rt2860v2_sta-objs += ../rt2860v2/common/mesh_forwarding.o +rt2860v2_sta-objs += ../rt2860v2/common/mesh_path_mng.o +endif + +ifeq ($(CONFIG_RT2860V2_STA_DLS),y) +rt2860v2_sta-objs += ../rt2860v2/sta/dls.o +endif + +ifeq ($(CONFIG_RT2860V2_STA_WSC),y) +rt2860v2_sta-objs += ../rt2860v2/common/wsc.o +rt2860v2_sta-objs += ../rt2860v2/common/wsc_tlv.o +rt2860v2_sta-objs += ../rt2860v2/common/crypt_biginteger.o +rt2860v2_sta-objs += ../rt2860v2/common/crypt_dh.o +endif + +ifeq ($(CONFIG_RT2860V2_STA_ETH_CONVERT),y) +rt2860v2_sta-objs += ../rt2860v2/common/cmm_mat.o +rt2860v2_sta-objs += ../rt2860v2/common/cmm_mat_iparp.o +rt2860v2_sta-objs += ../rt2860v2/common/cmm_mat_pppoe.o +rt2860v2_sta-objs += ../rt2860v2/common/cmm_mat_ipv6.o +endif + +ifeq ($(CONFIG_RT2860V2_STA_VIDEO_TURBINE),y) +rt2860v2_sta-objs += ../rt2860v2/common/cmm_video.o +endif + +################### +# CFLAGS +################## +EXTRA_CFLAGS += -DAGGREGATION_SUPPORT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT -DLINUX \ + -Wall -Wstrict-prototypes -Wno-trigraphs + +EXTRA_CFLAGS += -DCONFIG_STA_SUPPORT -DDBG -DRTMP_RBUS_SUPPORT -DRTMP_MAC_PCI +EXTRA_CFLAGS += -DDOT11_N_SUPPORT -DSTATS_COUNT_SUPPORT -DRELASE_EXCLUDE +EXTRA_CFLAGS += -DRALINK_ATE -DRALINK_QA -DNEW_TXCONT -DNEW_TXCARRSUPP -DCONFIG_RT2880_ATE_CMD_NEW + +ifeq ($(CONFIG_RALINK_RT2880),y) +EXTRA_CFLAGS += -DRT2880 +endif + +ifeq ($(CONFIG_RALINK_RT3052),y) +ifeq ($(CONFIG_RALINK_RT3350),y) +EXTRA_CFLAGS += -DRT3350 -DRT305x -DRTMP_RF_RW_SUPPORT +else +EXTRA_CFLAGS += -DRT3052 -DRT305x -DRTMP_RF_RW_SUPPORT +endif +endif + +ifeq ($(CONFIG_RALINK_RT3352),y) +EXTRA_CFLAGS += -DRT3352 -DRT305x -DRTMP_RF_RW_SUPPORT -DSPECIFIC_BCN_BUF_SUPPORT -DVCORECAL_SUPPORT +endif + +ifeq ($(CONFIG_RT3x52),y) +EXTRA_CFLAGS += -DRT3052 -DRT3352 -DRT305x -DRTMP_RF_RW_SUPPORT -DSPECIFIC_BCN_BUF_SUPPORT -DVCORECAL_SUPPORT +endif + +ifeq ($(CONFIG_RALINK_RT5350),y) +EXTRA_CFLAGS += -DRT5350 -DRT305x -DRTMP_RF_RW_SUPPORT -DVCORECAL_SUPPORT +endif + +ifeq ($(CONFIG_RALINK_RT3883),y) +EXTRA_CFLAGS += -DRT3883 -DDOT11N_SS3_SUPPORT -DA_BAND_SUPPORT -DRTMP_RF_RW_SUPPORT -DSPECIFIC_BCN_BUF_SUPPORT -DVCORECAL_SUPPORT +ifeq ($(CONFIG_RT2860V2_AP_TXBF),y) +EXTRA_CFLAGS += -DTXBF_SUPPORT +endif +EXTRA_CFLAGS += -DSTREAM_MODE_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_STA_WPA_SUPPLICANT),y) +EXTRA_CFLAGS += -DWPA_SUPPLICANT_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_STA_WMM_ACM),y) +EXTRA_CFLAGS += -DWMM_ACM_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_STA_LED),y) +EXTRA_CFLAGS += -DLED_CONTROL_SUPPORT -DCONFIG_SWMCU_SUPPORT +ifeq ($(CONFIG_RT2860V2_STA_WSC),y) +EXTRA_CFLAGS += -DWSC_LED_SUPPORT +endif +endif + +ifeq ($(CONFIG_RT2860V2_SNMP),y) +EXTRA_CFLAGS += -DSNMP_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_STA_CARRIER),y) +EXTRA_CFLAGS += -DCARRIER_DETECTION_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_EXT_CHANNEL_LIST),y) +EXTRA_CFLAGS += -DEXT_BUILD_CHANNEL_LIST +endif + +ifeq ($(CONFIG_RT2860V2_STA_IDS),y) +EXTRA_CFLAGS += -DIDS_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_STA_DLS),y) +EXTRA_CFLAGS += -DQOS_DLS_SUPPORT +endif + +#ifeq ($(CONFIG_RT2860V2_STA_WAPI),y) +#EXTRA_CFLAGS += -DWAPI_SUPPORT +#ifeq ($(CONFIG_RALINK_RT3052),y) +#EXTRA_CFLAGS += -DWAPI_SUPPORT -DSOFT_ENCRYPT +#endif +#endif + +ifeq ($(CONFIG_RT2860V2_STA_MESH),y) +EXTRA_CFLAGS += -DMESH_SUPPORT -DINTEL_CMPC +endif + +ifeq ($(CONFIG_RT2860V2_RT3XXX_STA_ANTENNA_DIVERSITY),y) +EXTRA_CFLAGS += -DRT3XXX_ANTENNA_DIVERSITY_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_HW_STA_ANTENNA_DIVERSITY),y) +EXTRA_CFLAGS += -DHW_ANTENNA_DIVERSITY_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_STA_WSC),y) +EXTRA_CFLAGS += -DWSC_STA_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_STA_ETH_CONVERT),y) +EXTRA_CFLAGS += -DETH_CONVERT_SUPPORT -DMAT_SUPPORT +endif + +ifeq ($(CONFIG_RT2860V2_STA_VIDEO_TURBINE),y) +EXTRA_CFLAGS += -DVIDEO_TURBINE_SUPPORT +endif + +ifeq ($(CONFIG_RA_NETWORK_WORKQUEUE_BH),y) +EXTRA_CFLAGS += -DWORKQUEUE_BH +endif + +ifeq ($(CONFIG_RT2860V2_STA_RTMP_INTERNAL_TX_ALC),y) +EXTRA_CFLAGS += -DRTMP_INTERNAL_TX_ALC +endif + +ifeq ($(CONFIG_RT2860V2_STA_80211N_DRAFT3),y) +EXTRA_CFLAGS += -DDOT11N_DRAFT3 +endif + diff --git a/mt7620/src/os/linux/ap_ioctl.c b/mt7620/src/os/linux/ap_ioctl.c new file mode 100644 index 0000000..de8ca3b --- /dev/null +++ b/mt7620/src/os/linux/ap_ioctl.c @@ -0,0 +1,445 @@ +/**************************************************************************** + * 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, + IW_PRIV_TYPE_CHAR | 1024, 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 + { RTPRIV_IOCTL_SET_WSCOOB, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024 , + "set_wsc_oob"}, +{ 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"}, +#ifdef DBG +{ 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 /* DBG */ + +#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( + IN struct net_device *net_dev, + IN OUT struct ifreq *rq, + IN 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; /*, index; */ +/* POS_COOKIE pObj; */ + INT apidx=0; + UINT32 org_len; + RT_CMD_AP_IOCTL_CONFIG IoctlConfig, *pIoctlConfig = &IoctlConfig; + + GET_PAD_FROM_NET_DEV(pAd, net_dev); +/* pObj = (POS_COOKIE) pAd->OS_Cookie; */ + + 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; + + pIoctlConfig->Status = 0; + pIoctlConfig->net_dev = 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; + UINT32 len; + + /* 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 */ + len = 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(VERIFY_WRITE, 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(VERIFY_READ, 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(VERIFY_READ, wrqin->u.data.pointer, wrqin->u.data.length) == TRUE) + Status = RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_SHOW, 0, NULL, 0); + } + break; + +#ifdef INF_AR9 +#ifdef AR9_MAPI_SUPPORT + 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 /*AR9_MAPI_SUPPORT*/ +#endif /* INF_AR9 */ + +#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; + +#ifdef DBG + 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 /* DBG */ + + 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/mt7620/src/os/linux/br_ftph.c b/mt7620/src/os/linux/br_ftph.c new file mode 100644 index 0000000..2cc7e0a --- /dev/null +++ b/mt7620/src/os/linux/br_ftph.c @@ -0,0 +1,195 @@ +/**************************************************************************** + * 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( + IN 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; +} /* End of BG_FTPH_Init */ + + +/* +======================================================================== +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/mt7620/src/os/linux/cfg80211.c b/mt7620/src/os/linux/cfg80211.c new file mode 100644 index 0000000..454d033 --- /dev/null +++ b/mt7620/src/os/linux/cfg80211.c @@ -0,0 +1,1968 @@ +/**************************************************************************** + * 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. + +***************************************************************************/ + + +/* #include "rt_config.h" */ +#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 + +/* 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, + .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, +}; + + + +/* + 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 */ + + + + +/* =========================== Private Function ============================== */ + +/* 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; \ + } \ + } + +/* +======================================================================== +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_ERROR, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + + /* get channel number */ + ChanId = ieee80211_frequency_to_channel(pChan->center_freq); + CFG80211DBG(RT_DEBUG_ERROR, ("80211> Channel = %d\n", ChanId)); + CFG80211DBG(RT_DEBUG_ERROR, ("80211> ChannelType = %d\n", 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; + } + + if (p80211CB->pCfg80211_Wdev->iftype == NL80211_IFTYPE_STATION) + ChanInfo.IfType = RT_CMD_80211_IFTYPE_STATION; + else if (p80211CB->pCfg80211_Wdev->iftype == NL80211_IFTYPE_ADHOC) + ChanInfo.IfType = RT_CMD_80211_IFTYPE_ADHOC; + else if (p80211CB->pCfg80211_Wdev->iftype == NL80211_IFTYPE_MONITOR) + ChanInfo.IfType = RT_CMD_80211_IFTYPE_MONITOR; + + 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; +} /* End of CFG80211_OpsChannelSet */ + + +/* +======================================================================== +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; + UINT32 Filter; + + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> Type = %d\n", Type)); + + /* sanity check */ +#ifdef CONFIG_STA_SUPPORT + if ((Type != NL80211_IFTYPE_ADHOC) && + (Type != NL80211_IFTYPE_STATION) && + (Type != NL80211_IFTYPE_MONITOR)) +#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; + /* End of if */ + + pNetDev->ieee80211_ptr->iftype = Type; + + if (pFlags != NULL) + { + Filter = 0; + + if (((*pFlags) & NL80211_MNTR_FLAG_FCSFAIL) == NL80211_MNTR_FLAG_FCSFAIL) + Filter |= RT_CMD_80211_FILTER_FCSFAIL; + + if (((*pFlags) & NL80211_MNTR_FLAG_FCSFAIL) == NL80211_MNTR_FLAG_PLCPFAIL) + Filter |= RT_CMD_80211_FILTER_PLCPFAIL; + + if (((*pFlags) & NL80211_MNTR_FLAG_CONTROL) == NL80211_MNTR_FLAG_CONTROL) + Filter |= RT_CMD_80211_FILTER_CONTROL; + + if (((*pFlags) & NL80211_MNTR_FLAG_CONTROL) == NL80211_MNTR_FLAG_OTHER_BSS) + Filter |= RT_CMD_80211_FILTER_OTHER_BSS; + } /* End of if */ + + RTMP_DRIVER_80211_VIF_SET(pAd, Filter, Type); + + RTMP_DRIVER_80211_CB_GET(pAd, &pCfg80211_CB); + pCfg80211_CB->MonFilterFlag = Filter; + return 0; +} /* End of CFG80211_OpsVirtualInfChg */ + + +#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 +/* +======================================================================== +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 +======================================================================== +*/ +static int CFG80211_OpsScan( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev, + IN struct cfg80211_scan_request *pRequest) +{ +#ifdef CONFIG_STA_SUPPORT + VOID *pAd; + CFG80211_CB *pCfg80211_CB; +#ifdef WPA_SUPPLICANT_SUPPORT + struct iw_scan_req IwReq; + union iwreq_data Wreq; +#endif /* WPA_SUPPLICANT_SUPPORT */ + + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + + /* sanity check */ + if ((pNdev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) && + (pNdev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)) + { + return -EOPNOTSUPP; + } /* End of if */ + + if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("80211> Network is down!\n")); + return -ENETDOWN; + } /* End of if */ + + if (RTMP_DRIVER_80211_SCAN(pAd) != NDIS_STATUS_SUCCESS) + return -EBUSY; /* scanning */ + /* End of if */ + + RTMP_DRIVER_80211_CB_GET(pAd, &pCfg80211_CB); + pCfg80211_CB->pCfg80211_ScanReq = pRequest; /* used in scan end */ + +#ifdef WPA_SUPPLICANT_SUPPORT + memset(&Wreq, 0, sizeof(Wreq)); + memset(&IwReq, 0, sizeof(IwReq)); + + if ((pRequest->ssids != NULL) && + (sizeof(pRequest->ssids->ssid) <= sizeof(IwReq.essid))) + { + /* use 1st SSID in the requested SSID list */ + IwReq.essid_len = pRequest->ssids->ssid_len; + memcpy(IwReq.essid, pRequest->ssids->ssid, sizeof(IwReq.essid)); + +#if WIRELESS_EXT > 17 + Wreq.data.flags |= IW_SCAN_THIS_ESSID; + Wreq.data.length = sizeof(struct iw_scan_req); +#endif /* WIRELESS_EXT */ + } + + rt_ioctl_siwscan(pNdev, NULL, &Wreq, (char *)&IwReq); +#else + + rt_ioctl_siwscan(pNdev, NULL, NULL, NULL); +#endif /* WPA_SUPPLICANT_SUPPORT */ + return 0; +#else + + return -EOPNOTSUPP; +#endif /* CONFIG_STA_SUPPORT */ +} /* End of CFG80211_OpsScan */ +#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; + CMD_RTPRIV_IOCTL_80211_IBSS IbssInfo; + + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> SSID = %s\n", + pParams->ssid)); + CFG80211DBG(RT_DEBUG_ERROR, ("80211> Beacon Interval = %d\n", + pParams->beacon_interval)); + + /* init */ + memset(&IbssInfo, 0, sizeof(IbssInfo)); + IbssInfo.BeaconInterval = pParams->beacon_interval; + IbssInfo.pSsid = pParams->ssid; + + /* ibss join */ + RTMP_DRIVER_80211_IBSS_JOIN(pAd, &IbssInfo); + + return 0; +} /* End of CFG80211_OpsIbssJoin */ + + +/* +======================================================================== +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_ERROR, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + + RTMP_DRIVER_80211_STA_LEAVE(pAd); + return 0; +} /* End of CFG80211_OpsIbssLeave */ +#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 - + TX_POWER_AUTOMATIC: the dbm parameter is ignored + TX_POWER_LIMITED: limit TX power by the dbm parameter + TX_POWER_FIXED: fix TX power to the dbm parameter +======================================================================== +*/ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)) +static int CFG80211_OpsTxPwrSet( + IN struct wiphy *pWiphy, + IN enum nl80211_tx_power_setting Type, + IN int dBm) +{ + CFG80211DBG(RT_DEBUG_ERROR, ("80211> %s ==>\n", __FUNCTION__)); + return -EOPNOTSUPP; +} /* End of CFG80211_OpsTxPwrSet */ + +#else +static int CFG80211_OpsTxPwrSet( + IN struct wiphy *pWiphy, + IN enum tx_power_setting Type, + IN int dBm) +{ + CFG80211DBG(RT_DEBUG_ERROR, ("80211> %s ==>\n", __FUNCTION__)); + return -EOPNOTSUPP; +} /* End of CFG80211_OpsTxPwrSet */ +#endif /* LINUX_VERSION_CODE */ + + +/* +======================================================================== +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, + IN int *pdBm) +{ + CFG80211DBG(RT_DEBUG_ERROR, ("80211> %s ==>\n", __FUNCTION__)); + return -EOPNOTSUPP; +} /* End of CFG80211_OpsTxPwrGet */ + + +/* +======================================================================== +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 FlgIsEnabled, + IN int Timeout) +{ + CFG80211DBG(RT_DEBUG_ERROR, ("80211> %s ==>\n", __FUNCTION__)); + return -EOPNOTSUPP; +} /* 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_ERROR, ("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; + /* End of if */ + if (StaInfo.TxRateFlags & RT_CMD_80211_TXRATE_SHORT_GI) + pSinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; + /* End of if */ + + pSinfo->txrate.mcs = StaInfo.TxRateMCS; + } + else + { + pSinfo->txrate.legacy = StaInfo.TxRateMCS; + } /* End of if */ + + 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; +} /* End of CFG80211_OpsStaGet */ + + +/* +======================================================================== +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; + /* End of if */ + + CFG80211DBG(RT_DEBUG_ERROR, ("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) +{ + CFG80211DBG(RT_DEBUG_ERROR, ("80211> %s ==>\n", __FUNCTION__)); + 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; + + + CFG80211DBG(RT_DEBUG_ERROR, ("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_ERROR, ("80211> KeyIdx = %d\n", KeyIdx)); + + if (pParams->key_len >= sizeof(KeyInfo.KeyBuf)) + return -EINVAL; + /* End of if */ + +#ifdef CONFIG_STA_SUPPORT + /* init */ + memset(&KeyInfo, 0, sizeof(KeyInfo)); + memcpy(KeyInfo.KeyBuf, pParams->key, pParams->key_len); + KeyInfo.KeyBuf[pParams->key_len] = 0x00; + + if ((pParams->cipher == WLAN_CIPHER_SUITE_WEP40) || + (pParams->cipher == WLAN_CIPHER_SUITE_WEP104)) + { + KeyInfo.KeyType = RT_CMD_80211_KEY_WEP; + } + else if ((pParams->cipher == WLAN_CIPHER_SUITE_TKIP) || + (pParams->cipher == WLAN_CIPHER_SUITE_CCMP)) + { + KeyInfo.KeyType = RT_CMD_80211_KEY_WPA; + } + else + return -ENOTSUPP; + + KeyInfo.KeyId = KeyIdx+1; + + /* add key */ + RTMP_DRIVER_80211_KEY_ADD(pAd, &KeyInfo); + return 0; +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + return -ENOTSUPP; +#endif /* CONFIG_AP_SUPPORT */ +} /* End of CFG80211_OpsKeyAdd */ + + +/* +======================================================================== +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_ERROR, ("80211> %s ==>\n", __FUNCTION__)); + return -ENOTSUPP; +} /* End of CFG80211_OpsKeyGet */ + + +/* +======================================================================== +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 */ +{ + CFG80211DBG(RT_DEBUG_ERROR, ("80211> %s ==>\n", __FUNCTION__)); + return -ENOTSUPP; +} /* End of CFG80211_OpsKeyDel */ + + +/* +======================================================================== +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_ERROR, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> KeyIdx = %d\n", KeyIdx)); + + RTMP_DRIVER_80211_KEY_DEFAULT_SET(pAd, KeyIdx); + return 0; +} /* End of CFG80211_OpsKeyDefaultSet */ + + +#ifdef CONFIG_STA_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. +======================================================================== +*/ +static int CFG80211_OpsConnect( + IN struct wiphy *pWiphy, + IN struct net_device *pNdev, + IN struct cfg80211_connect_params *pSme) +{ + 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 = NL80211_WPA_VERSION_2; + INT32 Chan = -1, Idx; + + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> %s ==>\n", __FUNCTION__)); + + /* init */ + MAC80211_PAD_GET(pAd, pWiphy); + + if (pChannel != NULL) + Chan = ieee80211_frequency_to_channel(pChannel->center_freq); + + Groupwise = pSme->crypto.cipher_group; + for(Idx=0; Idxcrypto.n_ciphers_pairwise; Idx++) + Pairwise |= pSme->crypto.ciphers_pairwise[Idx]; + /* End of for */ + + for(Idx=0; Idxcrypto.n_akm_suites; Idx++) + Keymgmt |= pSme->crypto.akm_suites[Idx]; + /* End of for */ + + WpaVersion = pSme->crypto.wpa_versions; + + memset(&ConnInfo, 0, sizeof(ConnInfo)); + if (WpaVersion & NL80211_WPA_VERSION_2) + ConnInfo.WpaVer = 2; + else if (WpaVersion & NL80211_WPA_VERSION_1) + ConnInfo.WpaVer = 1; + else + ConnInfo.WpaVer = 0; + + if (Keymgmt & WLAN_AKM_SUITE_8021X) + ConnInfo.FlgIs8021x = TRUE; + else + ConnInfo.FlgIs8021x = FALSE; + + if (pSme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) + ConnInfo.FlgIsAuthOpen = FALSE; + else + ConnInfo.FlgIsAuthOpen = TRUE; + + if (Pairwise & WLAN_CIPHER_SUITE_CCMP) + ConnInfo.PairwiseEncrypType |= RT_CMD_80211_CONN_ENCRYPT_CCMP; + else if (Pairwise & WLAN_CIPHER_SUITE_TKIP) + ConnInfo.PairwiseEncrypType |= RT_CMD_80211_CONN_ENCRYPT_TKIP; + else if ((Pairwise & WLAN_CIPHER_SUITE_WEP40) || + (Pairwise & WLAN_CIPHER_SUITE_WEP104)) + { + ConnInfo.PairwiseEncrypType |= RT_CMD_80211_CONN_ENCRYPT_WEP; + } + else + 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; + /* End of if */ + + ConnInfo.pKey = (UINT8 *)(pSme->key); + ConnInfo.KeyLen = pSme->key_len; + ConnInfo.pSsid = pSme->ssid; + ConnInfo.SsidLen = pSme->ssid_len; + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> SME %x\n", pSme->auth_type)); + + RTMP_DRIVER_80211_CONNECT(pAd, &ConnInfo); + 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) +{ + VOID *pAd; + + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> %s ==>\n", __FUNCTION__)); + CFG80211DBG(RT_DEBUG_ERROR, ("80211> ReasonCode = %d\n", ReasonCode)); + + MAC80211_PAD_GET(pAd, pWiphy); + + RTMP_DRIVER_80211_STA_LEAVE(pAd); + return 0; +} /* End of CFG80211_OpsDisconnect */ +#endif /* CONFIG_STA_SUPPORT */ +#endif /* LINUX_VERSION_CODE */ + + +#ifdef RFKILL_HW_SUPPORT +static int CFG80211_OpsRFKill( + IN struct wiphy *pWiphy) +{ + VOID *pAd; + BOOLEAN active; + + + 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; + + + 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; + /* End of if */ + + CFG80211DBG(RT_DEBUG_ERROR, ("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_ERROR, ("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_ERROR, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + + if ((pPmksa->bssid == NULL) || (pPmksa->pmkid == NULL)) + return -ENOENT; + /* End of if */ + + 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_ERROR, ("80211> %s ==>\n", __FUNCTION__)); + MAC80211_PAD_GET(pAd, pWiphy); + + if ((pPmksa->bssid == NULL) || (pPmksa->pmkid == NULL)) + return -ENOENT; + /* End of if */ + + 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_ERROR, ("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 */ + + + + +struct cfg80211_ops CFG80211_Ops = { + /* set channel for a given wireless interface */ + .set_channel = CFG80211_OpsChannelSet, + /* change type/configuration of virtual interface */ + .change_virtual_intf = CFG80211_OpsVirtualInfChg, + +#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)) + /* 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, + /* configure WLAN power management */ + .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 CONFIG_STA_SUPPORT + /* connect to the ESS with the specified parameters */ + .connect = CFG80211_OpsConnect, + /* disconnect from the BSS/ESS */ + .disconnect = CFG80211_OpsDisconnect, +#endif /* CONFIG_STA_SUPPORT */ +#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 = NULL, + /* cancel an on-going remain-on-channel operation */ + .cancel_remain_on_channel = NULL, +#if (LINUX_VERSION_CODE == KERNEL_VERSION(2,6,34)) + /* transmit an action frame */ + .action = NULL, +#endif /* LINUX_VERSION_CODE */ +#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 = NULL, +#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 */ +}; + + + + +/* =========================== Global Function ============================== */ + +/* +======================================================================== +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 */ + +#ifdef CONFIG_AP_SUPPORT + pWdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP); +#ifdef WDS_SUPPORT + pWdev->wiphy->interface_modes | = BIT(NL80211_IFTYPE_WDS); +#endif /* WDS_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + pWdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_MONITOR); +#endif /* CONFIG_STA_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; +#endif /* KERNEL_VERSION */ + +#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 (wiphy_register(pWdev->wiphy) < 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("80211> Register wiphy device fail!\n")); + goto LabelErrReg; + } /* End of if */ + + 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; + + + /* allocate MAC80211 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; + } /* End of if */ + + /* 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; + } /* End of if */ + + /* 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); + + 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_ERROR, + ("%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_ERROR, ("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/mt7620/src/os/linux/cfg80211drv.c b/mt7620/src/os/linux/cfg80211drv.c new file mode 100644 index 0000000..942e139 --- /dev/null +++ b/mt7620/src/os/linux/cfg80211drv.c @@ -0,0 +1,1265 @@ +/**************************************************************************** + * 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: + +***************************************************************************/ + +#ifdef RT_CFG80211_SUPPORT + +#include "rt_config.h" + +#define RT_CFG80211_DEBUG /* debug use */ +#define CFG80211CB (pAd->pCfg80211_CB) + +#ifdef RT_CFG80211_DEBUG +#define CFG80211DBG(__Flg, __pMsg) DBGPRINT(__Flg, __pMsg) +#else +#define CFG80211DBG(__Flg, __pMsg) +#endif /* RT_CFG80211_DEBUG */ + + + + +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, Data) != TRUE) + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_80211_SCAN: + CFG80211DRV_OpsScan(pAd); + break; + + case CMD_RTPRIV_IOCTL_80211_IBSS_JOIN: + CFG80211DRV_OpsJoinIbss(pAd, pData); + break; + + case CMD_RTPRIV_IOCTL_80211_STA_LEAVE: + CFG80211DRV_OpsLeave(pAd); + break; + + case CMD_RTPRIV_IOCTL_80211_STA_GET: + if (CFG80211DRV_StaGet(pAd, pData) != TRUE) + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_80211_KEY_ADD: + CFG80211DRV_KeyAdd(pAd, pData); + break; + + case CMD_RTPRIV_IOCTL_80211_KEY_DEFAULT_SET: +#ifdef CONFIG_STA_SUPPORT + pAd->StaCfg.DefaultKeyId = Data; /* base 0 */ +#endif /* CONFIG_STA_SUPPORT */ + break; + + case CMD_RTPRIV_IOCTL_80211_CONNECT_TO: + CFG80211DRV_Connect(pAd, pData); + break; + +#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 */ + + 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; + + default: + return NDIS_STATUS_FAILURE; + } + + return NDIS_STATUS_SUCCESS; +} + + +BOOLEAN CFG80211DRV_OpsSetChannel( + VOID *pAdOrg, + VOID *pData) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + CMD_RTPRIV_IOCTL_80211_CHAN *pChan; + UINT8 ChanId; + UINT8 IfType; + UINT8 ChannelType; + STRING ChStr[5] = { 0 }; +#ifdef DOT11_N_SUPPORT + UCHAR BW_Old; + BOOLEAN FlgIsChanged; +#endif /* DOT11_N_SUPPORT */ + + + /* init */ + pChan = (CMD_RTPRIV_IOCTL_80211_CHAN *)pData; + ChanId = pChan->ChanId; + IfType = pChan->IfType; + ChannelType = pChan->ChanType; + +#ifdef DOT11_N_SUPPORT + if (IfType != RT_CMD_80211_IFTYPE_MONITOR) + { + /* get channel BW */ + FlgIsChanged = FALSE; + BW_Old = pAd->CommonCfg.RegTransmitSetting.field.BW; + + /* set to new channel BW */ + if (ChannelType == RT_CMD_80211_CHANTYPE_HT20) + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + FlgIsChanged = TRUE; + } + else if ((ChannelType == RT_CMD_80211_CHANTYPE_HT40MINUS) || + (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; + FlgIsChanged = TRUE; + } /* End of if */ + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> New BW = %d\n", + pAd->CommonCfg.RegTransmitSetting.field.BW)); + + /* change HT/non-HT mode (do NOT change wireless mode here) */ + if (((ChannelType == RT_CMD_80211_CHANTYPE_NOHT) && + (pAd->CommonCfg.HT_Disable == 0)) || + ((ChannelType != RT_CMD_80211_CHANTYPE_NOHT) && + (pAd->CommonCfg.HT_Disable == 1))) + { + if (ChannelType == RT_CMD_80211_CHANTYPE_NOHT) + pAd->CommonCfg.HT_Disable = 1; + else + pAd->CommonCfg.HT_Disable = 0; + /* End of if */ + + FlgIsChanged = TRUE; + CFG80211DBG(RT_DEBUG_ERROR, ("80211> HT Disable = %d\n", + pAd->CommonCfg.HT_Disable)); + } /* End of if */ + } + else + { + /* for monitor mode */ + FlgIsChanged = TRUE; + pAd->CommonCfg.HT_Disable = 0; + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; + } /* End of if */ + + if (FlgIsChanged == TRUE) + SetCommonHT(pAd); + /* End of if */ +#endif /* DOT11_N_SUPPORT */ + + /* switch to the channel */ + sprintf(ChStr, "%d", ChanId); + if (Set_Channel_Proc(pAd, ChStr) == FALSE) + { + CFG80211DBG(RT_DEBUG_ERROR, ("80211> Change channel fail!\n")); + } /* End of if */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef DOT11_N_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. + */ + Set_SSID_Proc(pAd, (PSTRING)pAd->CommonCfg.Ssid); + } /* End of if */ +#endif /* DOT11_N_SUPPORT */ + + 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); + } /* End of if */ + + 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); + } /* End of if */ +#endif /* CONFIG_STA_SUPPORT */ + + return TRUE; +} + + +BOOLEAN CFG80211DRV_OpsChgVirtualInf( + VOID *pAdOrg, + VOID *pFlgFilter, + UINT8 IfType) +{ +#ifdef CONFIG_STA_SUPPORT + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + UINT32 FlgFilter = *(UINT32 *)pFlgFilter; + + + /* change type */ + if (IfType == RT_CMD_80211_IFTYPE_ADHOC) + Set_NetworkType_Proc(pAd, "Adhoc"); + else if (IfType == RT_CMD_80211_IFTYPE_STATION) + Set_NetworkType_Proc(pAd, "Infra"); + else if (IfType == RT_CMD_80211_IFTYPE_MONITOR) + { + /* set packet filter */ + Set_NetworkType_Proc(pAd, "Monitor"); + + if (FlgFilter != 0) + { + UINT32 Filter; + + + RTMP_IO_READ32(pAd, RX_FILTR_CFG, &Filter); + + if ((FlgFilter & RT_CMD_80211_FILTER_FCSFAIL) == \ + RT_CMD_80211_FILTER_FCSFAIL) + { + Filter = Filter & (~0x01); + } + else + Filter = Filter | 0x01; + /* End of if */ + + if ((FlgFilter & RT_CMD_80211_FILTER_PLCPFAIL) == \ + RT_CMD_80211_FILTER_PLCPFAIL) + { + Filter = Filter & (~0x02); + } + else + Filter = Filter | 0x02; + /* End of if */ + + if ((FlgFilter & RT_CMD_80211_FILTER_CONTROL) == \ + RT_CMD_80211_FILTER_CONTROL) + { + Filter = Filter & (~0xFF00); + } + else + Filter = Filter | 0xFF00; + /* End of if */ + + if ((FlgFilter & RT_CMD_80211_FILTER_OTHER_BSS) == \ + RT_CMD_80211_FILTER_OTHER_BSS) + { + Filter = Filter & (~0x08); + } + else + Filter = Filter | 0x08; + /* End of if */ + + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, Filter); + *(UINT32 *)pFlgFilter = Filter; + } /* End of if */ + + return TRUE; /* not need to set SSID */ + } /* End of if */ + + pAd->StaCfg.bAutoReconnect = TRUE; + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> SSID = %s\n", pAd->CommonCfg.Ssid)); + Set_SSID_Proc(pAd, (PSTRING)pAd->CommonCfg.Ssid); +#endif /* CONFIG_STA_SUPPORT */ + + return TRUE; +} + + +BOOLEAN CFG80211DRV_OpsScan( + VOID *pAdOrg) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + + + if (pAd->FlgCfg80211Scanning == TRUE) + return FALSE; /* scanning */ + /* End of if */ + + /* do scan */ + pAd->FlgCfg80211Scanning = TRUE; + 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->pSsid); +#endif /* CONFIG_STA_SUPPORT */ + return TRUE; +} + + +BOOLEAN CFG80211DRV_OpsLeave( + VOID *pAdOrg) +{ +#ifdef CONFIG_STA_SUPPORT + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + + + pAd->StaCfg.bAutoReconnect = FALSE; + pAd->FlgCfg80211Connecting = FALSE; + 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; + /* End of if */ + + /* fill tx rate */ + getRate(pEntry->HTPhyMode, &DataRate); + + 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; + /* End of if */ + if (pEntry->HTPhyMode.field.ShortGI) + pIbssInfo->TxRateFlags |= RT_CMD_80211_TXRATE_SHORT_GI; + /* End of if */ + + pIbssInfo->TxRateMCS = pEntry->HTPhyMode.field.MCS; + } + else + { + pIbssInfo->TxRateFlags = RT_CMD_80211_TXRATE_LEGACY; + pIbssInfo->TxRateMCS = DataRate*1000; /* unit: 100kbps */ + } /* End of if */ + + /* fill signal */ + RSSI = (pEntry->RssiSample.AvgRssi0 + + pEntry->RssiSample.AvgRssi1 + + pEntry->RssiSample.AvgRssi2) / 3; + 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 ((pAd->CommonCfg.PhyMode <= PHY_11G) || + (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM)) + { + PhyInfo.word = pAd->StaCfg.HTPhyMode.word; + } + else + PhyInfo.word = pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word; + /* End of if */ + + getRate(PhyInfo, &DataRate); + + if ((PhyInfo.field.MODE == MODE_HTMIX) || + (PhyInfo.field.MODE == MODE_HTGREENFIELD)) + { + if (PhyInfo.field.BW) + pIbssInfo->TxRateFlags |= RT_CMD_80211_TXRATE_BW_40; + /* End of if */ + if (PhyInfo.field.ShortGI) + pIbssInfo->TxRateFlags |= RT_CMD_80211_TXRATE_SHORT_GI; + /* End of if */ + + pIbssInfo->TxRateMCS = PhyInfo.field.MCS; + } + else + { + pIbssInfo->TxRateFlags = RT_CMD_80211_TXRATE_LEGACY; + pIbssInfo->TxRateMCS = DataRate*10; /* unit: 100kbps */ + } /* End of if */ + + /* fill signal */ + RSSI = (pAd->StaCfg.RssiSample.AvgRssi0 + + pAd->StaCfg.RssiSample.AvgRssi1 + + pAd->StaCfg.RssiSample.AvgRssi2) / 3; + pIbssInfo->Signal = RSSI; +} +#endif /* CONFIG_STA_SUPPORT */ + + return TRUE; +} + + +BOOLEAN CFG80211DRV_KeyAdd( + 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; + + if (pKeyInfo->KeyType == RT_CMD_80211_KEY_WEP) + { + switch(pKeyInfo->KeyId) + { + case 1: + default: + Set_Key1_Proc(pAd, (PSTRING)pKeyInfo->KeyBuf); + break; + + case 2: + Set_Key2_Proc(pAd, (PSTRING)pKeyInfo->KeyBuf); + break; + + case 3: + Set_Key3_Proc(pAd, (PSTRING)pKeyInfo->KeyBuf); + break; + + case 4: + Set_Key4_Proc(pAd, (PSTRING)pKeyInfo->KeyBuf); + break; + } /* End of switch */ + } + else + Set_WPAPSK_Proc(pAd, (PSTRING)pKeyInfo->KeyBuf); +#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]; + UINT32 SSIDLen; + + + pConnInfo = (CMD_RTPRIV_IOCTL_80211_CONNECT *)pData; + + /* change to infrastructure mode if we are in ADHOC mode */ + Set_NetworkType_Proc(pAd, "Infra"); + + /* set authentication mode */ + if (pConnInfo->WpaVer == 2) + { + if (pConnInfo->FlgIs8021x == TRUE) + Set_AuthMode_Proc(pAd, "WPA2"); + else + Set_AuthMode_Proc(pAd, "WPA2PSK"); + /* End of if */ + } + else if (pConnInfo->WpaVer == 1) + { + if (pConnInfo->FlgIs8021x == TRUE) + Set_AuthMode_Proc(pAd, "WPA"); + else + Set_AuthMode_Proc(pAd, "WPAPSK"); + /* End of if */ + } + else if (pConnInfo->FlgIsAuthOpen == FALSE) + Set_AuthMode_Proc(pAd, "SHARED"); + else + Set_AuthMode_Proc(pAd, "OPEN"); + /* End of if */ + + CFG80211DBG(RT_DEBUG_ERROR, + ("80211> AuthMode = %d\n", pAd->StaCfg.AuthMode)); + + /* set encryption mode */ + if (pConnInfo->PairwiseEncrypType & RT_CMD_80211_CONN_ENCRYPT_CCMP) + Set_EncrypType_Proc(pAd, "AES"); + else if (pConnInfo->PairwiseEncrypType & RT_CMD_80211_CONN_ENCRYPT_TKIP) + Set_EncrypType_Proc(pAd, "TKIP"); + else if (pConnInfo->PairwiseEncrypType & RT_CMD_80211_CONN_ENCRYPT_WEP) + { + Set_EncrypType_Proc(pAd, "WEP"); + } + else if (pConnInfo->GroupwiseEncrypType & RT_CMD_80211_CONN_ENCRYPT_CCMP) + Set_EncrypType_Proc(pAd, "AES"); + else if (pConnInfo->GroupwiseEncrypType & RT_CMD_80211_CONN_ENCRYPT_TKIP) + Set_EncrypType_Proc(pAd, "TKIP"); + else + Set_EncrypType_Proc(pAd, "NONE"); + /* End of if */ + + CFG80211DBG(RT_DEBUG_ERROR, + ("80211> EncrypType = %d\n", pAd->StaCfg.WepStatus)); + + /* 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_AuthMode_Proc(pAd, "SHARED"); + 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.DefaultKeyId = pConnInfo->KeyIdx; /* base 0 */ + if (pConnInfo->KeyLen >= sizeof(KeyBuf)) + return FALSE; + /* End of if */ + memcpy(KeyBuf, pConnInfo->pKey, pConnInfo->KeyLen); + KeyBuf[pConnInfo->KeyLen] = 0x00; + + CFG80211DBG(RT_DEBUG_ERROR, + ("80211> pAd->StaCfg.DefaultKeyId = %d\n", + pAd->StaCfg.DefaultKeyId)); + + switch(pConnInfo->KeyIdx) + { + case 1: + default: + Set_Key1_Proc(pAd, (PSTRING)KeyBuf); + break; + + case 2: + Set_Key2_Proc(pAd, (PSTRING)KeyBuf); + break; + + case 3: + Set_Key3_Proc(pAd, (PSTRING)KeyBuf); + break; + + case 4: + Set_Key4_Proc(pAd, (PSTRING)KeyBuf); + break; + } /* End of switch */ + } /* End of if */ + + /* TODO: We need to provide a command to set BSSID to associate a AP */ + + /* re-set SSID */ + pAd->StaCfg.bAutoReconnect = TRUE; + pAd->FlgCfg80211Connecting = TRUE; + + SSIDLen = pConnInfo->SsidLen; + if (SSIDLen > NDIS_802_11_LENGTH_SSID) + SSIDLen = NDIS_802_11_LENGTH_SSID; + /* End of if */ + + memset(&SSID, 0, sizeof(SSID)); + memcpy(SSID, pConnInfo->pSsid, SSIDLen); + Set_SSID_Proc(pAd, (PSTRING)SSID); + CFG80211DBG(RT_DEBUG_ERROR, ("80211> 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_Alpha2[0] = pRegInfo->Alpha2[0]; + pAd->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")); + } /* End of if */ +} + + +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->QloadLatestChannelBusyTimePri; + pSurveyInfo->ChannelTimeExtBusy = pAd->QloadLatestChannelBusyTimeSec; +#endif /* AP_QLOAD_SUPPORT */ +} + + +VOID CFG80211_UnRegister( + IN VOID *pAdOrg, + IN VOID *pNetDev) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; + + + /* sanity check */ + if (pAd->pCfg80211_CB == NULL) + return; + /* End of if */ + + CFG80211OS_UnRegister(pAd->pCfg80211_CB, pNetDev); + pAd->pCfg80211_CB = NULL; + pAd->CommonCfg.HT_Disable = 0; +} + + +/* +======================================================================== +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 */ + RTEnqueueInternalCmd(pAd, CMDTHREAD_REG_HINT_11D, + pVIE->data, pVIE->Length); + break; + } /* End of if */ + + LenEmt = pVIE->Length + 2; + + if (LenVIE <= LenEmt) + break; /* length is not enough */ + /* End of if */ + + pElement += LenEmt; + LenVIE -= LenEmt; + } /* End of while */ +} /* End of CFG80211_BeaconCountryRegionParse */ + + +/* +======================================================================== +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); +} /* End of CFG80211_RegHint */ + + +/* +======================================================================== +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); +} /* End of CFG80211_RegHint11D */ + + +/* +======================================================================== +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_ERROR, ("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 AUTO_CH_SELECT_ENHANCE +#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; + /* End of if */ + + 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_ERROR, + ("crda> find region %c%c, DFS Type %d\n", + pAlpha2[0], pAlpha2[1], DfsType)); + break; + } /* End of if */ + } /* End of for */ + } /* End of if */ + } /* End of if */ +#endif /* EXT_BUILD_CHANNEL_LIST */ +#endif /* AUTO_CH_SELECT_ENHANCE */ + + for(IdBand=0; IdBand<2; IdBand++) + { + if (((IdBand == 0) && (pBand24G == NULL)) || + ((IdBand == 1) && (pBand5G == NULL))) + { + continue; + } /* End of if */ + + if (IdBand == 0) + { + CFG80211DBG(RT_DEBUG_ERROR, ("crda> reset chan/power for 2.4GHz\n")); + } + else + { + CFG80211DBG(RT_DEBUG_ERROR, ("crda> reset chan/power for 5GHz\n")); + } /* End of if */ + + ChanNum = CFG80211OS_ChanNumGet(CFG80211CB, pWiphy, IdBand); + + for(IdChan=0; IdChanCommonCfg.PhyMode == PHY_11A) || + (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED)) + { + /* 5G-only mode */ + if (ChanId <= CFG80211_NUM_OF_CHAN_2GHZ) + continue; /* check next */ + /* End of if */ + } /* End of if */ + + if ((pAd->CommonCfg.PhyMode != PHY_11A) && + (pAd->CommonCfg.PhyMode != PHY_11ABG_MIXED) && + (pAd->CommonCfg.PhyMode != PHY_11AN_MIXED) && + (pAd->CommonCfg.PhyMode != PHY_11ABGN_MIXED) && + (pAd->CommonCfg.PhyMode != PHY_11AGN_MIXED)) + { + /* 2.5G-only mode */ + if (ChanId > CFG80211_NUM_OF_CHAN_2GHZ) + continue; /* check next */ + /* End of if */ + } /* End of if */ + + 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; + /* End of if */ + + /* keep DFS type */ + pAd->ChannelList[RecId].RegulatoryDomain = DfsType; + + /* re-set DFS info. */ + pAd->CommonCfg.RDDurRegion = DfsType; + + CFG80211DBG(RT_DEBUG_ERROR, + ("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; + } /* End of if */ + } /* End of for */ + } /* End of for */ + } /* End of for */ + + pAd->ChannelListNum = RecId; + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + + CFG80211DBG(RT_DEBUG_ERROR, ("crda> Number of channels = %d\n", RecId)); +} /* End of CFG80211_RegRuleApply */ + + +/* +======================================================================== +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; + + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> CFG80211_Scaning ==>\n")); + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("80211> Network is down!\n")); + return; + } /* End of if */ + + /* + In connect function, we also need to report BSS information to cfg80211; + Not only scan function. + */ + if ((pAd->FlgCfg80211Scanning == FALSE) && + (pAd->FlgCfg80211Connecting == FALSE)) + { + return; /* no scan is running */ + } /* End of if */ + + /* init */ + /* Note: Can not use local variable to do pChan */ + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + 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 */ +} /* End of CFG80211_Scaning */ + + +/* +======================================================================== +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; + } /* End of if */ + + if (pAd->FlgCfg80211Scanning == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("80211> No scan is running!\n")); + return; /* no scan is running */ + } /* End of if */ + + if (FlgIsAborted == TRUE) + FlgIsAborted = 1; + else + FlgIsAborted = 0; + /* End of if */ + + CFG80211OS_ScanEnd(CFG80211CB, FlgIsAborted); + + pAd->FlgCfg80211Scanning = FALSE; +#endif /* CONFIG_STA_SUPPORT */ +} /* End of CFG80211_ScanEnd */ + + +/* +======================================================================== +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_ERROR, ("80211> CFG80211_ConnectResultInform ==>\n")); + + CFG80211OS_ConnectResultInform(CFG80211CB, + pBSSID, + pReqIe, + ReqIeLen, + pRspIe, + RspIeLen, + FlgIsSuccess); + + pAd->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_ERROR, ("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 */ + + +#endif /* RT_CFG80211_SUPPORT */ + +/* End of cfg80211drv.c */ diff --git a/mt7620/src/os/linux/config.mk b/mt7620/src/os/linux/config.mk new file mode 100644 index 0000000..43c1fde --- /dev/null +++ b/mt7620/src/os/linux/config.mk @@ -0,0 +1,1320 @@ +# Support ATE function +HAS_ATE=n + +# Support QA ATE function +HAS_QA_SUPPORT=n + +HAS_RSSI_FEEDBACK=n + +# Support XLINK mode +HAS_XLINK=n + +# Support WSC function +HAS_WSC=n +HAS_WSC_V2=n +HAS_WSC_LED=n +HAS_IWSC_SUPPORT=n + +HAS_NINTENDO=n + +# Support LLTD function +HAS_LLTD=n + +# Support WDS function +HAS_WDS=n + +# Support AP-Client function +HAS_APCLI=n + +# Support AP-Client TGn Test +HAS_APCLI_CERT=n + +# Support Wpa_Supplicant +# i.e. wpa_supplicant -Dralink +HAS_WPA_SUPPLICANT=n + + +# Support Native WpaSupplicant for Network Maganger +# i.e. wpa_supplicant -Dwext +HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=n + +#Support Net interface block while Tx-Sw queue full +HAS_BLOCK_NET_IF=n + +#Support IGMP-Snooping function. +HAS_IGMP_SNOOP_SUPPORT=n + +#Support DFS function +HAS_DFS_SUPPORT=n + +#Support Carrier-Sense function +HAS_CS_SUPPORT=n + +# Support for STA Ethernet Converter +HAS_ETH_CONVERT_SUPPORT=n + +# Support user specific transmit rate of Multicast packet. +HAS_MCAST_RATE_SPECIFIC_SUPPORT=n + +# Support for Multiple Cards +HAS_MC_SUPPORT=n + +#Support for PCI-MSI +HAS_MSI_SUPPORT=n + + +#Support for IEEE802.11e DLS +HAS_QOS_DLS_SUPPORT=n + +#Support for EXT_CHANNEL +HAS_EXT_BUILD_CHANNEL_LIST=n + +#Support for IDS +HAS_IDS_SUPPORT=n + +#Support for MESH +HAS_MESH_SUPPORT=n + +#Support for Net-SNMP +HAS_SNMP_SUPPORT=n + +#Support features of 802.11n Draft3 +HAS_DOT11N_DRAFT3_SUPPORT=n + +#Support features of Single SKU. +HAS_SINGLE_SKU_SUPPORT=n + +#Support features of 802.11n +HAS_DOT11_N_SUPPORT=y + +#Support for WAPI +HAS_WAPI_SUPPORT=n + + +#Support for 2860/2880 co-exist +HAS_RT2880_RT2860_COEXIST=n + +HAS_KTHREAD_SUPPORT=n + + + +#Support for dot11z TDLS +HAS_DOT11Z_TDLS_SUPPORT=n + +#Support for WiFi-Driect(Peer to Peer) +HAS_P2P_SUPPORT=n +HAS_P2P_ODD_MAC_ADJUST=n +HAS_P2P_SPECIFIC_WIRELESS_EVENT=n + +#Support for Auto channel select enhance +HAS_AUTO_CH_SELECT_ENHANCE=n + +#Support statistics count +HAS_STATS_COUNT=y + +#Support TSSI Antenna Variation +HAS_TSSI_ANTENNA_VARIATION=n + +#Support USB_BULK_BUF_ALIGMENT +HAS_USB_BULK_BUF_ALIGMENT=n + +#Support for USB_SUPPORT_SELECTIVE_SUSPEND +HAS_USB_SUPPORT_SELECTIVE_SUSPEND=n + +#Support USB load firmware by multibyte +HAS_USB_FIRMWARE_MULTIBYTE_WRITE=n + + +#Support ANDROID_SUPPORT +HAS_ANDROID_SUPPORT=n + +#HAS_IFUP_IN_PROBE_SUPPORT +HAS_IFUP_IN_PROBE_SUPPORT=n + + + + +#Support TXRX SW Antenna Diversity +HAS_TXRX_SW_ANTDIV_SUPPORT=n + +#Client support WDS function +HAS_CLIENT_WDS_SUPPORT=n + +#Support for Bridge Fast Path & Bridge Fast Path function open to other module +HAS_BGFP_SUPPORT=n +HAS_BGFP_OPEN_SUPPORT=n + +# Support HOSTAPD function +HAS_HOSTAPD_SUPPORT=n + +#Support GreenAP function +HAS_GREENAP_SUPPORT=n + +#Support MAC80211 LINUX-only function +#Please make sure the version for CFG80211.ko and MAC80211.ko is same as the one +#our driver references to. +HAS_CFG80211_SUPPORT=n + +#Support RFKILL hardware block/unblock LINUX-only function +HAS_RFKILL_HW_SUPPORT=n + +HAS_EASY_CONFIG_SETUP_SUPPORT=n + + +HAS_APCLI_WPA_SUPPLICANT=n + +HAS_RTMP_FLASH_SUPPORT=n + +ifeq ($(OSABL),YES) +HAS_OSABL_FUNC_SUPPORT=y +HAS_OSABL_OS_PCI_SUPPORT=y +HAS_OSABL_OS_USB_SUPPORT=y +HAS_OSABL_OS_RBUS_SUPPORT=n +HAS_OSABL_OS_AP_SUPPORT=y +HAS_OSABL_OS_STA_SUPPORT=y +endif + +HAS_LED_CONTROL_SUPPORT=y + +HAS_WIFI_LED_SHARE=n + +#Support WIDI feature +#Must enable HAS_WSC at the same time. + +HAS_TXBF_SUPPORT=n + +HAS_STREAM_MODE_SUPPORT=n + +HAS_NEW_RATE_ADAPT_SUPPORT=n + +HAS_DPA_S_SUPPORT=n + + + +HAS_WOW_SUPPORT=n +HAS_WOW_IFDOWN_SUPPORT=n + +HAS_THERMAL_PROTECT_SUPPORT=n + +################################################# + +CC := $(CROSS_COMPILE)gcc +LD := $(CROSS_COMPILE)ld + +WFLAGS := -DAGGREGATION_SUPPORT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT -DLINUX -Wall -Wstrict-prototypes -Wno-trigraphs +WFLAGS += -DSYSTEM_LOG_SUPPORT -DRT28xx_MODE=$(RT28xx_MODE) -DCHIPSET=$(MODULE) -DRESOURCE_PRE_ALLOC + +ifeq ($(HAS_DPA_S_SUPPORT),y) +WFLAGS += -DDPA_S +endif + + + + + +ifeq ($(HAS_KTHREAD_SUPPORT),y) +WFLAGS += -DKTHREAD_SUPPORT +endif + +ifeq ($(HAS_RTMP_FLASH_SUPPORT),y) +WFLAGS += -DRTMP_FLASH_SUPPORT +endif + +ifeq ($(HAS_STREAM_MODE_SUPPORT),y) +WFLAGS += -DSTREAM_MODE_SUPPORT +endif + +ifeq ($(HAS_SINGLE_SKU_SUPPORT),y) +WFLAGS += -DSINGLE_SKU +endif + +# config for AP mode + +ifeq ($(RT28xx_MODE),AP) +WFLAGS += -DCONFIG_AP_SUPPORT -DUAPSD_SUPPORT -DMBSS_SUPPORT -DIAPP_SUPPORT -DDBG -DDOT1X_SUPPORT -DAP_SCAN_SUPPORT + +ifeq ($(HAS_APCLI_WPA_SUPPLICANT),y) +WFLAGS += -DApCli_WPA_SUPPLICANT_SUPPORT +endif + +ifeq ($(HAS_HOSTAPD_SUPPORT),y) +WFLAGS += -DHOSTAPD_SUPPORT +endif + +ifeq ($(HAS_ATE),y) +WFLAGS += -DRALINK_ATE +WFLAGS += -DCONFIG_RT2880_ATE_CMD_NEW +WFLAGS += -I$(RT28xx_DIR)/ate/include +ifeq ($(HAS_QA_SUPPORT),y) +WFLAGS += -DRALINK_QA +endif +endif + +ifeq ($(HAS_THERMAL_PROTECT_SUPPORT),y) +WFLAGS += -DTHERMAL_PROTECT_SUPPORT +endif + +ifeq ($(HAS_RSSI_FEEDBACK),y) +WFLAGS += -DRSSI_FEEDBACK +endif + +ifeq ($(RELEASE), DPB) +WFLAGS += -DGEMTEK_ATE +endif + + +ifeq ($(HAS_NINTENDO),y) +WFLAGS += -DNINTENDO_AP +endif + +ifeq ($(HAS_WSC),y) +WFLAGS += -DWSC_AP_SUPPORT + +ifeq ($(HAS_WSC_V2),y) +WFLAGS += -DWSC_V2_SUPPORT +endif +ifeq ($(HAS_WSC_LED),y) +WFLAGS += -DWSC_LED_SUPPORT +endif +endif + +ifeq ($(HAS_EASY_CONFIG_SETUP_SUPPORT),y) +WFLAGS += -DEASY_CONFIG_SETUP -DWAC_SUPPORT +endif + +ifeq ($(HAS_WDS),y) +WFLAGS += -DWDS_SUPPORT +endif + +ifeq ($(HAS_APCLI_CERT),y) +WFLAGS += -DAPCLI_CERT_SUPPORT +HAS_APCLI=y +endif + +ifeq ($(HAS_APCLI),y) +WFLAGS += -DAPCLI_SUPPORT -DMAT_SUPPORT -DAP_SCAN_SUPPORT +#ifeq ($(HAS_ETH_CONVERT_SUPPORT), y) +#WFLAGS += -DETH_CONVERT_SUPPORT +endif + +ifeq ($(HAS_IGMP_SNOOP_SUPPORT),y) +WFLAGS += -DIGMP_SNOOP_SUPPORT +endif + +ifeq ($(HAS_CS_SUPPORT),y) +WFLAGS += -DCARRIER_DETECTION_SUPPORT +endif + +ifeq ($(HAS_MCAST_RATE_SPECIFIC_SUPPORT), y) +WFLAGS += -DMCAST_RATE_SPECIFIC +endif + +ifneq ($(findstring 2860,$(CHIPSET)),) +ifeq ($(HAS_MSI_SUPPORT),y) +WFLAGS += -DPCI_MSI_SUPPORT +endif +endif + + +ifeq ($(HAS_QOS_DLS_SUPPORT),y) +WFLAGS += -DQOS_DLS_SUPPORT +endif + +ifeq ($(HAS_SNMP_SUPPORT),y) +WFLAGS += -DSNMP_SUPPORT +endif + +ifeq ($(HAS_DOT11_N_SUPPORT),y) +WFLAGS += -DDOT11_N_SUPPORT + +ifeq ($(HAS_DOT11N_DRAFT3_SUPPORT),y) +WFLAGS += -DDOT11N_DRAFT3 +endif + +ifeq ($(HAS_TXBF_SUPPORT),y) +WFLAGS += -DTXBF_SUPPORT +endif + +ifeq ($(HAS_NEW_RATE_ADAPT_SUPPORT),y) +WFLAGS += -DNEW_RATE_ADAPT_SUPPORT +endif + +ifeq ($(HAS_GREENAP_SUPPORT),y) +WFLAGS += -DGREENAP_SUPPORT +endif + +endif + +ifeq ($(HAS_AUTO_CH_SELECT_ENHANCE),y) +WFLAGS += -DAUTO_CH_SELECT_ENHANCE +endif + +ifeq ($(HAS_STATS_COUNT),y) +WFLAGS += -DSTATS_COUNT_SUPPORT +endif + +ifeq ($(HAS_TSSI_ANTENNA_VARIATION),y) +WFLAGS += -DTSSI_ANTENNA_VARIATION +endif + +ifeq ($(HAS_USB_BULK_BUF_ALIGMENT),y) +WFLAGS += -DUSB_BULK_BUF_ALIGMENT +endif + + +ifeq ($(HAS_CFG80211_SUPPORT),y) +WFLAGS += -DRT_CFG80211_SUPPORT +ifeq ($(HAS_RFKILL_HW_SUPPORT),y) +WFLAGS += -DRFKILL_HW_SUPPORT +endif +endif + +ifeq ($(OSABL),YES) +WFLAGS += -DOS_ABL_SUPPORT +ifeq ($(HAS_OSABL_FUNC_SUPPORT),y) +WFLAGS += -DOS_ABL_FUNC_SUPPORT +endif +ifeq ($(HAS_OSABL_OS_PCI_SUPPORT),y) +WFLAGS += -DOS_ABL_OS_PCI_SUPPORT +endif +ifeq ($(HAS_OSABL_OS_USB_SUPPORT),y) +WFLAGS += -DOS_ABL_OS_USB_SUPPORT +endif +ifeq ($(HAS_OSABL_OS_RBUS_SUPPORT),y) +WFLAGS += -DOS_ABL_OS_RBUS_SUPPORT +endif +ifeq ($(HAS_OSABL_OS_AP_SUPPORT),y) +WFLAGS += -DOS_ABL_OS_AP_SUPPORT +endif +ifeq ($(HAS_OSABL_OS_STA_SUPPORT),y) +WFLAGS += -DOS_ABL_OS_STA_SUPPORT +endif +endif + + +ifeq ($(HAS_TXRX_SW_ANTDIV_SUPPORT),y) +WFLAGS += -DTXRX_SW_ANTDIV_SUPPORT +endif + + +endif #// endif of RT2860_MODE == AP // + +################################################# + +# config for STA mode + +ifeq ($(RT28xx_MODE),STA) +WFLAGS += -DCONFIG_STA_SUPPORT -DDBG + +ifeq ($(HAS_XLINK),y) +WFLAGS += -DXLINK_SUPPORT +endif + +WFLAGS += -DADHOC_WPA2PSK_SUPPORT + +ifeq ($(HAS_WPA_SUPPLICANT),y) +WFLAGS += -DWPA_SUPPLICANT_SUPPORT +ifeq ($(HAS_NATIVE_WPA_SUPPLICANT_SUPPORT),y) +WFLAGS += -DNATIVE_WPA_SUPPLICANT_SUPPORT +endif +endif + +ifeq ($(HAS_WSC),y) +WFLAGS += -DWSC_STA_SUPPORT +ifeq ($(HAS_WSC_V2),y) +WFLAGS += -DWSC_V2_SUPPORT +endif +ifeq ($(HAS_WSC_LED),y) +WFLAGS += -DWSC_LED_SUPPORT +endif +ifeq ($(HAS_IWSC_SUPPORT),y) +WFLAGS += -DIWSC_SUPPORT +endif +endif + + +ifeq ($(HAS_ETH_CONVERT_SUPPORT), y) +WFLAGS += -DETH_CONVERT_SUPPORT -DMAT_SUPPORT +endif + +ifeq ($(HAS_ATE),y) +WFLAGS += -DRALINK_ATE +WFLAGS += -DCONFIG_RT2880_ATE_CMD_NEW +WFLAGS += -I$(RT28xx_DIR)/ate/include +ifeq ($(HAS_QA_SUPPORT),y) +WFLAGS += -DRALINK_QA +endif +endif + +ifeq ($(HAS_THERMAL_PROTECT_SUPPORT),y) +WFLAGS += -DTHERMAL_PROTECT_SUPPORT +endif + + +ifeq ($(HAS_SNMP_SUPPORT),y) +WFLAGS += -DSNMP_SUPPORT +endif + +ifeq ($(HAS_QOS_DLS_SUPPORT),y) +WFLAGS += -DQOS_DLS_SUPPORT +endif + +ifeq ($(HAS_DOT11_N_SUPPORT),y) +WFLAGS += -DDOT11_N_SUPPORT + +ifeq ($(HAS_DOT11N_DRAFT3_SUPPORT),y) +WFLAGS += -DDOT11N_DRAFT3 +endif + +ifeq ($(HAS_TXBF_SUPPORT),y) +WFLAGS += -DTXBF_SUPPORT +endif + +ifeq ($(HAS_NEW_RATE_ADAPT_SUPPORT),y) +WFLAGS += -DNEW_RATE_ADAPT_SUPPORT +endif + +endif + +ifeq ($(HAS_DOT11Z_TDLS_SUPPORT),y) +WFLAGS += -DDOT11Z_TDLS_SUPPORT -DUAPSD_SUPPORT +endif + +ifeq ($(HAS_P2P_SUPPORT),y) +WFLAGS += -DP2P_SUPPORT -DAPCLI_SUPPORT -DMAT_SUPPORT -DAP_SCAN_SUPPORT -DP2P_APCLI_SUPPORT -DCONFIG_AP_SUPPORT -DCONFIG_APSTA_MIXED_SUPPORT -DUAPSD_SUPPORT -DMBSS_SUPPORT -DIAPP_SUPPORT -DDOT1X_SUPPORT -DAP_SCAN_SUPPORT -DWSC_AP_SUPPORT -DWSC_STA_SUPPORT +endif + +ifeq ($(HAS_P2P_ODD_MAC_ADJUST),y) +WFLAGS += -DP2P_ODD_MAC_ADJUST +endif + +ifeq ($(HAS_P2P_SPECIFIC_WIRELESS_EVENT),y) +WFLAGS += -DRT_P2P_SPECIFIC_WIRELESS_EVENT +endif + +ifeq ($(HAS_CS_SUPPORT),y) +WFLAGS += -DCARRIER_DETECTION_SUPPORT +endif + +ifeq ($(HAS_STATS_COUNT),y) +WFLAGS += -DSTATS_COUNT_SUPPORT +endif + +ifeq ($(HAS_TSSI_ANTENNA_VARIATION),y) +WFLAGS += -DTSSI_ANTENNA_VARIATION +endif + +ifeq ($(HAS_ANDROID_SUPPORT),y) +WFLAGS += -DANDROID_SUPPORT +endif + + +ifeq ($(HAS_IFUP_IN_PROBE_SUPPORT),y) +WFLAGS += -DIFUP_IN_PROBE +endif + +ifeq ($(HAS_USB_SUPPORT_SELECTIVE_SUSPEND),y) +WFLAGS += -DUSB_SUPPORT_SELECTIVE_SUSPEND +endif + +ifeq ($(HAS_USB_FIRMWARE_MULTIBYTE_WRITE),y) +WFLAGS += -DUSB_FIRMWARE_MULTIBYTE_WRITE -DMULTIWRITE_BYTES=4 +endif + +ifeq ($(HAS_CFG80211_SUPPORT),y) +WFLAGS += -DRT_CFG80211_SUPPORT +ifeq ($(HAS_RFKILL_HW_SUPPORT),y) +WFLAGS += -DRFKILL_HW_SUPPORT +endif +endif + +ifeq ($(OSABL),YES) +WFLAGS += -DOS_ABL_SUPPORT +ifeq ($(HAS_OSABL_FUNC_SUPPORT),y) +WFLAGS += -DOS_ABL_FUNC_SUPPORT +endif +ifeq ($(HAS_OSABL_OS_PCI_SUPPORT),y) +WFLAGS += -DOS_ABL_OS_PCI_SUPPORT +endif +ifeq ($(HAS_OSABL_OS_USB_SUPPORT),y) +WFLAGS += -DOS_ABL_OS_USB_SUPPORT +endif +ifeq ($(HAS_OSABL_OS_RBUS_SUPPORT),y) +WFLAGS += -DOS_ABL_OS_RBUS_SUPPORT +endif +ifeq ($(HAS_OSABL_OS_AP_SUPPORT),y) +WFLAGS += -DOS_ABL_OS_AP_SUPPORT +endif +ifeq ($(HAS_OSABL_OS_STA_SUPPORT),y) +WFLAGS += -DOS_ABL_OS_STA_SUPPORT +endif +endif + + +ifeq ($(HAS_TXRX_SW_ANTDIV_SUPPORT),y) +WFLAGS += -DTXRX_SW_ANTDIV_SUPPORT +endif + + +ifeq ($(HAS_WIDI_SUPPORT),y) +WFLAGS += -DWIDI_SUPPORT + +ifeq ($(HAS_P2P_SUPPORT),y) +ifeq ($(HAS_INTEL_WFD_SUPPORT),y) +WFLAGS += -DINTEL_WFD_SUPPORT +endif + +ifeq ($(HAS_WFA_WFD_SUPPORT),y) +WFLAGS += -DWFA_WFD_SUPPORT +endif +endif + +endif + +ifeq ($(HAS_WOW_SUPPORT),y) +WFLAGS += -DWOW_SUPPORT +endif + +ifeq ($(HAS_WOW_IFDOWN_SUPPORT),y) +WFLAGS += -DWOW_IFDOWN_SUPPORT +endif + +endif +# endif of ifeq ($(RT28xx_MODE),STA) + +################################################# + +# config for APSTA + +ifeq ($(RT28xx_MODE),APSTA) +WFLAGS += -DCONFIG_AP_SUPPORT -DCONFIG_STA_SUPPORT -DCONFIG_APSTA_MIXED_SUPPORT -DUAPSD_SUPPORT -DMBSS_SUPPORT -DIAPP_SUPPORT -DDOT1X_SUPPORT -DAP_SCAN_SUPPORT -DDBG + +ifeq ($(HAS_NINTENDO),y) +WFLAGS += -DNINTENDO_AP +endif + +ifeq ($(HAS_WSC),y) +WFLAGS += -DWSC_AP_SUPPORT -DWSC_STA_SUPPORT +endif + +ifeq ($(HAS_WDS),y) +WFLAGS += -DWDS_SUPPORT +endif + +ifeq ($(HAS_APCLI),y) +WFLAGS += -DAPCLI_SUPPORT -DMAT_SUPPORT +endif + +ifeq ($(HAS_IGMP_SNOOP_SUPPORT),y) +WFLAGS += -DIGMP_SNOOP_SUPPORT +endif + +ifeq ($(HAS_CS_SUPPORT),y) +WFLAGS += -DCARRIER_DETECTION_SUPPORT +endif + +ifeq ($(HAS_MCAST_RATE_SPECIFIC_SUPPORT), y) +WFLAGS += -DMCAST_RATE_SPECIFIC +endif + +ifeq ($(HAS_QOS_DLS_SUPPORT),y) +WFLAGS += -DQOS_DLS_SUPPORT +endif + +ifeq ($(HAS_WPA_SUPPLICANT),y) +WFLAGS += -DWPA_SUPPLICANT_SUPPORT +ifeq ($(HAS_NATIVE_WPA_SUPPLICANT_SUPPORT),y) +WFLAGS += -DNATIVE_WPA_SUPPLICANT_SUPPORT +endif +endif + +ifeq ($(HAS_ETH_CONVERT_SUPPORT), y) +WFLAGS += -DETH_CONVERT_SUPPORT -DMAT_SUPPORT +endif + +ifeq ($(HAS_DOT11_N_SUPPORT),y) +WFLAGS += -DDOT11_N_SUPPORT +endif + +ifeq ($(HAS_TXBF_SUPPORT),y) +WFLAGS += -DTXBF_SUPPORT +endif + +ifeq ($(HAS_NEW_RATE_ADAPT_SUPPORT),y) +WFLAGS += -DNEW_RATE_ADAPT_SUPPORT +endif + + +ifeq ($(HAS_CS_SUPPORT),y) +WFLAGS += -DCARRIER_DETECTION_SUPPORT +endif + +ifeq ($(HAS_STATS_COUNT),y) +WFLAGS += -DSTATS_COUNT_SUPPORT +endif + +ifeq ($(HAS_TSSI_ANTENNA_VARIATION),y) +WFLAGS += -DTSSI_ANTENNA_VARIATION +endif + +ifeq ($(HAS_CFG80211_SUPPORT),y) +WFLAGS += -DRT_CFG80211_SUPPORT +ifeq ($(HAS_RFKILL_HW_SUPPORT),y) +WFLAGS += -DRFKILL_HW_SUPPORT +endif +endif + +ifeq ($(OSABL),YES) +WFLAGS += -DOS_ABL_SUPPORT +ifeq ($(HAS_OSABL_FUNC_SUPPORT),y) +WFLAGS += -DOS_ABL_FUNC_SUPPORT +endif +ifeq ($(HAS_OSABL_OS_PCI_SUPPORT),y) +WFLAGS += -DOS_ABL_OS_PCI_SUPPORT +endif +ifeq ($(HAS_OSABL_OS_USB_SUPPORT),y) +WFLAGS += -DOS_ABL_OS_USB_SUPPORT +endif +ifeq ($(HAS_OSABL_OS_RBUS_SUPPORT),y) +WFLAGS += -DOS_ABL_OS_RBUS_SUPPORT +endif +ifeq ($(HAS_OSABL_OS_AP_SUPPORT),y) +WFLAGS += -DOS_ABL_OS_AP_SUPPORT +endif +ifeq ($(HAS_OSABL_OS_STA_SUPPORT),y) +WFLAGS += -DOS_ABL_OS_STA_SUPPORT +endif +endif + +ifeq ($(HAS_P2P_SUPPORT),y) +WFLAGS += -DP2P_SUPPORT +WFLAGS += -DAPCLI_SUPPORT -DMAT_SUPPORT -DAP_SCAN_SUPPORT -DP2P_APCLI_SUPPORT +endif + +endif +# endif of ifeq ($(RT28xx_MODE),APSTA) +################################################# + +# +# Common compiler flag +# + + +ifeq ($(HAS_MESH_SUPPORT),y) +WFLAGS += -DMESH_SUPPORT -DINTEL_CMPC -DAP_SCAN_SUPPORT +endif + + + + +ifeq ($(HAS_EXT_BUILD_CHANNEL_LIST),y) +WFLAGS += -DEXT_BUILD_CHANNEL_LIST +endif + +ifeq ($(HAS_IDS_SUPPORT),y) +WFLAGS += -DIDS_SUPPORT +endif + +ifeq ($(HAS_WAPI_SUPPORT),y) +WFLAGS += -DWAPI_SUPPORT -DSOFT_ENCRYPT -DEXPORT_SYMTAB +endif + +ifeq ($(OSABL),YES) +WFLAGS += -DEXPORT_SYMTAB +endif + +ifeq ($(HAS_CLIENT_WDS_SUPPORT),y) +WFLAGS += -DCLIENT_WDS +endif + +ifeq ($(HAS_BGFP_SUPPORT),y) +WFLAGS += -DBG_FT_SUPPORT +endif + +ifeq ($(HAS_BGFP_OPEN_SUPPORT),y) +WFLAGS += -DBG_FT_OPEN_SUPPORT +endif + + +ifeq ($(HAS_LED_CONTROL_SUPPORT),y) +WFLAGS += -DLED_CONTROL_SUPPORT +endif + +################################################# +# ChipSet specific definitions. +# +ifneq ($(findstring 2860,$(CHIPSET)),) +WFLAGS +=-DRTMP_MAC_PCI -DRTMP_PCI_SUPPORT -DRT2860 -DRT28xx -DA_BAND_SUPPORT +CHIPSET_DAT = 2860 +endif + +ifneq ($(findstring 3090,$(CHIPSET)),) +WFLAGS +=-DRTMP_MAC_PCI -DRT30xx -DRT3090 -DRTMP_PCI_SUPPORT -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT -DVCORECAL_SUPPORT +CHIPSET_DAT = 2860 +endif + +ifneq ($(findstring 2870,$(CHIPSET)),) +WFLAGS +=-DRTMP_MAC_USB -DRTMP_USB_SUPPORT -DRT2870 -DRT28xx -DRTMP_TIMER_TASK_SUPPORT -DA_BAND_SUPPORT +CHIPSET_DAT = 2870 +endif + +ifneq ($(findstring 2070,$(CHIPSET)),) +WFLAGS +=-DRTMP_MAC_USB -DRT30xx -DRT3070 -DRT2070 -DRTMP_USB_SUPPORT -DRTMP_TIMER_TASK_SUPPORT -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT +CHIPSET_DAT = 2870 +endif + +ifneq ($(findstring 3070,$(CHIPSET)),) +WFLAGS +=-DRTMP_MAC_USB -DRT30xx -DRT3070 -DRTMP_USB_SUPPORT -DRTMP_TIMER_TASK_SUPPORT -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT -DVCORECAL_SUPPORT +CHIPSET_DAT = 2870 + +ifneq ($(findstring $(RT28xx_MODE),AP),) +ifeq ($(HAS_CS_SUPPORT), y) +WFLAGS += -DCARRIER_DETECTION_FIRMWARE_SUPPORT +endif +endif + +endif + +ifneq ($(findstring 2880,$(CHIPSET)),) +WFLAGS += -DRT2880 -DRT28xx -DRTMP_MAC_PCI -DCONFIG_RALINK_RT2880_MP -DRTMP_RBUS_SUPPORT -DMERGE_ARCH_TEAM -DA_BAND_SUPPORT -DCONFIG_SWMCU_SUPPORT +ifeq ($(HAS_WIFI_LED_SHARE), y) +WFLAGS += -DCONFIG_WIFI_LED_SHARE +endif +endif + +ifneq ($(findstring 3572,$(CHIPSET)),) +WFLAGS +=-DRTMP_MAC_USB -DRTMP_USB_SUPPORT -DRT2870 -DRT28xx -DRT30xx -DRT35xx -DRT3572 -DRTMP_TIMER_TASK_SUPPORT -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT -DA_BAND_SUPPORT -DVCORECAL_SUPPORT +CHIPSET_DAT = 2870 + +ifneq ($(findstring $(RT28xx_MODE),AP),) +ifeq ($(HAS_CS_SUPPORT), y) +WFLAGS += -DCARRIER_DETECTION_FIRMWARE_SUPPORT +endif +endif + +endif + +ifneq ($(findstring 3573,$(CHIPSET)),) +WFLAGS += -DRTMP_MAC_USB -DRTMP_USB_SUPPORT -DRT30xx -DRT35xx -DRT3593 -DRT3573\ + -DRTMP_TIMER_TASK_SUPPORT -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT\ + -DA_BAND_SUPPORT -DDOT11N_SS3_SUPPORT \ + -DVCORECAL_SUPPORT -DNEW_MBSSID_MODE +#WFLAGS += -DNEW_RATE_ADAPT_SUPPORT +CHIPSET_DAT = 2870 + +ifneq ($(findstring $(RT28xx_MODE),STA APSTA),) +WFLAGS += -DRTMP_FREQ_CALIBRATION_SUPPORT +endif + +ifneq ($(findstring $(RT28xx_MODE),AP),) +WFLAGS += -DSPECIFIC_BCN_BUF_SUPPORT +endif + +ifneq ($(findstring $(RT28xx_MODE),AP),) +ifeq ($(HAS_CS_SUPPORT), y) +WFLAGS += -DCARRIER_DETECTION_FIRMWARE_SUPPORT +endif +endif + +endif + +ifneq ($(findstring 3062,$(CHIPSET)),) +WFLAGS +=-DRTMP_MAC_PCI -DRT2860 -DRT28xx -DRT30xx -DRT35xx -DRT3062 -DRTMP_PCI_SUPPORT -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT -DVCORECAL_SUPPORT +CHIPSET_DAT = 2860 +endif + +ifneq ($(findstring 3562,$(CHIPSET)),) +WFLAGS +=-DRTMP_MAC_PCI -DRT2860 -DRT28xx -DRT30xx -DRT35xx -DRT3562 -DRTMP_PCI_SUPPORT -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT -DA_BAND_SUPPORT -DVCORECAL_SUPPORT + +CHIPSET_DAT = 2860 +endif + +ifneq ($(findstring 3593,$(CHIPSET)),) +WFLAGS +=-DRTMP_MAC_PCI -DDOT11N_SS3_SUPPORT -DRT3593 -DRT28xx -DRT30xx -DRT35xx -DRTMP_PCI_SUPPORT -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT -DA_BAND_SUPPORT -DNEW_MBSSID_MODE -DVCORECAL_SUPPORT + +#WFLAGS += -DNEW_RATE_ADAPT_SUPPORT +CHIPSET_DAT = 2860 + +ifneq ($(findstring $(RT28xx_MODE),STA APSTA),) +WFLAGS += -DRTMP_FREQ_CALIBRATION_SUPPORT +endif + +ifneq ($(findstring $(RT28xx_MODE),AP),) +WFLAGS += -DSPECIFIC_BCN_BUF_SUPPORT +endif +endif + +ifneq ($(findstring 3390,$(CHIPSET)),) +WFLAGS +=-DRTMP_MAC_PCI -DRT30xx -DRT33xx -DRT3090 -DRT3390 -DRTMP_PCI_SUPPORT -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT -DRTMP_INTERNAL_TX_ALC -DVCORECAL_SUPPORT +CHIPSET_DAT = 2860 +endif + +ifneq ($(findstring 3370,$(CHIPSET)),) +WFLAGS +=-DRTMP_MAC_USB -DRT30xx -DRT33xx -DRT3070 -DRT3370 -DRTMP_USB_SUPPORT -DRTMP_TIMER_TASK_SUPPORT -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT -DRTMP_INTERNAL_TX_ALC -DVCORECAL_SUPPORT +CHIPSET_DAT = 2870 + +ifneq ($(findstring $(RT28xx_MODE),AP),) +ifeq ($(HAS_CS_SUPPORT), y) +WFLAGS += -DCARRIER_DETECTION_FIRMWARE_SUPPORT +endif +endif + +endif + +ifneq ($(findstring 5390,$(CHIPSET)),) +WFLAGS +=-DRTMP_MAC_PCI -DRT30xx -DRT33xx -DRT3090 -DRT3390 -DRT5390 -DRTMP_PCI_SUPPORT -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT -DRTMP_FREQ_CALIBRATION_SUPPORT -DRTMP_INTERNAL_TX_ALC -DVCORECAL_SUPPORT -DIQ_CAL_SUPPORT -DNEW_MBSSID_MODE -DRTMP_TEMPERATURE_COMPENSATION +CHIPSET_DAT = 2860 + +ifneq ($(findstring $(RT28xx_MODE),AP),) +WFLAGS += -DSPECIFIC_BCN_BUF_SUPPORT +endif +endif + +ifneq ($(findstring 5370,$(CHIPSET)),) +WFLAGS +=-DRTMP_MAC_USB -DRT30xx -DRT33xx -DRT3070 -DRT3370 -DRT5370 -DRTMP_USB_SUPPORT -DRTMP_TIMER_TASK_SUPPORT -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT -DRTMP_INTERNAL_TX_ALC -DRTMP_FREQ_CALIBRATION_SUPPORT -DVCORECAL_SUPPORT -DIQ_CAL_SUPPORT -DNEW_MBSSID_MODE -DRTMP_TEMPERATURE_COMPENSATION +CHIPSET_DAT = 2870 + +ifneq ($(findstring $(RT28xx_MODE),AP),) +ifeq ($(HAS_CS_SUPPORT), y) +WFLAGS += -DCARRIER_DETECTION_FIRMWARE_SUPPORT +endif +endif + +ifneq ($(findstring $(RT28xx_MODE),AP),) +WFLAGS += -DSPECIFIC_BCN_BUF_SUPPORT +endif +endif + +ifneq ($(findstring 3052,$(CHIPSET)),) +WFLAGS += -DRTMP_MAC_PCI -DRTMP_RBUS_SUPPORT -DRT3052 -DRT305x -DRTMP_RF_RW_SUPPORT -DCONFIG_SWMCU_SUPPORT -DVCORECAL_SUPPORT +CHIPSET_DAT = 2870 +ifeq ($(HAS_WIFI_LED_SHARE), y) +WFLAGS += -DCONFIG_WIFI_LED_SHARE +endif +endif + +ifneq ($(findstring 3352,$(CHIPSET)),) +WFLAGS += -DRTMP_MAC_PCI -DRTMP_RBUS_SUPPORT -DRT3352 -DRT305x -DRTMP_RF_RW_SUPPORT -DVCORECAL_SUPPORT -DCONFIG_SWMCU_SUPPORT -DRTMP_INTERNAL_TX_ALC -DNEW_MBSSID_MODE +CHIPSET_DAT = 2860 +ifeq ($(HAS_WIFI_LED_SHARE), y) +WFLAGS += -DCONFIG_WIFI_LED_SHARE +endif +ifneq ($(findstring $(RT28xx_MODE),AP),) +WFLAGS += -DSPECIFIC_BCN_BUF_SUPPORT +endif +endif + +ifneq ($(findstring 5350,$(CHIPSET)),) +WFLAGS += -DRTMP_MAC_PCI -DRTMP_RBUS_SUPPORT -DRT5350 -DRT305x -DRT3050 -DRT3350 -DRTMP_RF_RW_SUPPORT -DVCORECAL_SUPPORT -DCONFIG_SWMCU_SUPPORT -DRTMP_INTERNAL_TX_ALC -DRTMP_FREQ_CALIBRATION_SUPPORT -DIQ_CAL_SUPPORT -DNEW_MBSSID_MODE +CHIPSET_DAT = 2860 +ifeq ($(HAS_WIFI_LED_SHARE), y) +WFLAGS += -DCONFIG_WIFI_LED_SHARE +endif +ifneq ($(findstring $(RT28xx_MODE),AP),) +WFLAGS += -DSPECIFIC_BCN_BUF_SUPPORT +endif +endif + +ifneq ($(findstring 5592,$(CHIPSET)),) +WFLAGS += -DRTMP_MAC_PCI -DRTMP_PCI_SUPPORT -DRT30xx -DRT5592\ + -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT\ + -DA_BAND_SUPPORT -DIQ_CAL_SUPPORT -DRX_DMA_SCATTER -DVCORECAL_SUPPORT\ + -DNEW_MBSSID_MODE -DRTMP_TEMPERATURE_COMPENSATION +CHIPSET_DAT = 2860 +ifeq ($(HAS_TSO_SUPPORT), y) +WFLAGS += -DCONFIG_TSO_SUPPORT +endif + +ifneq ($(findstring $(RT28xx_MODE),STA APSTA),) +WFLAGS += -DRTMP_FREQ_CALIBRATION_SUPPORT +endif + +ifneq ($(findstring $(RT28xx_MODE),AP),) +WFLAGS += -DSPECIFIC_BCN_BUF_SUPPORT +endif + +endif + +ifneq ($(findstring 5572,$(CHIPSET)),) +WFLAGS += -DRTMP_MAC_USB -DRTMP_USB_SUPPORT -DRT30xx -DRT5572 -DRT5592\ + -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT -DNEW_MBSSID_MODE\ + -DRTMP_TIMER_TASK_SUPPORT -DA_BAND_SUPPORT -DIQ_CAL_SUPPORT -DVCORECAL_SUPPORT\ + -DRTMP_TEMPERATURE_COMPENSATION +CHIPSET_DAT = 2870 +ifeq ($(HAS_TSO_SUPPORT), y) +WFLAGS += -DCONFIG_TSO_SUPPORT +endif + +ifneq ($(findstring $(RT28xx_MODE),AP),) +ifeq ($(HAS_CS_SUPPORT), y) +WFLAGS += -DCARRIER_DETECTION_FIRMWARE_SUPPORT +endif +endif + +ifneq ($(findstring $(RT28xx_MODE),STA APSTA),) +WFLAGS += -DRTMP_FREQ_CALIBRATION_SUPPORT +endif + +ifneq ($(findstring $(RT28xx_MODE),AP),) +#WFLAGS += -DSPECIFIC_BCN_BUF_SUPPORT +endif + +endif + +ifneq ($(findstring 3290,$(CHIPSET)),) +WFLAGS += -DRTMP_MAC_PCI -DRTMP_PCI_SUPPORT -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT -DRTMP_FREQ_CALIBRATION_SUPPORT -DRTMP_INTERNAL_TX_ALC -DRT30xx -DRT3290 -DVCORECAL_SUPPORT +CHIPSET_DAT = 2860 + +ifneq ($(findstring $(RT28xx_MODE),STA APSTA),) +WFLAGS += -DRTMP_FREQ_CALIBRATION_SUPPORT -DPCIE_PS_SUPPORT +endif + +ifneq ($(findstring $(RT28xx_MODE),AP),) +WFLAGS += -DSPECIFIC_BCN_BUF_SUPPORT +endif +endif + + +ifeq ($(CHIPSET),USB) +#3572 +WFLAGS +=-DRTMP_MAC_USB -DRTMP_USB_SUPPORT -DRT2870 -DRT28xx -DRT30xx -DRT35xx -DRTMP_TIMER_TASK_SUPPORT -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT -DA_BAND_SUPPORT -DSPECIFIC_VCORECAL_SUPPORT +#3370 +WFLAGS += -DRT33xx -DRT3070 -DRT3370 -DRTMP_TIMER_TASK_SUPPORT -DRTMP_INTERNAL_TX_ALC +CHIPSET_DAT = 2870 +endif + + +ifeq ($(CHIPSET),PCI) +#3562 +WFLAGS +=-DRTMP_MAC_PCI -DRT2860 -DRT28xx -DRT30xx -DRT35xx -DRTMP_PCI_SUPPORT -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT -DA_BAND_SUPPORT -DSPECIFIC_VCORECAL_SUPPORT +#3390 +WFLAGS +=-DRT33xx -DRT3090 -DRT3390 -DRTMP_INTERNAL_TX_ALC +endif + + +ifeq ($(CHIPSET),RBUS) +WFLAGS += -DMERGE_ARCH_TEAM -DCONFIG_SWMCU_SUPPORT -DCONFIG_RA_NAT_NONE -DRTMP_RBUS_SUPPORT +#5350, 3050, 3350, 3883 +WFLAGS +=-DRTMP_MAC_PCI -DRT305x -DRT5350 -DRT3050 -DRT3350 -DRT3352 -DRT3883 -DRTMP_PCI_SUPPORT -DRTMP_RF_RW_SUPPORT -DA_BAND_SUPPORT -DVCORECAL_SUPPORT + +ifneq ($(findstring $(RT28xx_MODE),AP),) +WFLAGS += -DSPECIFIC_BCN_BUF_SUPPORT +endif +#WFLAGS += -DDBG_CTRL_SUPPORT +#WFLAGS += -DINCLUDE_DEBUG_QUEUE +#WFLAGS += -DRANGE_EXTEND -DCFO_TRACK -DPRE_ANT_SWITCH +endif + + +################################################# + + +ifeq ($(PLATFORM),5VT) +#WFLAGS += -DCONFIG_5VT_ENHANCE +endif + +ifeq ($(HAS_BLOCK_NET_IF),y) +WFLAGS += -DBLOCK_NET_IF +endif + +ifeq ($(HAS_DFS_SUPPORT),y) +WFLAGS += -DDFS_SUPPORT +endif + +ifeq ($(HAS_MC_SUPPORT),y) +WFLAGS += -DMULTIPLE_CARD_SUPPORT +endif + +ifeq ($(HAS_LLTD),y) +WFLAGS += -DLLTD_SUPPORT +endif + +ifeq ($(PLATFORM),RMI) +WFLAGS += -DRT_BIG_ENDIAN +endif + +ifeq ($(PLATFORM),UBICOM_IPX8) +WFLAGS += -DRT_BIG_ENDIAN -DUNALIGNMENT_SUPPORT -DPLATFORM_UBM_IPX8 -DNO_CONSISTENT_MEM_SUPPORT -DCACHE_LINE_32B +endif + +ifeq ($(PLATFORM),BL2348) +WFLAGS += -DRT_BIG_ENDIAN +endif + +ifeq ($(PLATFORM),BL23570) +WFLAGS += -DRT_BIG_ENDIAN +endif + +ifeq ($(PLATFORM),BLUBB) +WFLAGS += -DRT_BIG_ENDIAN +endif + +ifeq ($(PLATFORM),BLPMP) +WFLAGS += -DRT_BIG_ENDIAN +endif + +ifeq ($(PLATFORM),RMI_64) +WFLAGS += -DRT_BIG_ENDIAN +endif +ifeq ($(PLATFORM),IXP) +WFLAGS += -DRT_BIG_ENDIAN +endif + +ifeq ($(PLATFORM),IKANOS_V160) +WFLAGS += -DRT_BIG_ENDIAN -DIKANOS_VX_1X0 +endif + +ifeq ($(PLATFORM),IKANOS_V180) +WFLAGS += -DRT_BIG_ENDIAN -DIKANOS_VX_1X0 +endif + +ifeq ($(PLATFORM),INF_TWINPASS) +WFLAGS += -DRT_BIG_ENDIAN -DINF_TWINPASS +endif + +ifeq ($(PLATFORM),INF_DANUBE) +ifneq (,$(findstring 2.4,$(LINUX_SRC))) +# Linux 2.4 +WFLAGS += -DINF_DANUBE -DRT_BIG_ENDIAN +else +# Linux 2.6 +WFLAGS += -DRT_BIG_ENDIAN +endif +endif + +ifeq ($(PLATFORM),INF_AR9) +WFLAGS += -DRT_BIG_ENDIAN -DINF_AR9 +# support MAPI function for AR9. +#WFLAGS += -DAR9_MAPI_SUPPORT +endif + +ifeq ($(PLATFORM),INF_VR9) +WFLAGS += -DRT_BIG_ENDIAN -DINF_AR9 -DINF_VR9 +endif + +ifeq ($(PLATFORM),CAVM_OCTEON) +WFLAGS += -DRT_BIG_ENDIAN +endif + +ifeq ($(PLATFORM),BRCM_6358) +WFLAGS += -DRT_BIG_ENDIAN -DBRCM_6358 +endif + +ifeq ($(PLATFORM),INF_AMAZON_SE) +WFLAGS += -DRT_BIG_ENDIAN -DINF_AMAZON_SE +endif + +ifeq ($(PLATFORM),RALINK_3052) +WFLAGS += -DPLATFORM_RALINK_3052 +endif + +ifeq ($(PLATFORM),FREESCALE8377) +#EXTRA_CFLAGS := -v -I$(RT28xx_DIR)/include -I$(LINUX_SRC)/include $(WFLAGS)-O2 -Wall -Wstrict-prototypes -Wno-trigraphs +#export EXTRA_CFLAGS +WFLAGS += -DRT_BIG_ENDIAN +EXTRA_CFLAGS := $(WFLAGS) -I$(RT28xx_DIR)/include +endif + +ifeq ($(PLATFORM),ST) +#WFLAGS += -DST +WFLAGS += -DST +endif + +#kernel build options for 2.4 +# move to Makefile outside LINUX_SRC := /opt/star/kernel/linux-2.4.27-star + +ifeq ($(PLATFORM),RALINK_3052) +CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include/asm-mips/mach-generic -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -finline-limit=100000 -march=mips2 -mabi=32 -Wa,--trap -DLINUX -nostdinc -iwithprefix include $(WFLAGS) +export CFLAGS +endif + +ifeq ($(PLATFORM), RALINK_2880) +CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -finline-limit=100000 -march=mips2 -mabi=32 -Wa,--trap -DLINUX -nostdinc -iwithprefix include $(WFLAGS) +export CFLAGS +endif + +ifeq ($(PLATFORM),STAR) +CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -Uarm -fno-common -pipe -mapcs-32 -D__LINUX_ARM_ARCH__=4 -march=armv4 -mshort-load-bytes -msoft-float -Uarm -DMODULE -DMODVERSIONS -include $(LINUX_SRC)/include/linux/modversions.h $(WFLAGS) + +export CFLAGS +endif + +ifeq ($(PLATFORM),UBICOM_IPX8) +EXTRA_CFLAGS += $(WFLAGS) -I$(RT28xx_DIR)/include +export EXTRA_CFLAGS +endif + +ifeq ($(PLATFORM),SIGMA) +CFLAGS := -D__KERNEL__ -I$(RT28xx_DIR)/include -I$(LINUX_SRC)/include -I$(LINUX_SRC)/include/asm/gcc -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -DEM86XX_CHIP=EM86XX_CHIPID_TANGO2 -DEM86XX_REVISION=6 -I$(LINUX_SRC)/include/asm-mips/mach-generic -I$(RT2860_DIR)/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -mabi=32 -march=mips32r2 -Wa,-32 -Wa,-march=mips32r2 -Wa,-mips32r2 -Wa,--trap -DMODULE $(WFLAGS) -DSIGMA863X_PLATFORM + +export CFLAGS +endif + +ifeq ($(PLATFORM),SIGMA_8622) +CFLAGS := -D__KERNEL__ -I$(CROSS_COMPILE_INCLUDE)/include -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fno-common -pipe -fno-builtin -D__linux__ -DNO_MM -mapcs-32 -march=armv4 -mtune=arm7tdmi -msoft-float -DMODULE -mshort-load-bytes -nostdinc -iwithprefix -DMODULE $(WFLAGS) +export CFLAGS +endif + +ifeq ($(PLATFORM),5VT) +CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -mlittle-endian -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -O3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-omit-frame-pointer -mapcs -mno-sched-prolog -mabi=apcs-gnu -mno-thumb-interwork -D__LINUX_ARM_ARCH__=5 -march=armv5te -mtune=arm926ej-s --param max-inline-insns-single=40000 -Uarm -Wdeclaration-after-statement -Wno-pointer-sign -DMODULE $(WFLAGS) + +export CFLAGS +endif + +ifeq ($(PLATFORM),IKANOS_V160) +CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(LINUX_SRC)/include/asm/gcc -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-generic -I$(RT28xx_DIR)/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -march=lx4189 -Wa, -DMODULE $(WFLAGS) +export CFLAGS +endif + +ifeq ($(PLATFORM),IKANOS_V180) +CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(LINUX_SRC)/include/asm/gcc -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-generic -I$(RT28xx_DIR)/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -mips32r2 -Wa, -DMODULE $(WFLAGS) +export CFLAGS +endif + +ifeq ($(PLATFORM),INF_TWINPASS) +CFLAGS := -D__KERNEL__ -DMODULE -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -G 0 -mno-abicalls -fno-pic -march=4kc -mips32 -Wa,--trap -pipe -mlong-calls $(WFLAGS) +export CFLAGS +endif + +ifeq ($(PLATFORM),INF_DANUBE) + ifneq (,$(findstring 2.4,$(LINUX_SRC))) + CFLAGS := -I$(RT28xx_DIR)/include $(WFLAGS) -Wundef -fno-strict-aliasing -fno-common -ffreestanding -Os -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap -I$(LINUX_SRC)/include/asm-mips/mach-generic + else + CFLAGS := -I$(RT28xx_DIR)/include $(WFLAGS) -Wundef -fno-strict-aliasing -fno-common -ffreestanding -Os -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -mabi=32 -march=mips32r2 -Wa,-32 -Wa,-march=mips32r2 -Wa,-mips32r2 -Wa,--trap -I$(LINUX_SRC)/include/asm-mips/mach-generic + endif +export CFLAGS +endif + +ifeq ($(PLATFORM),INF_AR9) +CFLAGS := -I$(RT28xx_DIR)/include $(WFLAGS) -Wundef -fno-strict-aliasing -fno-common -fno-pic -ffreestanding -Os -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -mabi=32 -mlong-calls -march=mips32r2 -mtune=34kc -march=mips32r2 -Wa,-32 -Wa,-march=mips32r2 -Wa,-mips32r2 -Wa,--trap -I$(LINUX_SRC)/include/asm-mips/mach-generic +export CFLAGS +endif + +ifeq ($(PLATFORM),INF_VR9) +CFLAGS := -I$(RT28xx_DIR)/include $(WFLAGS) -Wundef -fno-strict-aliasing -fno-common -fno-pic -ffreestanding -Os -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -mabi=32 -mlong-calls -march=mips32r2 -march=mips32r2 -Wa,-32 -Wa,-march=mips32r2 -Wa,-mips32r2 -Wa,--trap -I$(LINUX_SRC)/include/asm-mips/mach-generic +export CFLAGS +endif + +ifeq ($(PLATFORM),BRCM_6358) +CFLAGS := $(WFLAGS) -I$(RT28xx_DIR)/include -nostdinc -iwithprefix include -D__KERNEL__ -Wall -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -I $(LINUX_SRC)/include/asm/gcc -G 0 -mno-abicalls -fno-pic -pipe -finline-limit=100000 -mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap -I$(LINUX_SRC)/include/asm-mips/mach-bcm963xx -I$(LINUX_SRC)/include/asm-mips/mach-generic -Os -fomit-frame-pointer -Wdeclaration-after-statement -DMODULE -mlong-calls +export CFLAGS +endif + +ifeq ($(PLATFORM),INF_AMAZON_SE) +CFLAGS := -D__KERNEL__ -DMODULE=1 -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -DCONFIG_IFX_ALG_QOS -DCONFIG_WAN_VLAN_SUPPORT -fomit-frame-pointer -DIFX_PPPOE_FRAME -G 0 -fno-pic -mno-abicalls -mlong-calls -pipe -finline-limit=100000 -mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap -nostdinc -iwithprefix include $(WFLAGS) +export CFLAGS +endif + +ifeq ($(PLATFORM),ST) +CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -Wall -O2 -Wundef -Wstrict-prototypes -Wno-trigraphs -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-aliasing -fno-common -fomit-frame-pointer -ffreestanding -m4-nofpu -o $(WFLAGS) +export CFLAGS +endif + +ifeq ($(PLATFORM),PC) + ifneq (,$(findstring 2.4,$(LINUX_SRC))) + # Linux 2.4 + CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe -mpreferred-stack-boundary=2 -march=i686 -DMODULE -DMODVERSIONS -include $(LINUX_SRC)/include/linux/modversions.h $(WFLAGS) + export CFLAGS + else + # Linux 2.6 + EXTRA_CFLAGS := $(WFLAGS) -I$(RT28xx_DIR)/include + endif +endif + +ifeq ($(PLATFORM),INTELP6) + EXTRA_CFLAGS := $(WFLAGS) -I$(RT28xx_DIR)/include +endif + +#If the kernel version of RMI is newer than 2.6.27, please change "CFLAGS" to "EXTRA_FLAGS" +ifeq ($(PLATFORM),RMI) +EXTRA_CFLAGS := -D__KERNEL__ -DMODULE=1 -I$(LINUX_SRC)/include -I$(LINUX_SRC)/include/asm-mips/mach-generic -I$(RT28xx_DIR)/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -DCONFIG_IFX_ALG_QOS -DCONFIG_WAN_VLAN_SUPPORT -fomit-frame-pointer -DIFX_PPPOE_FRAME -G 0 -fno-pic -mno-abicalls -mlong-calls -pipe -finline-limit=100000 -mabi=32 -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -march=xlr -ffreestanding -march=xlr -Wa,--trap, -nostdinc -iwithprefix include $(WFLAGS) +export EXTRA_CFLAGS +endif + +ifeq ($(PLATFORM),RMI_64) +EXTRA_CFLAGS := -D__KERNEL__ -DMODULE=1 -I$(LINUX_SRC)/include -I$(LINUX_SRC)/include/asm-mips/mach-generic -I$(RT28xx_DIR)/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -DCONFIG_IFX_ALG_QOS -DCONFIG_WAN_VLAN_SUPPORT -fomit-frame-pointer -DIFX_PPPOE_FRAME -G 0 -fno-pic -mno-abicalls -mlong-calls -pipe -finline-limit=100000 -mabi=64 -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -march=xlr -ffreestanding -march=xlr -Wa,--trap, -nostdinc -iwithprefix include $(WFLAGS) +export EXTRA_CFLAGS +endif + +ifeq ($(PLATFORM),IXP) + CFLAGS := -v -D__KERNEL__ -DMODULE -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -mbig-endian -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -Uarm -fno-common -pipe -mapcs-32 -D__LINUX_ARM_ARCH__=5 -mcpu=xscale -mtune=xscale -malignment-traps -msoft-float $(WFLAGS) + EXTRA_CFLAGS := -v $(WFLAGS) -I$(RT28xx_DIR)/include -mbig-endian + export CFLAGS +endif + +ifeq ($(PLATFORM),SMDK) + EXTRA_CFLAGS := $(WFLAGS) -I$(RT28xx_DIR)/include +endif + +ifeq ($(PLATFORM),CAVM_OCTEON) + EXTRA_CFLAGS := $(WFLAGS) -I$(RT28xx_DIR)/include \ + -mabi=64 $(WFLAGS) +export CFLAGS +endif + +ifeq ($(PLATFORM),DM6446) + CFLAGS := -nostdinc -iwithprefix include -D__KERNEL__ -I$(RT28xx_DIR)/include -I$(LINUX_SRC)/include -Wall -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Os -fno-omit-frame-pointer -fno-omit-frame-pointer -mapcs -mno-sched-prolog -mlittle-endian -mabi=apcs-gnu -D__LINUX_ARM_ARCH__=5 -march=armv5te -mtune=arm9tdmi -msoft-float -Uarm -Wdeclaration-after-statement -c -o $(WFLAGS) +export CFLAGS +endif + +ifeq ($(PLATFORM),BL2348) +CFLAGS := -D__KERNEL__ -I$(RT28xx_DIR)/include -I$(LINUX_SRC)/include -I$(LINUX_SRC)/include/asm/gcc -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -DEM86XX_CHIP=EM86XX_CHIPID_TANGO2 -DEM86XX_REVISION=6 -I$(LINUX_SRC)/include/asm-mips/mach-generic -I$(RT2860_DIR)/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -mabi=32 -march=mips32r2 -Wa,-32 -Wa,-march=mips32r2 -Wa,-mips32r2 -Wa,--trap -DMODULE $(WFLAGS) -DSIGMA863X_PLATFORM -DEXPORT_SYMTAB -DPLATFORM_BL2348 +export CFLAGS +endif + +ifeq ($(PLATFORM),BL23570) +EXTRA_CFLAGS := -D__KERNEL__ -I$(RT28xx_DIR)/include -I$(LINUX_SRC)/include -I$(LINUX_SRC)/include/asm/gcc -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -DEM86XX_CHIP=EM86XX_CHIPID_TANGO2 -DEM86XX_REVISION=6 -I$(LINUX_SRC)/include/asm-mips/mach-generic -I$(RT2860_DIR)/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -mabi=32 -march=74kc -Wa,-32 -Wa,-march=mips32r2 -Wa,-mips32r2 -Wa,--trap -DMODULE $(WFLAGS) -DSIGMA863X_PLATFORM -DEXPORT_SYMTAB -DPLATFORM_BL23570 +export EXTRA_CFLAGS +endif + +ifeq ($(PLATFORM),BLUBB) +CFLAGS := -D__KERNEL__ -I$(RT28xx_DIR)/include -I$(LINUX_SRC)/include -I$(LINUX_SRC)/include/asm/gcc -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -DEM86XX_CHIP=EM86XX_CHIPID_TANGO2 -DEM86XX_REVISION=6 -I$(LINUX_SRC)/include/asm-mips/mach-generic -I$(RT2860_DIR)/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -mabi=32 -march=mips32r2 -Wa,-32 -Wa,-march=mips32r2 -Wa,-mips32r2 -Wa,--trap -DMODULE $(WFLAGS) -DSIGMA863X_PLATFORM -DEXPORT_SYMTAB -DPLATFORM_BL2348 +export CFLAGS +endif + +ifeq ($(PLATFORM),BLPMP) +CFLAGS := -D__KERNEL__ -I$(RT28xx_DIR)/include -I$(LINUX_SRC)/include -I$(LINUX_SRC)/include/asm/gcc -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -DEM86XX_CHIP=EM86XX_CHIPID_TANGO2 -DEM86XX_REVISION=6 -I$(LINUX_SRC)/include/asm-mips/mach-generic -I$(RT2860_DIR)/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -mabi=32 -march=mips32r2 -Wa,-32 -Wa,-march=mips32r2 -Wa,-mips32r2 -Wa,--trap -DMODULE $(WFLAGS) -DSIGMA863X_PLATFORM -DEXPORT_SYMTAB +export CFLAGS +endif + +ifeq ($(PLATFORM),MT85XX) + ifneq (,$(findstring 2.4,$(LINUX_SRC))) + # Linux 2.4 + CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe -mpreferred-stack-boundary=2 -march=i686 -DMODULE -DMODVERSIONS -include $(LINUX_SRC)/include/linux/modversions.h $(WFLAGS) + export CFLAGS + else + # Linux 2.6 + EXTRA_CFLAGS += $(WFLAGS) -I$(RT28xx_DIR)/include + EXTRA_CFLAGS += -D _NO_TYPEDEF_BOOL_ \ + -D _NO_TYPEDEF_UCHAR_ \ + -D _NO_TYPEDEF_UINT8_ \ + -D _NO_TYPEDEF_UINT16_ \ + -D _NO_TYPEDEF_UINT32_ \ + -D _NO_TYPEDEF_UINT64_ \ + -D _NO_TYPEDEF_CHAR_ \ + -D _NO_TYPEDEF_INT32_ \ + -D _NO_TYPEDEF_INT64_ \ + + endif +endif + +ifeq ($(PLATFORM),NXP_TV550) + ifneq (,$(findstring 2.4,$(LINUX_SRC))) + # Linux 2.4 + CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe -mpreferred-stack-boundary=2 -march=mips -DMODULE -DMODVERSIONS -include $(LINUX_SRC)/include/linux/modversions.h $(WFLAGS) + export CFLAGS + else + # Linux 2.6 + EXTRA_CFLAGS := $(WFLAGS) -I$(RT28xx_DIR)/include + endif +endif + +ifeq ($(PLATFORM),MVL5) +CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -mlittle-endian -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -O3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-omit-frame-pointer -mapcs -mno-sched-prolog -mno-thumb-interwork -D__LINUX_ARM_ARCH__=5 -march=armv5te -mtune=arm926ej-s --param max-inline-insns-single=40000 -Uarm -Wdeclaration-after-statement -Wno-pointer-sign -DMODULE $(WFLAGS) +export CFLAGS +endif + +ifeq ($(PLATFORM),RALINK_3352) +CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include/asm-mips/mach-generic -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -finline-limit=100000 -march=mips2 -mabi=32 -Wa,--trap -DLINUX -nostdinc -iwithprefix include $(WFLAGS) +export CFLAGS +endif diff --git a/mt7620/src/os/linux/inf_ppa.c b/mt7620/src/os/linux/inf_ppa.c new file mode 100644 index 0000000..78a9f2b --- /dev/null +++ b/mt7620/src/os/linux/inf_ppa.c @@ -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, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering 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( + IN struct sk_buff *skb_p, + IN 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/mt7620/src/os/linux/pci_main_dev.c b/mt7620/src/os/linux/pci_main_dev.c new file mode 100644 index 0000000..e73b199 --- /dev/null +++ b/mt7620/src/os/linux/pci_main_dev.c @@ -0,0 +1,521 @@ +/* + *************************************************************************** + * 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 "rt_config.h" */ +#include "rtmp_comm.h" +#include "rt_os_util.h" +#include "rt_os_net.h" +#include + +/* */ +/* Function declarations */ +/* */ +/*extern int rt28xx_close(IN struct net_device *net_dev); */ +/*extern int rt28xx_open(struct net_device *net_dev); */ + +static VOID __devexit rt2860_remove_one(struct pci_dev *pci_dev); +static INT __devinit rt2860_probe(struct pci_dev *pci_dev, const struct pci_device_id *ent); +static void __exit rt2860_cleanup_module(void); +static int __init rt2860_init_module(void); + + +#ifdef CONFIG_PM +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,10) +#define pm_message_t u32 +#endif + +static int rt2860_suspend(struct pci_dev *pci_dev, pm_message_t state); +static int rt2860_resume(struct pci_dev *pci_dev); +#endif +#endif /* CONFIG_PM */ + +/* */ +/* Ralink PCI device table, include all supported chipsets */ +/* */ +static struct pci_device_id rt2860_pci_tbl[] __devinitdata = +{ +#ifdef RT2860 + {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2860_PCI_DEVICE_ID)}, /*RT28602.4G */ + {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2860_PCIe_DEVICE_ID)}, + {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2760_PCI_DEVICE_ID)}, + {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2790_PCIe_DEVICE_ID)}, + {PCI_DEVICE(VEN_AWT_PCI_VENDOR_ID, VEN_AWT_PCIe_DEVICE_ID)}, + {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7708)}, + {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7728)}, + {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7758)}, + {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7727)}, + {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7738)}, + {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7748)}, + {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7768)}, +#endif /* RT2860 */ + {0,} /* terminate list */ +}; + +MODULE_DEVICE_TABLE(pci, rt2860_pci_tbl); +#ifdef CONFIG_STA_SUPPORT +#ifdef MODULE_VERSION +MODULE_VERSION(STA_DRIVER_VERSION); +#endif +#endif /* CONFIG_STA_SUPPORT */ + + +/* */ +/* Our PCI driver structure */ +/* */ +static struct pci_driver rt2860_driver = +{ + name: RTMP_DRV_NAME, + id_table: rt2860_pci_tbl, + probe: rt2860_probe, +#if LINUX_VERSION_CODE >= 0x20412 + remove: __devexit_p(rt2860_remove_one), +#else + remove: __devexit(rt2860_remove_one), +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#ifdef CONFIG_PM + suspend: rt2860_suspend, + resume: rt2860_resume, +#endif +#endif +}; + + +/*************************************************************************** + * + * PCI device initialization related procedures. + * + ***************************************************************************/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#ifdef CONFIG_PM + +VOID RT2860RejectPendingPackets( + IN VOID *pAd) +{ + /* clear PS packets */ + /* clear TxSw packets */ +} + +static int rt2860_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, ("===> rt2860_suspend()\n")); + + 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, ("<=== rt2860_suspend()\n")); + return retval; +} + +static int rt2860_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) */ + /* in include/linux/pci.h, you can find that */ + /* #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, ("===> rt2860_resume()\n")); + + 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, ("<=== rt2860_resume()\n")); + 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, ("<=== rt2860_resume()\n")); + return 0; +} +#endif /* CONFIG_PM */ +#endif + + +static INT __init rt2860_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(&rt2860_driver); +#else + return pci_module_init(&rt2860_driver); +#endif +} + + +/* */ +/* Driver module unload function */ +/* */ +static VOID __exit rt2860_cleanup_module(VOID) +{ + pci_unregister_driver(&rt2860_driver); +} + +module_init(rt2860_init_module); +module_exit(rt2860_cleanup_module); + + +/* */ +/* PCI device probe & initialization function */ +/* */ +static INT __devinit rt2860_probe( + IN struct pci_dev *pci_dev, + IN const struct pci_device_id *pci_id) +{ + VOID *pAd = NULL; + struct net_device *net_dev; + PVOID handle; + PSTRING print_name; + ULONG csr_addr; + INT rv = 0; + RTMP_OS_NETDEV_OP_HOOK netDevHook; + ULONG OpMode; + + DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_probe\n")); + +/*PCIDevInit============================================== */ + /* wake up and enable device */ + if ((rv = pci_enable_device(pci_dev))!= 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 = pci_name(pci_dev); +#else + print_name = pci_dev->slot_name; +#endif /* LINUX_VERSION_CODE */ + + if ((rv = pci_request_regions(pci_dev, 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(pci_dev, 0), pci_resource_len(pci_dev, 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(pci_dev, 0), (ULONG)pci_resource_start(pci_dev, 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(pci_dev, 0), (ULONG)csr_addr, pci_dev->irq)); + } + + /* Set DMA master */ + pci_set_master(pci_dev); + + +/*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 == 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 = pci_dev; + +#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 pci_dev for allocate structure of "RTMP_ADAPTER" */ + if (rv != NDIS_STATUS_SUCCESS) + goto err_out_iounmap; + /* Here are the RTMP_ADAPTER structure with pci-bus specific parameters. */ +/* pAd->CSRBaseAddress = (PUCHAR)csr_addr; */ + RTMP_DRIVER_PCI_CSR_SET(pAd, csr_addr); + +/* RTMPInitPCIeDevice(pci_dev, pAd); */ + RTMP_DRIVER_PCIE_INIT(pAd, pci_dev); + +/*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 = pci_dev->irq; /* Interrupt IRQ number */ + net_dev->base_addr = csr_addr; /* Save CSR virtual address and irq to device structure */ + pci_set_drvdata(pci_dev, 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, &(pci_dev->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 = &(pci_dev->dev); */ +/* pAd->CFG80211_Register = CFG80211_Register; */ +/* RTMP_DRIVER_CFG80211_INIT(pAd, pci_dev); */ + + /* + 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, &(pci_dev->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 KTHREAD_SUPPORT */ +#ifdef PRE_ASSIGN_MAC_ADDR + UCHAR PermanentAddress[MAC_ADDR_LEN]; + RTMP_DRIVER_MAC_ADDR_GET(pAd, &PermanentAddress[0]); + DBGPRINT(RT_DEBUG_TRACE, ("@%s MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, PermanentAddress[0], PermanentAddress[1],PermanentAddress[2],PermanentAddress[3],PermanentAddress[4],PermanentAddress[5])); + /* Set up the Mac address */ + RtmpOSNetDevAddrSet(OpMode, net_dev, &PermanentAddress[0], NULL); +#endif /* PRE_ASSIGN_MAC_ADDR */ + + DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_probe\n")); + + 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(pci_dev, 0), pci_resource_len(pci_dev, 0)); + +err_out_free_res: + pci_release_regions(pci_dev); + +err_out: + pci_disable_device(pci_dev); + + DBGPRINT(RT_DEBUG_ERROR, ("<=== rt2860_probe failed with rv = %d!\n", rv)); + + return -ENODEV; /* probe fail */ +} + + +static VOID __devexit rt2860_remove_one( + IN struct pci_dev *pci_dev) +{ + PNET_DEV net_dev = pci_get_drvdata(pci_dev); + VOID *pAd = NULL; + ULONG csr_addr = net_dev->base_addr; /* pAd->CSRBaseAddress; */ + + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_remove_one\n")); + + if (pAd != NULL) + { + /* Unregister/Free all allocated net_device. */ + RtmpPhyNetDevExit(pAd, net_dev); + + /* 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)); + +#ifdef RT_CFG80211_SUPPORT + RTMP_DRIVER_80211_UNREGISTER(pAd, net_dev); +#endif /* RT_CFG80211_SUPPORT */ + + /* Free RTMP_ADAPTER related structures. */ + RtmpRaDevCtrlExit(pAd); + } + 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)); + } + + /* Free the root net_device */ + RtmpOSNetDevFree(net_dev); +} + + + + diff --git a/mt7620/src/os/linux/rbus_main_dev.c b/mt7620/src/os/linux/rbus_main_dev.c new file mode 100644 index 0000000..68370a7 --- /dev/null +++ b/mt7620/src/os/linux/rbus_main_dev.c @@ -0,0 +1,198 @@ +/* + *************************************************************************** + * 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 + -------- ---------- ---------------------------------------------- +*/ +#define RTMP_MODULE_OS + +#include "rt_config.h" + + +static struct net_device *rt2880_dev = NULL; + + +VOID __exit rt2880_module_exit(VOID); +int __init rt2880_module_init(VOID); + + +module_init(rt2880_module_init); +module_exit(rt2880_module_exit); + +#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 + +int 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; + + + DBGPRINT(RT_DEBUG_TRACE, ("===> 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; + } + /* 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; //net_dev; + +#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(). + */ + CFG80211_Register(pAd, pAd->pCfgDev, pNetDev); +#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_TRACE, ("%s: at CSR addr 0x%lx, IRQ %u. \n", net_dev->name, (ULONG)csr_addr, net_dev->irq)); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== 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 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); + +#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(); +} + diff --git a/mt7620/src/os/linux/rt_linux.c b/mt7620/src/os/linux/rt_linux.c new file mode 100644 index 0000000..fdaecf5 --- /dev/null +++ b/mt7620/src/os/linux/rt_linux.c @@ -0,0 +1,5446 @@ +/**************************************************************************** + + 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 "rt_config.h" */ +#include "rtmp_comm.h" +#include "rtmp_osabl.h" +#include "rt_os_util.h" +#include "dot11i_wpa.h" + +#if defined(CONFIG_RA_HW_NAT) || defined(CONFIG_RA_HW_NAT_MODULE) +#if defined(CONFIG_SUPPORT_OPENWRT) +#include "../../../linux-kernel/net/nat/hw_nat/ra_nat.h" +#include "../../../linux-kernel/net/nat/hw_nat/frame_engine.h" +#else +#include "../../../../../../net/nat/hw_nat/ra_nat.h" +#include "../../../../../../net/nat/hw_nat/frame_engine.h" +#endif /* CONFIG_SUPPORT_OPENWRT */ +#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 + +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 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(IN VOID *pRscSrc, + IN UINT32 RscLen); +BOOLEAN RTMP_OS_Remove_Rsc(IN LIST_HEADER *pRscList, + IN 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)) { + init_timer(pTimer); + pTimer->data = (unsigned long)data; + pTimer->function = function; + } +} + +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( + IN ULONG usec) +{ + ULONG i; + + for (i = 0; i < (usec / 50); i++) + udelay(50); + + if (usec % 50) + udelay(usec % 50); +} + +VOID RtmpOsMsDelay( + IN ULONG msec) +{ + mdelay(msec); +} + +void RTMP_GetCurrentSystemTime( + LARGE_INTEGER * time) +{ + time->u.LowPart = jiffies; +} + +void RTMP_GetCurrentSystemTick( + ULONG *pNow) +{ + *pNow = jiffies; +} + +/* 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) +/* The flag "CONFIG_RALINK_FLASH_API" is used for APSoC Linux SDK */ +#ifdef CONFIG_RALINK_FLASH_API + +int32_t FlashRead( + uint32_t *dst, + uint32_t *src, + uint32_t count); + +int32_t FlashWrite( + uint16_t *source, + uint16_t *destination, + uint32_t numBytes); +#define NVRAM_OFFSET 0x30000 +#if defined (CONFIG_RT2880_FLASH_32M) +#define RF_OFFSET 0x1FE0000 +#else +#ifdef RTMP_FLASH_SUPPORT +#define RF_OFFSET 0x48000 +#else +#define RF_OFFSET 0x40000 +#endif /* RTMP_FLASH_SUPPORT */ +#endif + +#else /* CONFIG_RALINK_FLASH_API */ + +#ifdef RA_MTD_RW_BY_NUM +#if defined (CONFIG_RT2880_FLASH_32M) +#define MTD_NUM_FACTORY 5 +#else +#define MTD_NUM_FACTORY 2 +#endif +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); +#else +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); +#endif + +#endif /* CONFIG_RALINK_FLASH_API */ + +void RtmpFlashRead( + UCHAR * p, + ULONG a, + ULONG b) +{ +#ifdef CONFIG_RALINK_FLASH_API + FlashRead((uint32_t *) p, (uint32_t *) a, (uint32_t) b); +#else +#ifdef RA_MTD_RW_BY_NUM + ra_mtd_read(MTD_NUM_FACTORY, 0, (size_t) b, p); +#else + ra_mtd_read_nm("Factory", a&0xFFFF, (size_t) b, p); +#endif +#endif /* CONFIG_RALINK_FLASH_API */ +} + +void RtmpFlashWrite( + UCHAR * p, + ULONG a, + ULONG b) +{ +#ifdef CONFIG_RALINK_FLASH_API + FlashWrite((uint16_t *) p, (uint16_t *) a, (uint32_t) b); +#else +#ifdef RA_MTD_RW_BY_NUM + ra_mtd_write(MTD_NUM_FACTORY, 0, (size_t) b, p); +#else + ra_mtd_write_nm("Factory", a&0xFFFF, (size_t) b, p); +#endif +#endif /* CONFIG_RALINK_FLASH_API */ +} +#endif /* defined(RTMP_RBUS_SUPPORT) || defined (RTMP_FLASH_SUPPORT) */ + +PNDIS_PACKET RtmpOSNetPktAlloc( + IN VOID *pReserved, + IN 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( + IN VOID *pReserved, + IN ULONG Length) +{ + struct sk_buff *pkt; + + pkt = dev_alloc_skb(Length); + + if (pkt == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("can't allocate frag rx %ld size packet\n", Length)); + } + + if (pkt) { + MEM_DBG_PKT_ALLOC_INC(pkt); + RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS); + } + + return (PNDIS_PACKET) pkt; +} + + + +/* the allocated NDIS PACKET must be freed via RTMPFreeNdisPacket() */ +NDIS_STATUS RTMPAllocateNdisPacket( + IN VOID *pReserved, + OUT PNDIS_PACKET *ppPacket, + IN PUCHAR pHeader, + IN UINT HeaderLen, + IN PUCHAR pData, + IN UINT DataLen) +{ + PNDIS_PACKET pPacket; + ASSERT(pData); + ASSERT(DataLen); + + /* 1. Allocate a packet */ + pPacket = (PNDIS_PACKET) dev_alloc_skb(HeaderLen + DataLen + RTMP_PKT_TAIL_PADDING); + + + if (pPacket == NULL) { + *ppPacket = NULL; +#ifdef DEBUG + printk(KERN_ERR "RTMPAllocateNdisPacket Fail\n\n"); +#endif + return NDIS_STATUS_FAILURE; + } + MEM_DBG_PKT_ALLOC_INC(pPacket); + + /* 2. clone the frame content */ + if (HeaderLen > 0) + NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket), pHeader, HeaderLen); + if (DataLen > 0) + NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket) + HeaderLen, pData, + DataLen); + + /* 3. update length of packet */ + skb_put(GET_OS_PKT_TYPE(pPacket), HeaderLen + DataLen); + + RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS); +/* printk(KERN_ERR "%s : pPacket = %p, len = %d\n", __FUNCTION__, + pPacket, GET_OS_PKT_LEN(pPacket));*/ + *ppPacket = 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( + IN VOID *pReserved, + IN PNDIS_PACKET pPacket) +{ + dev_kfree_skb_any(RTPKT_TO_OSPKT(pPacket)); + MEM_DBG_PKT_FREE_INC(pPacket); +} + + +/* IRQL = DISPATCH_LEVEL */ +/* NOTE: we do have an assumption here, that Byte0 and Byte1 + * always reasid at the same scatter gather buffer + */ +NDIS_STATUS Sniff2BytesFromNdisBuffer( + IN PNDIS_BUFFER pFirstBuffer, + IN UCHAR DesiredOffset, + OUT PUCHAR pByte0, + OUT PUCHAR pByte1) +{ + *pByte0 = *(PUCHAR) (pFirstBuffer + DesiredOffset); + *pByte1 = *(PUCHAR) (pFirstBuffer + DesiredOffset + 1); + + return NDIS_STATUS_SUCCESS; +} + +void RTMP_QueryPacketInfo( + IN PNDIS_PACKET pPacket, + OUT PACKET_INFO * pPacketInfo, + OUT PUCHAR * pSrcBufVA, + OUT UINT * pSrcBufLen) +{ + pPacketInfo->BufferCount = 1; + pPacketInfo->pFirstBuffer = (PNDIS_BUFFER) GET_OS_PKT_DATAPTR(pPacket); + pPacketInfo->PhysicalBufferCount = 1; + pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket); + + *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket); + *pSrcBufLen = GET_OS_PKT_LEN(pPacket); +} + + +PNDIS_PACKET DuplicatePacket( + IN PNET_DEV pNetDev, + IN PNDIS_PACKET pPacket, + IN UCHAR FromWhichBSSID) +{ + struct sk_buff *skb; + PNDIS_PACKET pRetPacket = NULL; + USHORT DataSize; + UCHAR *pData; + + DataSize = (USHORT) GET_OS_PKT_LEN(pPacket); + pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket); + + skb = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG); + if (skb) { + MEM_DBG_PKT_ALLOC_INC(skb); + skb->dev = pNetDev; /*get_netdev_from_bssid(pAd, FromWhichBSSID); */ + 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; /*get_netdev_from_bssid(pAd, FromWhichBSSID); */ + pPacket = OSPKT_TO_RTPKT(skb); + } + + return pPacket; +} + +#define TKIP_TX_MIC_SIZE 8 +PNDIS_PACKET duplicate_pkt_with_TKIP_MIC( + IN VOID *pReserved, + IN 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); + } + /* End of if */ + return pPacket; +} /* End of duplicate_pkt_with_VLAN */ +#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 PUCHAR 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); + /*get_netdev_from_bssid(pAd, apidx)); */ + 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); + } + 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(pRxBlk->pRxPacket); */ + ASSERT(pHeader802_3); + + pOSPkt = RTPKT_TO_OSPKT(pRxPacket); + + /*get_netdev_from_bssid(pAd, FromWhichBSSID); */ + 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; + + /* VLAN related */ + if (VLAN_VID != 0) + VLAN_Size = LENGTH_802_1Q; + /* End of if */ + + 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 */ + +} + + + +void hex_dump( + char *str, + unsigned char *pSrcBufVA, + unsigned int SrcBufLen) +{ +#ifdef DBG + 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 */ + +#ifdef CONFIG_STA_SUPPORT +INT32 ralinkrate[] = { +2, 4, 11, 22, /* CCK */ +12, 18, 24, 36, 48, 72, 96, 108, /* OFDM */ +/* 20MHz, 800ns GI, MCS: 0 ~ 15 */ +13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234, 260, +39, 78, 117, 156, 234, 312, 351, 390, /* 20MHz, 800ns GI, MCS: 16 ~ 23 */ +/* 40MHz, 800ns GI, MCS: 0 ~ 15 */ +27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, +81, 162, 243, 324, 486, 648, 729, 810, /* 40MHz, 800ns GI, MCS: 16 ~ 23 */ +/* 20MHz, 400ns GI, MCS: 0 ~ 15 */ +14, 29, 43, 57, 87, 115, 130, 144, 29, 59, 87, 115, 173, 230, 260, 288, +43, 87, 130, 173, 260, 317, 390, 433, /* 20MHz, 400ns GI, MCS: 16 ~ 23 */ +/* 40MHz, 400ns GI, MCS: 0 ~ 15 */ +30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600, +90, 180, 270, 360, 540, 720, 810, 900}; /* 40MHz, 400ns GI, MCS: 16 ~ 23 */ + +UINT32 RT_RateSize = sizeof (ralinkrate); + +void send_monitor_packets(IN PNET_DEV pNetDev, + IN PNDIS_PACKET pRxPacket, + IN PHEADER_802_11 pHeader, + 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}; + + MEM_DBG_PKT_FREE_INC(pRxPacket); + + + pOSPkt = RTPKT_TO_OSPKT(pRxPacket); /*pRxBlk->pRxPacket); */ + pOSPkt->dev = pNetDev; /*get_netdev_from_bssid(pAd, BSS0); */ + if (pHeader->FC.Type == BTYPE_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; + } + + /*end if */ + if (DataSize < pOSPkt->len) { + skb_trim(pOSPkt, DataSize); + } else { + skb_put(pOSPkt, (DataSize - pOSPkt->len)); + } /*end if */ + + if ((pData - pOSPkt->data) > 0) { + skb_put(pOSPkt, (pData - pOSPkt->data)); + skb_pull(pOSPkt, (pData - pOSPkt->data)); + } + /*end if */ + 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; + } /*end if */ + } + /*end if */ + 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; + +#ifdef DOT11_N_SUPPORT + if (PHYMODE >= MODE_HTMIX) { + rate_index = + 12 + ((UCHAR) BW * 24) + ((UCHAR) ShortGI * 48) + + ((UCHAR) MCS); + } else +#endif /* DOT11_N_SUPPORT */ + if (PHYMODE == MODE_OFDM) + rate_index = (UCHAR) (MCS) + 4; + else + rate_index = (UCHAR) (MCS); + + if (rate_index < 0) + rate_index = 0; + if (rate_index >= + (sizeof (ralinkrate) / sizeof (ralinkrate[0]))) + rate_index = + (sizeof (ralinkrate) / sizeof (ralinkrate[0])) - 1; + + ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate; + ph->rate.status = 0; + ph->rate.len = 4; + /* real rate = ralinkrate[rate_index] / 2 */ + ph->rate.data = ralinkrate[rate_index]; + + 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; + + /* RXD_STRUC PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); */ + 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; + +} +#endif /* CONFIG_STA_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) { + /* 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 { + DBGPRINT(RT_DEBUG_ERROR, ("no file read method\n")); + return -1; + } +} + +int RtmpOSFileWrite(RTMP_OS_FD osfd, + char *pDataPtr, int writeLen) { + return osfd->f_op->write(osfd, + pDataPtr, + ( + size_t) writeLen, + &osfd->f_pos); +} + +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; +#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(IN OS_TASK *pTask) { +/* RTMP_ADAPTER *pAd; */ + int ret = NDIS_STATUS_FAILURE; + +/* pAd = (RTMP_ADAPTER *)pTask->priv; */ + +#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(IN 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(IN 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; +#ifdef P2P_SUPPORT + case RT_WLAN_EVENT_SHOWPIN: + eventType = 0x8C05; /* IWEVP2PKEYSHOWPIN; */ + break; + case RT_WLAN_EVENT_PIN: + eventType = 0x8C06; /* IWEVP2PKEYPIN; */ + break; +#endif /* P2P_SUPPORT */ + + 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) +{ +#ifdef DPA_S + RtmpOSNotifyRawData(pNetDev, &flags, sizeof(flags), 0, ETH_P_DPA_S_NOTIF); +#else + 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); +#endif + 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; +} + +int RtmpOSNetDevAddrSet(IN UCHAR OpMode, + IN PNET_DEV pNetDev, + IN PUCHAR pMacAddr, + IN PUCHAR dev_name) { + struct net_device *net_dev; +/* RTMP_ADAPTER *pAd; */ + + net_dev = pNetDev; +/* GET_PAD_FROM_NET_DEV(pAd, net_dev); */ + +#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) { +/* NdisZeroMemory(pAd->StaCfg.dev_name, 16); */ +/* NdisMoveMemory(pAd->StaCfg.dev_name, net_dev->name, strlen(net_dev->name)); */ + 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 + /* + if (MC_RowID >= 0) + sprintf(suffixName, "%02d_%d", MC_RowID, ifNameIdx); + */ + if (MC_RowID > 0) + sprintf(suffixName, "i%d", ifNameIdx); + else +#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(IN PNET_DEV pNetDev) +{ + dev_close(pNetDev); +} + +void RtmpOSNetDevFree(PNET_DEV pNetDev) +{ + DEV_PRIV_INFO *pDevInfo = NULL; + + + ASSERT(pNetDev); + + /* free assocaited private information */ + pDevInfo = _RTMP_OS_NETDEV_GET_PRIV(pNetDev); + if (pDevInfo != NULL) + os_free_mem(NULL, pDevInfo); + +#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) { + /* assign it as null first. */ + *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(IN 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(IN VOID *pReserved, + IN 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_netdev(pNetDev); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) + vfree(pNetDevOps); +#endif +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) +static void RALINK_ET_DrvInfoGet(IN struct net_device *pDev, + IN 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 /* LINUX_VERSION_CODE */ + +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) { +/* PRTMP_ADAPTER pAd = NULL; */ + +/* GET_PAD_FROM_NET_DEV(pAd, pNetDev); */ + +#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 (pDevOpHook->get_stats) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) + pNetDevOps->ndo_get_stats = pDevOpHook->get_stats; +#else + pNetDev->get_stats = 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, 0 /*privMemSize */ ); + if (status != NDIS_STATUS_SUCCESS) { + /* allocation fail, exit */ + 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) { + /* error! no any available ra name can be used! */ + 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 interface 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); + } /* End of if */ + } else { + /* no VLAN tag is needed to insert */ + memcpy(pData, pHeader802_3, HdrLen); + } /* End of if */ + + return VLAN_Size; +} /* End of VLAN_Tag_Insert */ +#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(IN PVOID handle, + OUT PVOID *ppAd, + IN UINT32 SizeOfpAd) { +/* RTMP_ADAPTER *pAd; */ +#ifdef WORKQUEUE_BH +/* POS_COOKIE cookie; */ +#endif /* WORKQUEUE_BH */ + + +#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(sizeof(RTMP_ADAPTER)); //pci_alloc_consistent(pci_dev, sizeof(RTMP_ADAPTER), phy_addr); */ + *ppAd = (PVOID) vmalloc(SizeOfpAd); /*pci_alloc_consistent(pci_dev, sizeof(RTMP_ADAPTER), phy_addr); */ +/* pAd = (RTMP_ADAPTER *)(*ppAd); */ + 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;//[1024]; + ULONG macAddr = 0; + UINT32 macValue = 0; + + os_alloc_mem(NULL, (UCHAR **)&msg, 1024); + + if (msg) + { + 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, "%08lx = %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;//[1024]; + USHORT eepAddr = 0; + USHORT eepValue; + + os_alloc_mem(NULL, (UCHAR **)&msg, 1024); + + if (msg) + { + 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 <= 0xFE) */ + while (eepAddr <= AddrEnd) { + /* RT28xx_EEPROM_READ16(pAd, eepAddr, eepValue); // sample */ + 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); + } +} + + +/* +======================================================================== +Routine Description: + Check if the network interface is up. + +Arguments: + *pDev - Network Interface + +Return Value: + None + +Note: +======================================================================== +*/ +BOOLEAN RtmpOSNetDevIsUp(IN VOID *pDev) { + struct net_device *pNetDev = (struct net_device *)pDev; + + if ((pNetDev == NULL) || !(pNetDev->flags & IFF_UP)) + return FALSE; + + return TRUE; +} + +/* +======================================================================== +Routine Description: + Wake up the command thread. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsCmdUp(IN RTMP_OS_TASK *pCmdQTask) { +#ifdef KTHREAD_SUPPORT + do { + OS_TASK *pTask = RTMP_OS_TASK_GET(pCmdQTask); + { + pTask->kthread_running = TRUE; + wake_up(&pTask->kthread_q); + } + } while (0); +#else + do { + OS_TASK *pTask = RTMP_OS_TASK_GET(pCmdQTask); + CHECK_PID_LEGALITY(pTask->taskPID) { + RTMP_SEM_EVENT_UP(&(pTask->taskSema)); + } + } while (0); +#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) { +} + +/* +======================================================================== +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 = pNetDev; +/* PRTMP_ADAPTER pAd = NULL; */ + +/* GET_PAD_FROM_NET_DEV(pAd, net_dev); */ + +/* ASSERT(pAd); */ + net_dev = net_dev; /* avoid compile warning */ + +#ifdef RTMP_PCI_SUPPORT + if (infType == RTMP_DEV_INF_PCI || infType == RTMP_DEV_INF_PCIE) { +/* POS_COOKIE pObj = (POS_COOKIE)(pAd->OS_Cookie); */ +#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(IN ULONG Size) { + return vmalloc(Size); +} + +/* +======================================================================== +Routine Description: + vfree + +Arguments: + pMem - the memory + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsVfree(IN VOID *pMem) { + if (pMem != NULL) + vfree(pMem); +} + +/* +======================================================================== +Routine Description: + Get network interface name. + +Arguments: + pDev - the device + +Return Value: + the name + +Note: +======================================================================== +*/ +char *RtmpOsGetNetDevName(IN VOID *pDev) { + return ((PNET_DEV) pDev)->name; +} + +/* +======================================================================== +Routine Description: + Assign protocol to the packet. + +Arguments: + pPkt - the packet + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsPktProtocolAssign(IN PNDIS_PACKET pNetPkt) { + struct sk_buff *pRxPkt = RTPKT_TO_OSPKT(pNetPkt); + pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev); +} + +BOOLEAN RtmpOsStatsAlloc(IN VOID **ppStats, + IN VOID **ppIwStats) { + os_alloc_mem(NULL, (UCHAR **) ppStats, + sizeof (struct net_device_stats)); + if ((*ppStats) == NULL) + return FALSE; + NdisZeroMemory((UCHAR *) *ppStats, sizeof (struct net_device_stats)); + +#if WIRELESS_EXT >= 12 + os_alloc_mem(NULL, (UCHAR **) ppIwStats, sizeof (struct iw_statistics)); + if ((*ppIwStats) == NULL) { + os_free_mem(NULL, *ppStats); + return FALSE; + } + NdisZeroMemory((UCHAR *)* ppIwStats, sizeof (struct iw_statistics)); +#endif + + return TRUE; +} + +/* +======================================================================== +Routine Description: + Pass the received packet to OS. + +Arguments: + pPkt - the packet + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsPktRcvHandle(IN PNDIS_PACKET pNetPkt) { + struct sk_buff *pRxPkt = RTPKT_TO_OSPKT(pNetPkt); + + + netif_rx(pRxPkt); +} + +VOID RtmpOsTaskPidInit(IN 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(IN 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 */ + +VOID RtmpOsPktNatMagicTag(IN PNDIS_PACKET pNetPkt) { +#ifdef RTMP_RBUS_SUPPORT +#if !defined(CONFIG_RA_NAT_NONE) +#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) + struct sk_buff *pRxPkt = RTPKT_TO_OSPKT(pNetPkt); + FOE_MAGIC_TAG(pRxPkt) = FOE_MAGIC_WLAN; +#endif /* CONFIG_RA_HW_NAT || CONFIG_RA_HW_NAT_MODULE */ +#endif /* CONFIG_RA_NAT_NONE */ +#endif /* RTMP_RBUS_SUPPORT */ +} + +VOID RtmpOsPktNatNone(IN PNDIS_PACKET pNetPkt) { +#ifdef RTMP_RBUS_SUPPORT +#if defined(CONFIG_RA_NAT_NONE) +#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) + FOE_AI(((struct sk_buff *)pNetPkt)) = UN_HIT; +#endif /* CONFIG_RA_HW_NAT || CONFIG_RA_HW_NAT_MODULE */ +#endif /* CONFIG_RA_NAT_NONE */ +#endif /* RTMP_RBUS_SUPPORT */ +} + + +#ifdef RT_CFG80211_SUPPORT +/* 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, +}; + +/* + 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, +}; + +/* +======================================================================== +Routine Description: + UnRegister MAC80211 Module. + +Arguments: + pCB - CFG80211 control block pointer + pNetDev - Network device + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID CFG80211OS_UnRegister( + IN VOID *pCB, + IN VOID *pNetDevOrg) +{ + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + struct net_device *pNetDev = (struct net_device *)pNetDevOrg; + + + /* unregister */ + if (pCfg80211_CB->pCfg80211_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); + /* End of if */ + + if (pCfg80211_CB->pCfg80211_Rates != NULL) + kfree(pCfg80211_CB->pCfg80211_Rates); + /* End of if */ + + 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); + } /* End of if */ + + os_free_mem(NULL, pCfg80211_CB); +} /* End of CFG80211OS_UnRegister */ + + +/* +======================================================================== +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 *pBandInfo, + 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, NumOfRate; + UINT32 IdLoop; + UINT32 CurTxPower; + + + /* sanity check */ + if (pBandInfo->RFICType == 0) + pBandInfo->RFICType = RFIC_24GHZ | RFIC_5GHZ; + /* End of if */ + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> RFICType = %d\n", + pBandInfo->RFICType)); + + /* init */ + if (pBandInfo->RFICType & RFIC_5GHZ) + NumOfChan = CFG80211_NUM_OF_CHAN_2GHZ + CFG80211_NUM_OF_CHAN_5GHZ; + else + NumOfChan = CFG80211_NUM_OF_CHAN_2GHZ; + /* End of if */ + + if (pBandInfo->FlgIsBMode == TRUE) + NumOfRate = 4; + else + NumOfRate = 4 + 8; + /* End of if */ + + if (pChannels == NULL) + { + pChannels = kzalloc(sizeof(*pChannels) * NumOfChan, GFP_KERNEL); + if (!pChannels) + { + DBGPRINT(RT_DEBUG_ERROR, ("80211> ieee80211_channel allocation fail!\n")); + return FALSE; + } /* End of if */ + } /* End of if */ + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> Number of channel = %d\n", + CFG80211_NUM_OF_CHAN_5GHZ)); + + 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; + } /* End of if */ + } /* End of if */ + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> Number of rate = %d\n", NumOfRate)); + + /* get TX power */ +#ifdef SINGLE_SKU + CurTxPower = pBandInfo->DefineMaxTxPwr; /* dBm */ +#else + CurTxPower = 0; /* unknown */ +#endif /* SINGLE_SKU */ + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> CurTxPower = %d dBm\n", CurTxPower)); + + /* init channel */ + for(IdLoop=0; IdLoopCfg80211_bands[IEEE80211_BAND_2GHZ]; + if (pBandInfo->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_DSSSCCK40; + pBand->ht_cap.ampdu_factor = 3; /* 2 ^ 16 */ + pBand->ht_cap.ampdu_density = pBandInfo->MpduDensity; + + memset(&pBand->ht_cap.mcs, 0, sizeof(pBand->ht_cap.mcs)); + CFG80211DBG(RT_DEBUG_ERROR, + ("80211> TxStream = %d\n", pBandInfo->TxStream)); + + switch(pBandInfo->TxStream) + { + case 1: + default: + pBand->ht_cap.mcs.rx_mask[0] = 0xff; + break; + + case 2: + pBand->ht_cap.mcs.rx_mask[0] = 0xff; + pBand->ht_cap.mcs.rx_mask[1] = 0xff; + 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; + break; + } /* End of switch */ + + 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; + } /* End of if */ + + pBand = &pCfg80211_CB->Cfg80211_bands[IEEE80211_BAND_5GHZ]; + if (pBandInfo->RFICType & RFIC_5GHZ) + { + pBand->n_channels = CFG80211_NUM_OF_CHAN_5GHZ; + pBand->n_bitrates = NumOfRate - 4; + pBand->channels = &pChannels[CFG80211_NUM_OF_CHAN_2GHZ]; + pBand->bitrates = &pRates[4]; + + /* for HT, assign pBand->ht_cap */ +#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_DSSSCCK40; + pBand->ht_cap.ampdu_factor = 3; /* 2 ^ 16 */ + pBand->ht_cap.ampdu_density = pBandInfo->MpduDensity; + + memset(&pBand->ht_cap.mcs, 0, sizeof(pBand->ht_cap.mcs)); + switch(pBandInfo->RxStream) + { + case 1: + default: + pBand->ht_cap.mcs.rx_mask[0] = 0xff; + break; + + case 2: + pBand->ht_cap.mcs.rx_mask[0] = 0xff; + pBand->ht_cap.mcs.rx_mask[1] = 0xff; + 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; + break; + } /* End of switch */ + + 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; + } /* End of if */ + + pCfg80211_CB->pCfg80211_Channels = pChannels; + pCfg80211_CB->pCfg80211_Rates = pRates; + + return TRUE; +} /* End of CFG80211_SupBandInit */ + + +/* +======================================================================== +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; + + + /* sanity check */ + if ((pCfg80211_CB == NULL) || (pCfg80211_CB->pCfg80211_Wdev == NULL)) + return FALSE; + /* End of if */ + + 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; + } /* End of if */ + + return FALSE; +} /* End of CFG80211OS_SupBandReInit */ + + +/* +======================================================================== +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; + } /* End of if */ + + /* hints a country IE as a regulatory domain "without" channel/power info. */ +/* regulatory_hint(pCfg80211_CB->pMac80211_Hw->wiphy, pCountryIe); */ + regulatory_hint(pCfg80211_CB->pCfg80211_Wdev->wiphy, (const char *)pCountryIe); +} /* End of CFG80211OS_RegHint */ + + +/* +======================================================================== +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; + } /* End of if */ + + 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->pMac80211_Hw->wiphy, pCountryIe, CountryIeLen); */ + regulatory_hint_11d(pCfg80211_CB->pCfg80211_Wdev->wiphy, pCountryIe, CountryIeLen); +#endif /* LINUX_VERSION_CODE */ +} /* End of CFG80211_RegHint11D */ + + +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; + + + /* sanity check */ + if (pWiphy == NULL) + { + if ((pCfg80211_CB != NULL) && (pCfg80211_CB->pCfg80211_Wdev != NULL)) + pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy; + /* End of if */ + } /* End of if */ + + 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; + + + /* sanity check */ + if (pWiphy == NULL) + { + if ((pCfg80211_CB != NULL) && (pCfg80211_CB->pCfg80211_Wdev != NULL)) + pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy; + /* End of if */ + } /* End of if */ + + 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; + + + /* sanity check */ + if (pWiphy == NULL) + { + if ((pCfg80211_CB != NULL) && (pCfg80211_CB->pCfg80211_Wdev != NULL)) + pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy; + /* End of if */ + } /* End of if */ + + 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; + /* End of if */ + + pChan->center_freq = ieee80211_channel_to_frequency(ChanId); + +#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 */ + /* End of if */ + } + else + pChan->max_bandwidth = 5; /* 5MHz for non-HT device */ + /* End of if */ +#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; */ + /* End of if */ + + 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; + UINT32 IdChan; + UINT32 CenFreq; + + + /* get channel information */ + CenFreq = ieee80211_channel_to_frequency(ChanId); + + for(IdChan=0; IdChanChanInfo[IdChan].center_freq == CenFreq) + break; + } + if (IdChan >= MAX_NUM_OF_CHANNELS) + { + DBGPRINT(RT_DEBUG_ERROR, ("80211> Can not find any chan info!\n")); + return; + } + + /* 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 */ + cfg80211_inform_bss_frame(pCfg80211_CB->pCfg80211_Wdev->wiphy, + &pCfg80211_CB->ChanInfo[IdChan], + (struct ieee80211_mgmt *)pFrame, + FrameLen, + RSSI, + GFP_ATOMIC); + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> cfg80211_inform_bss_frame\n")); +#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; + + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> cfg80211_scan_done\n")); + cfg80211_scan_done(pCfg80211_CB->pCfg80211_ScanReq, FlgIsAborted); +#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; + /* End of if */ + + 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); + } /* End of if */ +#endif /* LINUX_VERSION_CODE */ +} /* End of CFG80211_ConnectResultInform */ +#endif /* RT_CFG80211_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); +} + + +/* +======================================================================== +Routine Description: + Assign private data pointer to the network interface. + +Arguments: + pDev - the device + pPriv - the pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsSetNetDevPriv(IN VOID *pDev, + IN VOID *pPriv) { + + DEV_PRIV_INFO *pDevInfo = NULL; + + + pDevInfo = (DEV_PRIV_INFO *) _RTMP_OS_NETDEV_GET_PRIV((PNET_DEV) pDev); + + if (pDevInfo == NULL) + { + os_alloc_mem(NULL, (UCHAR **)&pDevInfo, sizeof(DEV_PRIV_INFO)); + if (pDevInfo == NULL) + return; + } + + pDevInfo->pPriv = (VOID *)pPriv; + pDevInfo->priv_flags = 0; + + _RTMP_OS_NETDEV_SET_PRIV((PNET_DEV) pDev, pDevInfo); +} + + +/* +======================================================================== +Routine Description: + Get private data pointer from the network interface. + +Arguments: + pDev - the device + pPriv - the pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID *RtmpOsGetNetDevPriv(IN VOID *pDev) { + + DEV_PRIV_INFO *pDevInfo = NULL; + + + pDevInfo = (DEV_PRIV_INFO *) _RTMP_OS_NETDEV_GET_PRIV((PNET_DEV) pDev); + if (pDevInfo != NULL) + return pDevInfo->pPriv; + return NULL; +} + + +/* +======================================================================== +Routine Description: + Get private flags from the network interface. + +Arguments: + pDev - the device + +Return Value: + pPriv - the pointer + +Note: +======================================================================== +*/ +USHORT RtmpDevPrivFlagsGet(IN VOID *pDev) { + + DEV_PRIV_INFO *pDevInfo = NULL; + + + pDevInfo = (DEV_PRIV_INFO *) _RTMP_OS_NETDEV_GET_PRIV((PNET_DEV) pDev); + if (pDevInfo != NULL) + return pDevInfo->priv_flags; + return 0; +} + + +/* +======================================================================== +Routine Description: + Get private flags from the network interface. + +Arguments: + pDev - the device + +Return Value: + pPriv - the pointer + +Note: +======================================================================== +*/ +VOID RtmpDevPrivFlagsSet(IN VOID *pDev, IN USHORT PrivFlags) { + + DEV_PRIV_INFO *pDevInfo = NULL; + + + pDevInfo = (DEV_PRIV_INFO *) _RTMP_OS_NETDEV_GET_PRIV((PNET_DEV) pDev); + if (pDevInfo != NULL) + pDevInfo->priv_flags = PrivFlags; +} + + + +#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(IN RTMP_OS_FS_INFO *pOSFSInfoOrg, + IN 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; + } + } +} + +/* +======================================================================== +Routine Description: + Activate a tasklet. + +Arguments: + pTasklet - the tasklet + +Return Value: + TRUE or FALSE + +Note: +======================================================================== +*/ +BOOLEAN RtmpOsTaskletSche(IN 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(IN RTMP_NET_TASK_STRUCT *pTasklet, + IN VOID (*pFunc) (unsigned long data), + IN ULONG Data, + IN LIST_HEADER * pTaskletList) { +#ifdef WORKQUEUE_BH + if (RTMP_OS_Alloc_RscOnly(pTasklet, + sizeof (struct work_struct)) == FALSE) { + return FALSE; /* allocate fail */ + } + + INIT_WORK((struct work_struct *)(pTasklet->pContent), pFunc); +#else + + if (RTMP_OS_Alloc_RscOnly(pTasklet, + sizeof (OS_NET_TASK_STRUCT)) == FALSE) { + return FALSE; /* allocate fail */ + } + + 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(IN 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(IN RTMP_NET_TASK_STRUCT *pTasklet, + IN ULONG Data) { +#ifndef WORKQUEUE_BH + if (pTasklet->pContent != NULL) + ((OS_NET_TASK_STRUCT *) (pTasklet->pContent))->data = + (ULONG) Data; +#endif /* WORKQUEUE_BH */ +} + +INT32 RtmpOsTaskIsKilled(IN RTMP_OS_TASK *pTaskOrg) { + OS_TASK *pTask; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (pTask == NULL) + return 1; + return pTask->task_killed; +} + +VOID RtmpOsTaskWakeUp(IN 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(IN RTMP_OS_TASK *pTaskOrg) { + OS_TASK *pTask; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (pTask == NULL) + 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(IN NDIS_MINIPORT_TIMER *pTimerOrg, + IN unsigned long timeout) { + OS_NDIS_MINIPORT_TIMER *pTimer; + + pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent); + if (pTimer != NULL) { + __RTMP_SetPeriodicTimer(pTimer, timeout); + } +} + +/* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */ +VOID RTMP_OS_Init_Timer(IN VOID *pReserved, + IN NDIS_MINIPORT_TIMER *pTimerOrg, + IN TIMER_FUNCTION function, + IN PVOID data, + IN LIST_HEADER *pTimerList) { + OS_NDIS_MINIPORT_TIMER *pTimer; + + if (RTMP_OS_Alloc_RscOnly(pTimerOrg, + sizeof (OS_NDIS_MINIPORT_TIMER)) == FALSE) { + return; /* allocate fail */ + } + + pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent); + + if (pTimer != NULL) { + __RTMP_OS_Init_Timer(pReserved, pTimer, function, data); + } +} + +VOID RTMP_OS_Add_Timer(IN NDIS_MINIPORT_TIMER *pTimerOrg, + IN unsigned long timeout) { + OS_NDIS_MINIPORT_TIMER *pTimer; + + pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent); + + if (pTimer != NULL) { + if (timer_pending(pTimer)) + return; + + __RTMP_OS_Add_Timer(pTimer, + timeout); + } +} + +VOID RTMP_OS_Mod_Timer(IN NDIS_MINIPORT_TIMER *pTimerOrg, + IN unsigned long timeout) { + OS_NDIS_MINIPORT_TIMER *pTimer; + + pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent); + if (pTimer != NULL) { + __RTMP_OS_Mod_Timer(pTimer, timeout); + } +} + +VOID RTMP_OS_Del_Timer(IN NDIS_MINIPORT_TIMER *pTimerOrg, + OUT BOOLEAN *pCancelled) { + OS_NDIS_MINIPORT_TIMER *pTimer; + + pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent); + if (pTimer != NULL) { + __RTMP_OS_Del_Timer(pTimer, pCancelled); + } +} + +VOID RTMP_OS_Release_Timer(IN NDIS_MINIPORT_TIMER *pTimerOrg) { + OS_NDIS_MINIPORT_TIMER *pTimer; + + pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent); + if (pTimer != NULL) { + __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(IN LIST_HEADER *pRscList, + IN VOID *pRscSrc, + IN 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(IN VOID *pRscSrc, + IN 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(IN LIST_HEADER *pRscList, + IN 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(IN 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(IN RTMP_OS_TASK *pTask, + IN 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(IN 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(IN 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(IN 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(IN RTMP_OS_TASK *pTaskOrg) { + OS_TASK *pTask; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (pTask == NULL) + return; + __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(IN RTMP_OS_TASK *pTaskOrg, + IN RTMP_OS_TASK_CALLBACK fn, + IN 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(IN RTMP_OS_TASK *pTaskOrg, + IN PSTRING pTaskName, + IN VOID *pPriv, + IN LIST_HEADER *pTaskList, + IN 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(IN VOID *pReserved, + IN RTMP_OS_TASK *pTaskOrg, + IN 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(IN 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(IN NDIS_SPIN_LOCK *pLock, + IN 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(IN 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(IN 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(IN 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(IN NDIS_SPIN_LOCK *pLockOrg, + IN 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(IN NDIS_SPIN_LOCK *pLockOrg, + IN 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"); +} + +/* +======================================================================== +Routine Description: + Get MAC address for the network interface. + +Arguments: + pDev - the device + +Return Value: + None + +Note: +======================================================================== +*/ +unsigned char *RtmpOsNetDevGetPhyAddr(IN 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(IN 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(IN 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(IN 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(IN VOID *pPkt, + IN 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(IN VOID *pDev, + IN 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(IN 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(IN UINT32 Time) { + OS_WAIT(Time); +} + +/* +======================================================================== +Routine Description: + Check if b is smaller than a. + +Arguments: + Time - micro second + +Return Value: + None + +Note: +======================================================================== +*/ +UINT32 RtmpOsTimerAfter(IN ULONG a, + IN 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(IN ULONG a, + IN 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(IN 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(IN UINT16 Value) { + return OS_NTOHS(Value); +} + +/* +======================================================================== +Routine Description: + htons + +Arguments: + Value - the value + +Return Value: + the value + +Note: +======================================================================== +*/ +UINT16 RtmpOsHtons(IN UINT16 Value) { + return OS_HTONS(Value); +} + +/* +======================================================================== +Routine Description: + ntohl + +Arguments: + Value - the value + +Return Value: + the value + +Note: +======================================================================== +*/ +UINT32 RtmpOsNtohl(IN UINT32 Value) { + return OS_NTOHL(Value); +} + +/* +======================================================================== +Routine Description: + htonl + +Arguments: + Value - the value + +Return Value: + the value + +Note: +======================================================================== +*/ +UINT32 RtmpOsHtonl(IN 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(IN 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(IN 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(IN 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(OUT VOID *to, + IN const void *from, + IN 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(OUT VOID *to, + IN const void *from, + IN 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(IN RTMP_OS_SEM *pSem, + IN 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; /* allocate fail */ + } + + 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(IN RTMP_OS_SEM *pSem, + IN 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; /* allocate fail */ + } + + 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(IN 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(IN RTMP_OS_SEM *pSemOrg) { + OS_SEM *pSem; + INT32 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(IN 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(IN PNET_DEV pNetDev, + IN PNDIS_PACKET pNetPkt, + IN ULONG ThisFrameLen, + IN PUCHAR pData) { + memcpy(skb_put(pNetPkt, ThisFrameLen), pData, ThisFrameLen); + SET_OS_PKT_NETDEV(pNetPkt, pNetDev); + RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pNetPkt), PKTSRC_NDIS); +} + +/* +======================================================================== +Routine Description: + Check if the packet is cloned. + +Arguments: + pNetPkt - the packet + +Return Value: + TRUE - Yes + Otherwise - No + +Note: +======================================================================== +*/ +INT RtmpOsIsPktCloned(IN 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(IN 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(IN 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(IN PNDIS_PACKET pNetPkt, + IN 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(IN PNDIS_PACKET pNetPkt, + IN 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(IN PNDIS_PACKET pNetPkt, + IN 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(IN PNDIS_PACKET pNetPkt, + IN 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(IN PNDIS_PACKET pNetPkt, + IN 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(IN PNDIS_PACKET pNetPkt, + IN UINT Len) { + return OS_PKT_HEAD_BUF_EXTEND(pNetPkt, Len); +} + +/* +======================================================================== +Routine Description: + + +Arguments: + pPkt - the packet + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsPktInfPpaSend(IN PNDIS_PACKET pNetPkt) { +#ifdef INF_PPA_SUPPORT + struct sk_buff *pRxPkt = RTPKT_TO_OSPKT(pNetPkt); + int ret = 0; + unsigned int ppa_flags = 0; /* reserved for now */ + + pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev); + + memset(pRxPkt->head, 0, pRxPkt->data - pRxPkt->head - 14); + DBGPRINT(RT_DEBUG_TRACE, + ("ppa_hook_directpath_send_fn rx :ret:%d headroom:%d dev:%s pktlen:%d<===\n", + ret, skb_headroom(pRxPkt) + , pRxPkt->dev->name, pRxPkt->len)); + hex_dump("rx packet", pRxPkt->data, 32); + ret = + ppa_hook_directpath_send_fn(pAd->g_if_id, pRxPkt, pRxPkt->len, + ppa_flags); +#endif /* INF_PPA_SUPPORT */ +} + +INT32 RtmpThreadPidKill(IN RTMP_OS_PID PID) { + return KILL_THREAD_PID(PID, SIGTERM, 1); +} + +long RtmpOsSimpleStrtol(IN const char *cp, IN char **endp, IN 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(IN RTMP_OS_ATOMIC *pAtomic, + IN 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(IN RTMP_OS_ATOMIC *pAtomic) { + if (pAtomic->pContent != NULL) { + + 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(IN RTMP_OS_ATOMIC *pAtomicSrc) { + atomic_t *pAtomic; + + if (pAtomicSrc->pContent == NULL) + return 0; + + pAtomic = (atomic_t *) (pAtomicSrc->pContent); + return atomic_read(pAtomic); +} + +/* +======================================================================== +Routine Description: + Atomic dec a variable. + +Arguments: + pAtomic - the atomic + +Return Value: + content + +Note: +======================================================================== +*/ +VOID RtmpOsAtomicDec(IN RTMP_OS_ATOMIC *pAtomicSrc) { + atomic_t *pAtomic; + + if (pAtomicSrc->pContent == NULL) + return; + + pAtomic = (atomic_t *) (pAtomicSrc->pContent); + atomic_dec(pAtomic); +} + +/* +======================================================================== +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(IN RTMP_OS_ATOMIC *pAtomicSrc, + IN LONG Value) { + atomic_t *pAtomic; + + if (pAtomicSrc->pContent == NULL) + return; + + pAtomic = (atomic_t *) (pAtomicSrc->pContent); + InterlockedExchange(pAtomic, Value); +} + +/* +======================================================================== +Routine Description: + Initialize the OS utilities. + +Arguments: + pOps - Utility table + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsOpsInit(IN RTMP_OS_ABL_OPS *pOps) { + pOps->ra_printk = (RTMP_PRINTK)printk; + pOps->ra_snprintf = (RTMP_SNPRINTF)snprintf; +} +#else /* OS_ABL_FUNC_SUPPORT */ + +void RtmpOSFSInfoChange(IN RTMP_OS_FS_INFO *pOSFSInfoOrg, + IN BOOLEAN bSet) { + __RtmpOSFSInfoChange(pOSFSInfoOrg, bSet); +} + +/* timeout -- ms */ +VOID RTMP_SetPeriodicTimer(IN NDIS_MINIPORT_TIMER *pTimerOrg, + IN unsigned long timeout) { + __RTMP_SetPeriodicTimer(pTimerOrg, + timeout); +} + +/* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */ +VOID RTMP_OS_Init_Timer( + IN VOID *pReserved, + IN NDIS_MINIPORT_TIMER *pTimerOrg, + IN TIMER_FUNCTION function, + IN PVOID data, + IN LIST_HEADER *pTimerList) { + __RTMP_OS_Init_Timer(pReserved, pTimerOrg, function, data); +} + +VOID RTMP_OS_Add_Timer(IN NDIS_MINIPORT_TIMER *pTimerOrg, + IN unsigned long timeout) { + __RTMP_OS_Add_Timer(pTimerOrg, + timeout); +} + +VOID RTMP_OS_Mod_Timer(IN NDIS_MINIPORT_TIMER *pTimerOrg, + IN unsigned long timeout) { + __RTMP_OS_Mod_Timer(pTimerOrg, + timeout); +} + +VOID RTMP_OS_Del_Timer(IN NDIS_MINIPORT_TIMER *pTimerOrg, + OUT BOOLEAN *pCancelled) { + __RTMP_OS_Del_Timer(pTimerOrg, pCancelled); +} + +VOID RTMP_OS_Release_Timer(IN NDIS_MINIPORT_TIMER *pTimerOrg) { + __RTMP_OS_Release_Timer(pTimerOrg); +} + +NDIS_STATUS RtmpOSTaskKill(IN RTMP_OS_TASK * pTask) { + return __RtmpOSTaskKill(pTask); +} + +INT RtmpOSTaskNotifyToExit(IN RTMP_OS_TASK * pTask) { + return __RtmpOSTaskNotifyToExit(pTask); +} + +void RtmpOSTaskCustomize(IN RTMP_OS_TASK * pTask) { + __RtmpOSTaskCustomize(pTask); +} + +NDIS_STATUS RtmpOSTaskAttach(IN RTMP_OS_TASK * pTask, + IN RTMP_OS_TASK_CALLBACK fn, + IN ULONG arg) { + return __RtmpOSTaskAttach(pTask, fn, arg); +} + +NDIS_STATUS RtmpOSTaskInit(IN RTMP_OS_TASK * pTask, + IN PSTRING pTaskName, + IN VOID *pPriv, + IN LIST_HEADER * pTaskList, + IN LIST_HEADER * pSemList) { + return __RtmpOSTaskInit(pTask, pTaskName, pPriv, pSemList); +} + +BOOLEAN RtmpOSTaskWait(IN VOID *pReserved, + IN RTMP_OS_TASK * pTask, + IN INT32 *pStatus) { + return __RtmpOSTaskWait(pReserved, pTask, pStatus); +} + +VOID RtmpOsTaskWakeUp(IN RTMP_OS_TASK * pTask) { +#ifdef KTHREAD_SUPPORT + WAKE_UP(pTask); +#else + RTMP_SEM_EVENT_UP(&pTask->taskSema); +#endif +} + +#endif /* OS_ABL_FUNC_SUPPORT */ + +/* End of rt_linux.c */ diff --git a/mt7620/src/os/linux/rt_linux_symb.c b/mt7620/src/os/linux/rt_linux_symb.c new file mode 100644 index 0000000..ff3eb64 --- /dev/null +++ b/mt7620/src/os/linux/rt_linux_symb.c @@ -0,0 +1,307 @@ +/**************************************************************************** + + 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(Sniff2BytesFromNdisBuffer); +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(RtmpOsPktProtocolAssign); +EXPORT_SYMBOL(RtmpOsPktInfPpaSend); +EXPORT_SYMBOL(RtmpThreadPidKill); +EXPORT_SYMBOL(RtmpOsPktRcvHandle); +#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(RtmpOsSetNetDevPriv); +EXPORT_SYMBOL(RtmpOsGetNetDevPriv); +EXPORT_SYMBOL(RtmpDevPrivFlagsGet); +EXPORT_SYMBOL(RtmpOsSetNetDevType); +EXPORT_SYMBOL(RtmpOsSetNetDevTypeMonitor); +#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(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(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(RtmpDrvMaxRateGet); +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(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_SupBandReInit); +#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(RT_RateSize); +EXPORT_SYMBOL(send_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_AllocateMgmtDescMemory); +EXPORT_SYMBOL(RTMP_AllocateRxPacketBuffer); +EXPORT_SYMBOL(RTMP_FreeDescMemory); +EXPORT_SYMBOL(RTMP_AllocateTxDescMemory); +EXPORT_SYMBOL(linux_pci_unmap_single); +EXPORT_SYMBOL(linux_pci_map_single); +EXPORT_SYMBOL(RTMP_AllocateFirstTxBuffer); +EXPORT_SYMBOL(RTMP_AllocateRxDescMemory); +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) */ + + +EXPORT_SYMBOL(RtPrivIoctlSetVal); + +#endif /* OS_ABL_SUPPORT */ + +/* End of rt_linux_symb.c */ diff --git a/mt7620/src/os/linux/rt_main_dev.c b/mt7620/src/os/linux/rt_main_dev.c new file mode 100644 index 0000000..68108b3 --- /dev/null +++ b/mt7620/src/os/linux/rt_main_dev.c @@ -0,0 +1,951 @@ +/* + *************************************************************************** + * 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 + + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +/*UINT32 CW_MAX_IN_BITS;*/ +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ + +/*---------------------------------------------------------------------*/ +/* Private Variables Used */ +/*---------------------------------------------------------------------*/ + +PSTRING mac = ""; /* default 00:00:00:00:00:00 */ +PSTRING hostname = ""; /* default CMPC */ +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12) +MODULE_PARM (mac, "s"); +#else +module_param (mac, charp, 0); +#endif +MODULE_PARM_DESC (mac, "rt28xx: wireless mac addr"); + +#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 */ +static INT rt28xx_send_packets(IN struct sk_buff *skb_p, IN struct net_device *net_dev); + + + + +struct net_device_stats *RT28xx_get_ether_stats( + IN struct net_device *net_dev); + + +/* +======================================================================== +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; + + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + /* Sanity check for pAd */ + if (pAd == NULL) + return 0; /* close ok */ + + 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(IN struct net_device *net_dev) +{ + VOID *pAd = NULL; + + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + /* Sanity check for pAd */ + if (pAd == NULL) + return 0; /* close ok */ + +#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 */ + + /* increase MODULE use count */ + 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; +/* BOOLEAN Cancelled; */ +/* UINT32 i = 0; */ + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + DBGPRINT(RT_DEBUG_TRACE, ("===> rt28xx_close\n")); + + /* Sanity check for pAd */ + if (pAd == NULL) + return 0; /* close ok */ + + RTMPDrvClose(pAd, net_dev); + + + DBGPRINT(RT_DEBUG_TRACE, ("<=== rt28xx_close\n")); + return 0; /* close ok */ +} /* End of rt28xx_close */ + + +/* +======================================================================== +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 */ + + + /* sanity check */ + 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); + + /* Sanity check for pAd */ + 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_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 */ + + +#ifdef CONFIG_APSTA_MIXED_SUPPORT + if (OpMode == OPMODE_AP) + { + /*CW_MAX_IN_BITS = 6; */ + RTMP_DRIVER_MAX_IN_BITS_SET(pAd, 6); + } + else if (OpMode == OPMODE_STA) + { + /*CW_MAX_IN_BITS = 10; */ + RTMP_DRIVER_MAX_IN_BITS_SET(pAd, 10); + } +#endif /* CONFIG_APSTA_MIXED_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) */ +#ifndef P2P_APCLI_SUPPORT + 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 +#ifndef P2P_APCLI_SUPPORT + RT28xx_ApCli_Init(pAd, net_dev); +#endif /* P2P_APCLI_SUPPORT */ +#endif /* APCLI_SUPPORT */ + +#ifdef MESH_SUPPORT + RTMP_Mesh_Init(pAd, net_dev, hostname); +#endif /* MESH_SUPPORT */ + +#ifdef P2P_SUPPORT + RTMP_P2P_Init(pAd, net_dev); +#endif /* P2P_SUPPORT */ + +#ifdef LINUX +#ifdef RT_CFG80211_SUPPORT +/* RT_CFG80211_REINIT(pAd); */ +/* RT_CFG80211_CRDA_REG_RULE_APPLY(pAd); */ + 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 */ + + return (retval); + +err: +/*+++move from rt28xx_init() to here. */ +/* RtmpOSIRQRelease(net_dev); */ + RTMP_DRIVER_IRQ_RELEASE(pAd); +/*---move from rt28xx_init() to here. */ + + return (-1); +} /* End of rt28xx_open */ + + +PNET_DEV RtmpPhyNetDevInit( + IN VOID *pAd, + IN RTMP_OS_NETDEV_OP_HOOK *pNetDevHook) +{ + struct net_device *net_dev = NULL; +/* NDIS_STATUS Status; */ + ULONG InfId, OpMode; + + RTMP_DRIVER_MAIN_INF_GET(pAd, &InfId); + +/* net_dev = RtmpOSNetDevCreate(pAd, INT_MAIN, 0, sizeof(PRTMP_ADAPTER), INF_MAIN_DEV_NAME); */ + RTMP_DRIVER_MAIN_INF_CREATE(pAd, &net_dev); + if (net_dev == NULL) + { + printk("RtmpPhyNetDevInit(): creation failed for main physical net device!\n"); + 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_stats; + + 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); + +#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 */ + + /* put private data structure */ + RTMP_OS_NETDEV_SET_PRIV(net_dev, pAd); + + /* double-check if pAd is associated with the net_dev */ + if (RTMP_OS_NETDEV_GET_PRIV(net_dev) == NULL) + { + RtmpOSNetDevFree(net_dev); + return NULL; + } +/* pAd->net_dev = net_dev; */ + + 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( + IN VOID *net_dev_, + IN 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 *skbsrc) +{ + struct sk_buff *skb = (struct sk_buff *)skbsrc; + struct net_device *net_dev = skb->dev; + VOID *pAd = NULL; +/* int status = 0; */ + PNDIS_PACKET pPacket = (PNDIS_PACKET) skb; + + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + return RTMPSendPackets((NDIS_HANDLE)pAd, (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: +======================================================================== +*/ +static int rt28xx_send_packets( + IN struct sk_buff *skb_p, + IN struct net_device *net_dev) +{ +/* RTMP_ADAPTER *pAd = NULL; */ + +/* GET_PAD_FROM_NET_DEV(pAd, net_dev); */ + + if (!(RTMP_OS_NETDEV_STATE_RUNNING(net_dev))) + { + RELEASE_NDIS_PACKET(NULL, (PNDIS_PACKET)skb_p, NDIS_STATUS_FAILURE); + return 0; + } + + NdisZeroMemory((PUCHAR)&skb_p->cb[CB_OFF], 15); +#ifdef P2P_SUPPORT + NdisZeroMemory((PUCHAR)&skb_p->cb[CB_OFF+26], 1); +#endif /* P2P_SUPPORT */ + RTMP_SET_PACKET_NET_DEVICE_MBSSID(skb_p, MAIN_MBSSID); + MEM_DBG_PKT_ALLOC_INC(skb_p); + + return rt28xx_packet_xmit(skb_p); +} + + +#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) +{ + VOID *pAd = NULL; + struct iw_statistics *pStats; + RT_CMD_IW_STATS DrvIwStats, *pDrvIwStats = &DrvIwStats; + + + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + +#ifdef P2P_SUPPORT +#endif /* P2P_SUPPORT */ + 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( + IN PNET_DEV net_dev, + IN OUT struct ifreq *rq, + IN 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) + { +#ifdef P2P_SUPPORT + if (RTMP_DRIVER_P2P_INF_CHECK(pAd, RT_DEV_PRIV_FLAGS_GET(net_dev)) == NDIS_STATUS_SUCCESS) + ret = rt28xx_ap_ioctl(net_dev, rq, cmd); + else +#endif /* P2P_SUPPORT */ + 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: + net_device_stats* + + Note: + + ======================================================================== +*/ +struct net_device_stats *RT28xx_get_ether_stats( + IN struct net_device *net_dev) +{ + VOID *pAd = NULL; + struct net_device_stats *pStats; + + if (net_dev) + GET_PAD_FROM_NET_DEV(pAd, net_dev); + + if (pAd) + { + RT_CMD_STATS DrvStats, *pDrvStats = &DrvStats; + + + //assign net device for RTMP_DRIVER_INF_STATS_GET() + pDrvStats->pNetDev = net_dev; + RTMP_DRIVER_INF_STATS_GET(pAd, pDrvStats); + + pStats = (struct net_device_stats *)(pDrvStats->pStats); + pStats->rx_packets = pDrvStats->rx_packets; + pStats->tx_packets = pDrvStats->tx_packets; + + pStats->rx_bytes = pDrvStats->rx_bytes; + pStats->tx_bytes = pDrvStats->tx_bytes; + + pStats->rx_errors = pDrvStats->rx_errors; + pStats->tx_errors = pDrvStats->tx_errors; + + pStats->rx_dropped = 0; + pStats->tx_dropped = 0; + + pStats->multicast = pDrvStats->multicast; + pStats->collisions = pDrvStats->collisions; + + pStats->rx_length_errors = 0; + pStats->rx_over_errors = pDrvStats->rx_over_errors; + pStats->rx_crc_errors = 0;/*pAd->WlanCounters.FCSErrorCount; // recved pkt with crc error */ + pStats->rx_frame_errors = pDrvStats->rx_frame_errors; + pStats->rx_fifo_errors = pDrvStats->rx_fifo_errors; + pStats->rx_missed_errors = 0; /* receiver missed packet */ + + /* detailed tx_errors */ + pStats->tx_aborted_errors = 0; + pStats->tx_carrier_errors = 0; + pStats->tx_fifo_errors = 0; + pStats->tx_heartbeat_errors = 0; + pStats->tx_window_errors = 0; + + /* for cslip etc */ + pStats->rx_compressed = 0; + pStats->tx_compressed = 0; + + return pStats; + } + else + return NULL; +} + + +BOOLEAN RtmpPhyNetDevExit( + IN VOID *pAd, + IN PNET_DEV net_dev) +{ + +#ifdef MESH_SUPPORT + RTMP_Mesh_Remove(pAd); +#endif /* MESH_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +#ifndef P2P_APCLI_SUPPORT + /* remove all AP-client virtual interfaces. */ + RT28xx_ApCli_Remove(pAd); +#endif /* P2P_APCLI_SUPPORT */ +#endif /* APCLI_SUPPORT */ + +#ifdef WDS_SUPPORT + /* remove all WDS virtual interfaces. */ + RT28xx_WDS_Remove(pAd); +#endif /* WDS_SUPPORT */ + +#ifdef MBSS_SUPPORT +#ifndef P2P_APCLI_SUPPORT + RT28xx_MBSS_Remove(pAd); +#endif /* P2P_APCLI_SUPPORT */ +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef P2P_SUPPORT + RTMP_P2P_Remove(pAd); +#endif /* P2P_SUPPORT */ + +#ifdef INF_PPA_SUPPORT + + RTMP_DRIVER_INF_PPA_EXIT(pAd); +#endif /* INF_PPA_SUPPORT */ + + /* Unregister network device */ + if (net_dev != NULL) + { + printk("RtmpOSNetDevDetach(): RtmpOSNetDeviceDetach(), dev->name=%s!\n", net_dev->name); + RtmpOSNetDevDetach(net_dev); + } + + 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; +/* POS_COOKIE _pObj = (POS_COOKIE)(pAd->OS_Cookie); */ +/* RTMP_MSI_ENABLE(pAd); */ + RTMP_DRIVER_PCI_MSI_ENABLE(pAd, &pci_dev); + + retval = request_irq(pci_dev->irq, rt2860_interrupt, SA_SHIRQ, (net_dev)->name, (net_dev)); + 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: + net_device_stats* + + Note: + + ======================================================================== +*/ +struct net_device_stats *RT28xx_get_wds_ether_stats( + IN PNET_DEV net_dev) +{ + VOID *pAd = NULL; +/* INT WDS_apidx = 0,index; */ + struct net_device_stats *pStats; + RT_CMD_STATS WdsStats, *pWdsStats = &WdsStats; + + if (net_dev) { + GET_PAD_FROM_NET_DEV(pAd, net_dev); + } + +/* if (RT_DEV_PRIV_FLAGS_GET(net_dev) == INT_WDS) */ + { + if (pAd) + { + + pWdsStats->pNetDev = net_dev; + if (RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_WDS_STATS_GET, + 0, pWdsStats, RT_DEV_PRIV_FLAGS_GET(net_dev)) != NDIS_STATUS_SUCCESS) + return NULL; + + pStats = (struct net_device_stats *)pWdsStats->pStats; /*pAd->stats; */ + + pStats->rx_packets = pWdsStats->rx_packets; /*pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.ReceivedFragmentCount.QuadPart; */ + pStats->tx_packets = pWdsStats->tx_packets; /*pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.TransmittedFragmentCount.QuadPart; */ + + pStats->rx_bytes = pWdsStats->rx_bytes; /*pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.ReceivedByteCount; */ + pStats->tx_bytes = pWdsStats->tx_bytes; /*pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.TransmittedByteCount; */ + + pStats->rx_errors = pWdsStats->rx_errors; /*pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.RxErrors; */ + pStats->tx_errors = pWdsStats->tx_errors; /*pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.TxErrors; */ + + pStats->rx_dropped = 0; + pStats->tx_dropped = 0; + + pStats->multicast = pWdsStats->multicast; /*pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.MulticastReceivedFrameCount.QuadPart; // multicast packets received */ + pStats->collisions = pWdsStats->collisions; /*pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.OneCollision + pAd->WdsTab.WdsEntry[index].WdsCounter.MoreCollisions; // Collision packets */ + + pStats->rx_length_errors = 0; + pStats->rx_over_errors = pWdsStats->rx_over_errors; /*pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.RxNoBuffer; // receiver ring buff overflow */ + pStats->rx_crc_errors = 0;/*pAd->WlanCounters.FCSErrorCount; // recved pkt with crc error */ + pStats->rx_frame_errors = pWdsStats->rx_frame_errors; /*pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.RcvAlignmentErrors; // recv'd frame alignment error */ + pStats->rx_fifo_errors = pWdsStats->rx_fifo_errors; /*pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.RxNoBuffer; // recv'r fifo overrun */ + pStats->rx_missed_errors = 0; /* receiver missed packet */ + + /* detailed tx_errors */ + pStats->tx_aborted_errors = 0; + pStats->tx_carrier_errors = 0; + pStats->tx_fifo_errors = 0; + pStats->tx_heartbeat_errors = 0; + pStats->tx_window_errors = 0; + + /* for cslip etc */ + pStats->rx_compressed = 0; + pStats->tx_compressed = 0; + + return pStats; + } + else + return NULL; + } +/* else */ +/* return NULL; */ +} +#endif /* WDS_SUPPORT */ + + + + diff --git a/mt7620/src/os/linux/rt_pci_rbus.c b/mt7620/src/os/linux/rt_pci_rbus.c new file mode 100644 index 0000000..f459a4c --- /dev/null +++ b/mt7620/src/os/linux/rt_pci_rbus.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, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering 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; +/* INT_SOURCE_CSR_STRUC IntSource; */ +/* POS_COOKIE pObj; */ +#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/mt7620/src/os/linux/rt_proc.c b/mt7620/src/os/linux/rt_proc.c new file mode 100644 index 0000000..aeebcd1 --- /dev/null +++ b/mt7620/src/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 +extern 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/mt7620/src/os/linux/rt_profile.c b/mt7620/src/os/linux/rt_profile.c new file mode 100644 index 0000000..1e96f9d --- /dev/null +++ b/mt7620/src/os/linux/rt_profile.c @@ -0,0 +1,1204 @@ +/**************************************************************************** + * 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" + +#ifdef RTMP_RBUS_SUPPORT +#if defined(CONFIG_RA_HW_NAT) || defined(CONFIG_RA_HW_NAT_MODULE) +#if defined(CONFIG_SUPPORT_OPENWRT) +#include "../../../linux-kernel/net/nat/hw_nat/ra_nat.h" +#include "../../../linux-kernel/net/nat/hw_nat/frame_engine.h" +#else +#include "../../../../../../net/nat/hw_nat/ra_nat.h" +#include "../../../../../../net/nat/hw_nat/frame_engine.h" +#endif /* CONFIG_SUPPORT_OPENWRT */ +#endif +#endif /* RTMP_RBUS_SUPPORT */ + + +#ifdef SYSTEM_LOG_SUPPORT +/* 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 *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 */ +#endif /* SYSTEM_LOG_SUPPORT */ + + +NDIS_STATUS RTMPReadParametersHook( + IN PRTMP_ADAPTER pAd) +{ + PSTRING src = NULL; + RTMP_OS_FD srcf; + RTMP_OS_FS_INFO osFSInfo; + INT retval = NDIS_STATUS_FAILURE; + PSTRING buffer; + +#ifdef HOSTAPD_SUPPORT + int i; +#endif /*HOSTAPD_SUPPORT */ + +/* buffer = kmalloc(MAX_INI_BUFFER_SIZE, MEM_ALLOC_FLAG); */ + os_alloc_mem(pAd, (UCHAR **)&buffer, MAX_INI_BUFFER_SIZE); + if(buffer == NULL) + return NDIS_STATUS_FAILURE; + memset(buffer, 0x00, MAX_INI_BUFFER_SIZE); + +#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 */ +#ifdef MULTIPLE_CARD_SUPPORT + src = pAd->MC_FileName; +#endif /* MULTIPLE_CARD_SUPPORT */ + } + else +#endif /* RTMP_RBUS_SUPPORT */ + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + src = AP_PROFILE_PATH; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + src = STA_PROFILE_PATH; + } +#endif /* CONFIG_STA_SUPPORT */ +#ifdef MULTIPLE_CARD_SUPPORT + src = (PSTRING)pAd->MC_FileName; +#endif /* MULTIPLE_CARD_SUPPORT */ + } + + 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 + { + retval =RtmpOSFileRead(srcf, buffer, MAX_INI_BUFFER_SIZE); + if (retval > 0) + { + RTMPSetProfileParameters(pAd, buffer); + retval = NDIS_STATUS_SUCCESS; + } + else + DBGPRINT(RT_DEBUG_ERROR, ("Read file \"%s\" failed(errCode=%d)!\n", src, retval)); + + retval = RtmpOSFileClose(srcf); + if ( retval != 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=FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("Reset ra%d hostapd support=FLASE", i)); + + } +#endif /*HOSTAPD_SUPPORT */ + +#ifdef SINGLE_SKU_V2 + RTMPSetSingleSKUParameters(pAd); +#endif /* SINGLE_SKU_V2 */ + +/* kfree(buffer); */ + os_free_mem(NULL, buffer); + + return (retval); + +} + + +#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 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 */ + + +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 */ +} + + +#ifdef WORKQUEUE_BH +void tbtt_workq(struct work_struct *work) +#else +void tbtt_tasklet(unsigned long data) +#endif /* WORKQUEUE_BH */ +{ +/*#define MAX_TX_IN_TBTT (16) */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef WORKQUEUE_BH + POS_COOKIE pObj = container_of(work, struct os_cookie, tbtt_work); + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pObj->pAd_va; +#else + PRTMP_ADAPTER pAd = (PRTMP_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 */ + + } +#endif /* RTMP_MAC_PCI */ + +#ifdef P2P_SUPPORT + if (P2P_INF_ON(pAd) && P2P_GO_ON(pAd)) +#else + if (pAd->OpMode == OPMODE_AP) +#endif /* 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->MacTab.fMcastPsQEnable == TRUE) + { + UINT32 macValue, idx; + + for (idx = 0; idx < 40; idx++) + { + RTMP_IO_READ32(pAd, TXRXQ_STA, &macValue); + + if (macValue & 0x0000F800) + { + break; + } + else + { + RTMPusecDelay(50); + } + } + + RTMP_IO_WRITE32(pAd, TX_WCID_DROP_MASK0, 0xFFFFFFFE); + + 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); + + for (idx = 0; idx < 200; idx++) + { + RTMP_IO_READ32(pAd, MCU_INT_STATUS, &macValue); + + if (macValue & 0x04) + { + break; + } + else + { + RTMPusecDelay(50); + } + } + + RTMP_IO_WRITE32(pAd, TX_WCID_DROP_MASK0, 0x0); + } + } + + RTMP_IO_WRITE32(pAd, MCU_INT_STATUS, 0x14); + pAd->MacTab.fMcastPsQEnable = FALSE; + } +#endif /* CONFIG_AP_SUPPORT */ +} + + +void announce_802_3_packet( + IN VOID *pAdSrc, + IN PNDIS_PACKET pPacket, + IN UCHAR OpMode) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; +/* struct sk_buff *pRxPkt; */ + PNDIS_PACKET pRxPkt; +#ifdef INF_PPA_SUPPORT + int ret = 0; + unsigned int ppa_flags = 0; /* reserved for now */ +#endif /* INF_PPA_SUPPORT */ + + pAd = pAd; /* avoid compile warning */ + + MEM_DBG_PKT_FREE_INC(pPacket); + + + ASSERT(pPacket); + +/* pRxPkt = RTPKT_TO_OSPKT(pPacket); */ + pRxPkt = pPacket; +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +#ifdef P2P_SUPPORT + if (OpMode == OPMODE_AP) +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { + if (RTMP_MATPktRxNeedConvert(pAd, RtmpOsPktNetDevGet(pRxPkt))) + { + { + RTMP_MATEngineRxHandle(pAd, pRxPkt, 0); + } + } + } +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef ETH_CONVERT_SUPPORT +#ifdef P2P_SUPPORT + if (OpMode == OPMODE_STA) +#else + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) +#endif /* P2P_SUPPORT */ + { + if (RTMP_MATPktRxNeedConvert(pAd, RtmpOsPktNetDevGet(pRxPkt)) && + (pAd->EthConvert.ECMode & ETH_CONVERT_MODE_DONGLE)) + RTMP_MATEngineRxHandle(pAd, pRxPkt, 0); + } +#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); */ + RtmpOsPktProtocolAssign(pRxPkt); + pToUpperLayerPktSent(pRxPkt); + return; +} +#endif /* PLATFORM_BL2348 */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef IKANOS_VX_1X0 + IKANOS_DataFrameRx(pAd, pRxPkt); + return; +#endif /* IKANOS_VX_1X0 */ + + + /* mark for bridge fast path, 2009/06/22 */ + /* pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev); */ + +#ifdef INF_PPA_SUPPORT + if (ppa_hook_directpath_send_fn && pAd->PPAEnable==TRUE ) + { + RtmpOsPktInfPpaSend(pRxPkt); + + pRxPkt=NULL; + return; + + } +#endif /* INF_PPA_SUPPORT */ + +#ifdef RTMP_RBUS_SUPPORT + if (pAd->infType == RTMP_DEV_INF_RBUS) + { +#ifdef CONFIG_RT2880_BRIDGING_ONLY + /* pRxPkt->cb[22]=0xa8; */ + PACKET_CB_ASSIGN(pRxPkt, 22) = 0xa8; +#endif + +#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE) + if(ra_classifier_hook_rx!= NULL) + { + unsigned int flags; + + RTMP_IRQ_LOCK(&pAd->page_lock, flags); + ra_classifier_hook_rx(pRxPkt, classifier_cur_cycle); + RTMP_IRQ_UNLOCK(&pAd->page_lock, flags); + } +#endif /* CONFIG_RA_CLASSIFIER */ + +#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) + { + unsigned int flags; + +#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) + RtmpOsPktNatMagicTag(pRxPkt); +#endif + + /* pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev); */ + RtmpOsPktProtocolAssign(pRxPkt); + + RTMP_IRQ_LOCK(&pAd->page_lock, flags); + if(ra_sw_nat_hook_rx(pRxPkt)) + { + RtmpOsPktRcvHandle(pRxPkt); + } + RTMP_IRQ_UNLOCK(&pAd->page_lock, flags); + return; + } +#else + { +#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) + RtmpOsPktNatNone(pRxPkt); +#endif /* CONFIG_RA_HW_NAT */ + } +#endif /* CONFIG_RA_NAT_NONE */ + } +#endif /* RTMP_RBUS_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT +#ifdef BG_FT_SUPPORT + if (BG_FTPH_PacketFromApHandle(pRxPkt) == 0) + return; +#endif /* BG_FT_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +/* pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev); */ + RtmpOsPktProtocolAssign(pRxPkt); + RtmpOsPktRcvHandle(pRxPkt); + +} + + +#ifdef CONFIG_STA_SUPPORT +void STA_MonPktSend( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PNET_DEV pNetDev; + PNDIS_PACKET pRxPacket; + PHEADER_802_11 pHeader; + USHORT DataSize; + UINT32 MaxRssi; + UCHAR L2PAD, PHYMODE, BW, ShortGI, MCS, AMPDU, STBC, RSSI1; + UCHAR BssMonitorFlag11n, Channel, CentralChannel; + UCHAR *pData, *pDevName; + + + /* sanity check */ + 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 (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; + } + + /* init */ + MaxRssi = RTMPMaxRssi(pAd, + ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI0, RSSI_0), + ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI1, RSSI_1), + ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI2, RSSI_2)); + + pNetDev = get_netdev_from_bssid(pAd, BSS0); + pRxPacket = pRxBlk->pRxPacket; + pHeader = pRxBlk->pHeader; + pData = pRxBlk->pData; + DataSize = pRxBlk->DataSize; + L2PAD = pRxBlk->RxD.L2PAD; + PHYMODE = pRxBlk->pRxWI->PHYMODE; + BW = pRxBlk->pRxWI->BW; + ShortGI = pRxBlk->pRxWI->ShortGI; + MCS = pRxBlk->pRxWI->MCS; + AMPDU = pRxBlk->RxD.AMPDU; + STBC = pRxBlk->pRxWI->STBC; + RSSI1 = pRxBlk->pRxWI->RSSI1; + 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; + CentralChannel = pAd->CommonCfg.CentralChannel; + + /* pass the packet */ + send_monitor_packets(pNetDev, pRxPacket, 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_STA_SUPPORT */ + + +extern NDIS_SPIN_LOCK TimerSemLock; + +VOID RTMPFreeAdapter( + IN 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 RTMP_FLASH_SUPPORT + if (pAd->eebuf && (pAd->eebuf != pAd->chipCap.eebuf)) + { + os_free_mem(NULL, pAd->eebuf); + pAd->eebuf = NULL; + } +#endif /* RTMP_FLASH_SUPPORT */ + + + NdisFreeSpinLock(&pAd->MgmtRingLock); + +#ifdef RTMP_MAC_PCI + NdisFreeSpinLock(&pAd->RxRingLock); +#endif /* RTMP_MAC_PCI */ + + + 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); +#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; + } + if (pAd->stats) + { + os_free_mem(NULL, pAd->stats); + pAd->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); +} + + +int RTMPSendPackets( + IN NDIS_HANDLE MiniportAdapterContext, + IN PPNDIS_PACKET ppPacketArray, + IN UINT NumberOfPackets, + IN UINT32 PktTotalLen, + IN RTMP_NET_ETH_CONVERT_DEV_SEARCH Func) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)MiniportAdapterContext; + PNDIS_PACKET pPacket = ppPacketArray[0]; + + + INC_COUNTER64(pAd->WlanCounters.TransmitCountFrmOs); + + if (pPacket == NULL) + goto done; + + /* RT2870STA does this in RTMPSendPackets() */ +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_RESOURCES); + 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_FAILURE); + return 0; + } + } +#endif /* CONFIG_STA_SUPPORT */ + + /* EapolStart size is 18 */ + if (PktTotalLen < 14) + { + /*printk("bad packet size: %d\n", pkt->len); */ + hex_dump("bad packet", GET_OS_PKT_DATAPTR(pPacket), PktTotalLen); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return 0; + } + +#if !defined(CONFIG_RA_NAT_NONE) + /* bruce+ */ + if(ra_sw_nat_hook_tx!= NULL) + { + unsigned long flags; + + RTMP_INT_LOCK(&pAd->page_lock, flags); + ra_sw_nat_hook_tx(pPacket); + RTMP_INT_UNLOCK(&pAd->page_lock, flags); + } +#endif + + RTMP_SET_PACKET_5VT(pPacket, 0); +/* MiniportMMRequest(pAd, pkt->data, pkt->len); */ +#ifdef CONFIG_5VT_ENHANCE + if (*(int*)(GET_OS_PKT_CB(pPacket)) == BRIDGE_TAG) { + RTMP_SET_PACKET_5VT(pPacket, 1); + } +#endif + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + APSendPackets((NDIS_HANDLE)pAd, (PPNDIS_PACKET) &pPacket, 1); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef P2P_SUPPORT + if (RTMP_GET_PACKET_OPMODE(pPacket)) + { + APSendPackets((NDIS_HANDLE)pAd, (PPNDIS_PACKET) &pPacket, 1); + goto done; + } +#endif /* P2P_SUPPORT */ +#ifdef ETH_CONVERT_SUPPORT + UCHAR *pData = GET_OS_PKT_DATAPTR(pPacket); + + /* Don't move this checking into STASendPackets(), becasue the net_device is OS-depeneded. */ + if ((pAd->EthConvert.ECMode & ETH_CONVERT_MODE_CLONE) + && (!pAd->EthConvert.CloneMacVaild) + && (pAd->EthConvert.macAutoLearn) + && (!(pData[6] & 0x1))) + { + VOID *pNetDev = Func(pAd->net_dev, pData); + + if (!pNetDev) { + NdisMoveMemory(&pAd->EthConvert.EthCloneMac[0], &pData[6], MAC_ADDR_LEN); + pAd->EthConvert.CloneMacVaild = TRUE; + } + } + + if ((pAd->EthConvert.ECMode == ETH_CONVERT_MODE_CLONE) + && (NdisEqualMemory(pAd->CurrentAddress, &pData[6], MAC_ADDR_LEN) == 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 */ + + STASendPackets((NDIS_HANDLE)pAd, (PPNDIS_PACKET) &pPacket, 1); + } + +#endif /* CONFIG_STA_SUPPORT */ + +done: + return 0; +} + + +PNET_DEV get_netdev_from_bssid( + IN PRTMP_ADAPTER pAd, + IN UCHAR FromWhichBSSID) +{ + PNET_DEV dev_p = NULL; +#ifdef CONFIG_AP_SUPPORT + UCHAR infRealIdx; +#endif /* CONFIG_AP_SUPPORT */ + + do + { +#ifdef CONFIG_STA_SUPPORT +#ifdef P2P_SUPPORT + if(FromWhichBSSID >= MIN_NET_DEVICE_FOR_P2P_GO) + { + dev_p = pAd->ApCfg.MBSSID[BSS0].MSSIDDev; + break; + } +#endif /* P2P_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ +#ifdef MESH_SUPPORT + if(FromWhichBSSID >= MIN_NET_DEVICE_FOR_MESH) + { + dev_p = pAd->MeshTab.dev; + break; + } +#endif /* MESH_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].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].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].MSSIDDev; + } + else +#endif /* CONFIG_AP_SUPPORT */ + { + dev_p = pAd->net_dev; + } + + } while (FALSE); + + ASSERT(dev_p); + return dev_p; /* return one of MBSS */ +} + + +#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( + IN RTMP_ADAPTER *pAd, + IN 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; +/* DBGPRINT(RT_DEBUG_INFO, ("rt28xx_ioctl I/F(ra%d)(flags=%d): cmd = 0x%08x\n", pObj->ioctl_if, RT_DEV_PRIV_FLAGS_GET(net_dev), cmd)); */ + } + 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].MSSIDDev == pConfig->net_dev) + { + pObj->ioctl_if = index; + +/* DBGPRINT(RT_DEBUG_INFO, ("rt28xx_ioctl I/F(ra%d)(flags=%d): cmd = 0x%08x\n", index, RT_DEV_PRIV_FLAGS_GET(net_dev), cmd)); */ + break; + } + } + /* Interface not found! */ + if(index == pAd->ApCfg.BssidNum) + { +/* DBGPRINT(RT_DEBUG_ERROR, ("rt28xx_ioctl can not find I/F\n")); */ + return -ENETDOWN; + } + } + else /* ioctl command from I/F(ra0) */ + { +/* GET_PAD_FROM_NET_DEV(pAd, net_dev); */ + pObj->ioctl_if = MAIN_MBSSID; +/* DBGPRINT(RT_DEBUG_ERROR, ("rt28xx_ioctl can not find I/F and use default: cmd = 0x%08x\n", cmd)); */ + } + 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].dev == pConfig->net_dev) + { + pObj->ioctl_if = index; + + break; + } + + if(index == MAX_WDS_ENTRY) + { + DBGPRINT(RT_DEBUG_ERROR, ("rt28xx_ioctl can not find wds I/F\n")); + 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].dev == pConfig->net_dev) + { + pObj->ioctl_if = index; + + break; + } + + if(index == MAX_APCLI_NUM) + { + DBGPRINT(RT_DEBUG_ERROR, ("rt28xx_ioctl can not find Apcli I/F\n")); + return -ENETDOWN; + } + } + APCLI_MR_APIDX_SANITY_CHECK(pObj->ioctl_if); + } +#endif /* APCLI_SUPPORT */ +#ifdef MESH_SUPPORT + else if (pConfig->priv_flags == INT_MESH) + { + pObj->ioctl_if_type = INT_MESH; + pObj->ioctl_if = 0; + } +#endif /* MESH_SUPPORT */ +#ifdef P2P_SUPPORT + else if (pConfig->priv_flags == INT_P2P) + { + pObj->ioctl_if_type = INT_P2P; + pObj->ioctl_if = MAIN_MBSSID; + } +#endif /* P2P_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/mt7620/src/os/linux/rt_rbus_pci_drv.c b/mt7620/src/os/linux/rt_rbus_pci_drv.c new file mode 100644 index 0000000..efa8a50 --- /dev/null +++ b/mt7620/src/os/linux/rt_rbus_pci_drv.c @@ -0,0 +1,2005 @@ +/**************************************************************************** + * 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 WORKQUEUE_BH +static void rx_done_workq(struct work_struct *work); +static void mgmt_dma_done_workq(struct work_struct *work); +static void ac0_dma_done_workq(struct work_struct *work); +static void ac1_dma_done_workq(struct work_struct *work); +static void ac2_dma_done_workq(struct work_struct *work); +static void ac3_dma_done_workq(struct work_struct *work); +static void hcca_dma_done_workq(struct work_struct *work); +static void fifo_statistic_full_workq(struct work_struct *work); +#else +static void rx_done_tasklet(unsigned long data); +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); +#endif /* WORKQUEUE_BH */ + +#ifdef UAPSD_SUPPORT +#ifdef WORKQUEUE_BH +static void uapsd_eosp_sent_workq(struct work_struct *work); +#else +static void uapsd_eosp_sent_tasklet(unsigned long data); +#endif /* WORKQUEUE_BH */ +#endif /* UAPSD_SUPPORT */ + + +/*---------------------------------------------------------------------*/ +/* Symbol & Macro Definitions */ +/*---------------------------------------------------------------------*/ +#define RT2860_INT_RX_DLY (1<<0) /* bit 0 */ +#define RT2860_INT_TX_DLY (1<<1) /* bit 1 */ +#define RT2860_INT_RX_DONE (1<<2) /* bit 2 */ +#define RT2860_INT_AC0_DMA_DONE (1<<3) /* bit 3 */ +#define RT2860_INT_AC1_DMA_DONE (1<<4) /* bit 4 */ +#define RT2860_INT_AC2_DMA_DONE (1<<5) /* bit 5 */ +#define RT2860_INT_AC3_DMA_DONE (1<<6) /* bit 6 */ +#define RT2860_INT_HCCA_DMA_DONE (1<<7) /* bit 7 */ +#define RT2860_INT_MGMT_DONE (1<<8) /* bit 8 */ +#ifdef CARRIER_DETECTION_SUPPORT +#define RT2860_INT_TONE_RADAR (1<<20) /* bit 20 */ +#endif /* CARRIER_DETECTION_SUPPORT*/ + +#define INT_RX RT2860_INT_RX_DONE + +#define INT_AC0_DLY (RT2860_INT_AC0_DMA_DONE) /*| RT2860_INT_TX_DLY) */ +#define INT_AC1_DLY (RT2860_INT_AC1_DMA_DONE) /*| RT2860_INT_TX_DLY) */ +#define INT_AC2_DLY (RT2860_INT_AC2_DMA_DONE) /*| RT2860_INT_TX_DLY) */ +#define INT_AC3_DLY (RT2860_INT_AC3_DMA_DONE) /*| RT2860_INT_TX_DLY) */ +#define INT_HCCA_DLY (RT2860_INT_HCCA_DMA_DONE) /*| RT2860_INT_TX_DLY) */ +#define INT_MGMT_DLY RT2860_INT_MGMT_DONE +#ifdef CARRIER_DETECTION_SUPPORT +#define INT_TONE_RADAR (RT2860_INT_TONE_RADAR) +#endif /* CARRIER_DETECTION_SUPPORT*/ + +NDIS_STATUS RtmpNetTaskInit(IN RTMP_ADAPTER *pAd) +{ + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_INIT(pAd, &pObj->rx_done_work, rx_done_workq); + RTMP_OS_TASKLET_INIT(pAd, &pObj->mgmt_dma_done_work, mgmt_dma_done_workq); + RTMP_OS_TASKLET_INIT(pAd, &pObj->ac0_dma_done_work, ac0_dma_done_workq); + RTMP_OS_TASKLET_INIT(pAd, &pObj->ac1_dma_done_work, ac1_dma_done_workq); + RTMP_OS_TASKLET_INIT(pAd, &pObj->ac2_dma_done_work, ac2_dma_done_workq); + RTMP_OS_TASKLET_INIT(pAd, &pObj->ac3_dma_done_work, ac3_dma_done_workq); + RTMP_OS_TASKLET_INIT(pAd, &pObj->hcca_dma_done_work, hcca_dma_done_workq); + RTMP_OS_TASKLET_INIT(pAd, &pObj->tbtt_work, tbtt_workq); + RTMP_OS_TASKLET_INIT(pAd, &pObj->fifo_statistic_full_work, fifo_statistic_full_workq); +#ifdef UAPSD_SUPPORT + RTMP_OS_TASKLET_INIT(pAd, &pObj->uapsd_eosp_sent_work, uapsd_eosp_sent_workq); +#endif /* UAPSD_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef P2P_SUPPORT +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { +#ifdef DFS_SUPPORT + RTMP_OS_TASKLET_INIT(pAd, &pObj->dfs_work, dfs_workq); +#endif /* DFS_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ +#else + RTMP_OS_TASKLET_INIT(pAd, &pObj->rx_done_task, rx_done_tasklet, (unsigned long)pAd); + 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->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 +#ifdef P2P_SUPPORT +#else + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +#endif /* P2P_SUPPORT */ + { +#ifdef DFS_SUPPORT + RTMP_OS_TASKLET_INIT(pAd, &pObj->dfs_task, dfs_tasklet, (unsigned long)pAd); +#endif /* DFS_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* WORKQUEUE_BH */ + + return NDIS_STATUS_SUCCESS; +} + + +void RtmpNetTaskExit(IN RTMP_ADAPTER *pAd) +{ + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + +#ifndef WORKQUEUE_BH + RTMP_OS_TASKLET_KILL(&pObj->rx_done_task); + 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 */ +#endif /* WORKQUEUE_BH */ +} + + +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")); +/* DBGPRINT(RT_DEBUG_ERROR, ("%s: kill task(%s) failed!\n", */ +/* RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev), pTask->taskName)); */ + } + 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; + + pAd->int_disable_mask &= ~(mode); + regValue = pAd->int_enable_reg & ~(pAd->int_disable_mask); + /*if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) */ + { + RTMP_IO_WRITE32(pAd, INT_MASK_CSR, regValue); /* 1:enable */ + } + /*else */ + /* DBGPRINT(RT_DEBUG_TRACE, ("fOP_STATUS_DOZE !\n")); */ + + 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); /* 0: disable */ + + if (regValue == 0) + { + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE); + } +} + + +/*************************************************************************** + * + * tasklet related procedures. + * + **************************************************************************/ +#ifdef WORKQUEUE_BH +static void mgmt_dma_done_workq(struct work_struct *work) +#else +static void mgmt_dma_done_tasklet(unsigned long data) +#endif /* WORKQUEUE_BH */ +{ + unsigned long flags; + INT_SOURCE_CSR_STRUC IntSource; +#ifdef WORKQUEUE_BH + POS_COOKIE pObj = container_of(work, struct os_cookie, mgmt_dma_done_work); + PRTMP_ADAPTER pAd = (PRTMP_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 &= ~INT_MGMT_DLY; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + pObj = (POS_COOKIE) pAd->OS_Cookie; + +/* printk("mgmt_dma_done_process\n"); */ + IntSource.word = 0; + IntSource.field.MgmtDmaDone = 1; + 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); + /* + * double check to avoid lose of interrupts + */ + if (pAd->int_pending & INT_MGMT_DLY) + { +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pObj->mgmt_dma_done_work); +#else + RTMP_OS_TASKLET_SCHE(&pObj->mgmt_dma_done_task); +#endif /* WORKQUEUE_BH */ + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + /* enable TxDataInt again */ + rt2860_int_enable(pAd, INT_MGMT_DLY); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); +} + + +#ifdef WORKQUEUE_BH +static void rx_done_workq(struct work_struct *work) +#else +static void rx_done_tasklet(unsigned long data) +#endif /* WORKQUEUE_BH */ +{ + unsigned long flags; + BOOLEAN bReschedule = 0; +#ifdef WORKQUEUE_BH + POS_COOKIE pObj = container_of(work, struct os_cookie, rx_done_work); + PRTMP_ADAPTER pAd = (PRTMP_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 &= ~(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); +#ifdef P2P_SUPPORT + bReschedule = RxDoneInterruptHandle(pAd); +#else +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + bReschedule = APRxDoneInterruptHandle(pAd); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + bReschedule = STARxDoneInterruptHandle(pAd, 0); +#endif /* CONFIG_STA_SUPPORT */ +#endif /* P2P_SUPPORT */ + +#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) + { +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pObj->rx_done_work); +#else + RTMP_OS_TASKLET_SCHE(&pObj->rx_done_task); +#endif /* WORKQUEUE_BH */ + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + /* enable RxINT again */ + rt2860_int_enable(pAd, INT_RX); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + +} + +#ifdef WORKQUEUE_BH +void fifo_statistic_full_workq(struct work_struct *work) +#else +void fifo_statistic_full_tasklet(unsigned long data) +#endif /* WORKQUEUE_BH */ +{ + unsigned long flags; +#ifdef WORKQUEUE_BH + POS_COOKIE pObj = container_of(work, struct os_cookie, fifo_statistic_full_work); + PRTMP_ADAPTER pAd = (PRTMP_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 &= ~(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) + { +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pObj->fifo_statistic_full_work); +#else + RTMP_OS_TASKLET_SCHE(&pObj->fifo_statistic_full_task); +#endif /* WORKQUEUE_BH */ + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + /* enable RxINT again */ + + rt2860_int_enable(pAd, FifoStaFullInt); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + +} + +#ifdef WORKQUEUE_BH +static void hcca_dma_done_workq(struct work_struct *work) +#else +static void hcca_dma_done_tasklet(unsigned long data) +#endif /* WORKQUEUE_BH */ +{ + unsigned long flags; + INT_SOURCE_CSR_STRUC IntSource; +#ifdef WORKQUEUE_BH + POS_COOKIE pObj = container_of(work, struct os_cookie, hcca_dma_done_work); + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) pObj->pAd_va; + +#else + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; + POS_COOKIE pObj; +#endif /* WORKQUEUE_BH */ + BOOLEAN bReschedule = 0; + + /* 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; + + + IntSource.word = 0; + IntSource.field.HccaDmaDone = 1; + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_pending &= ~INT_HCCA_DLY; + + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + + bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource); + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + /* + * double check to avoid lose of interrupts + */ + if ((pAd->int_pending & INT_HCCA_DLY) || bReschedule) + { +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pObj->hcca_dma_done_work); +#else + RTMP_OS_TASKLET_SCHE(&pObj->hcca_dma_done_task); +#endif /* WORKQUEUE_BH */ + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + /* enable TxDataInt again */ + rt2860_int_enable(pAd, INT_HCCA_DLY); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); +} + +#ifdef WORKQUEUE_BH +static void ac3_dma_done_workq(struct work_struct *work) +#else +static void ac3_dma_done_tasklet(unsigned long data) +#endif /* WORKQUEUE_BH */ +{ + unsigned long flags; + INT_SOURCE_CSR_STRUC IntSource; + BOOLEAN bReschedule = 0; +#ifdef WORKQUEUE_BH + POS_COOKIE pObj = container_of(work, struct os_cookie, ac3_dma_done_work); + PRTMP_ADAPTER pAd = (PRTMP_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 &= ~(INT_AC3_DLY); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + pObj = (POS_COOKIE) pAd->OS_Cookie; + +/* printk("ac0_dma_done_process\n"); */ + IntSource.word = 0; + IntSource.field.Ac3DmaDone = 1; + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_pending &= ~INT_AC3_DLY; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + + bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource); + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + /* + * double check to avoid lose of interrupts + */ + if ((pAd->int_pending & INT_AC3_DLY) || bReschedule) + { +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pObj->ac3_dma_done_work); +#else + RTMP_OS_TASKLET_SCHE(&pObj->ac3_dma_done_task); +#endif /* WORKQUEUE_BH */ + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + /* enable TxDataInt again */ + rt2860_int_enable(pAd, INT_AC3_DLY); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); +} + +#ifdef WORKQUEUE_BH +static void ac2_dma_done_workq(struct work_struct *work) +#else +static void ac2_dma_done_tasklet(unsigned long data) +#endif /* WORKQUEUE_BH */ +{ + unsigned long flags; + INT_SOURCE_CSR_STRUC IntSource; + BOOLEAN bReschedule = 0; +#ifdef WORKQUEUE_BH + POS_COOKIE pObj = container_of(work, struct os_cookie, ac2_dma_done_work); + PRTMP_ADAPTER pAd = (PRTMP_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 &= ~(INT_AC2_DLY); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + IntSource.word = 0; + IntSource.field.Ac2DmaDone = 1; + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_pending &= ~INT_AC2_DLY; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + + bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource); + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + + /* + * double check to avoid lose of interrupts + */ + if ((pAd->int_pending & INT_AC2_DLY) || bReschedule) + { +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pObj->ac2_dma_done_work); +#else + RTMP_OS_TASKLET_SCHE(&pObj->ac2_dma_done_task); +#endif /* WORKQUEUE_BH */ + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + /* enable TxDataInt again */ + rt2860_int_enable(pAd, INT_AC2_DLY); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); +} + +#ifdef WORKQUEUE_BH +static void ac1_dma_done_workq(struct work_struct *work) +#else +static void ac1_dma_done_tasklet(unsigned long data) +#endif /* WORKQUEUE_BH */ +{ + unsigned long flags; + BOOLEAN bReschedule = 0; + INT_SOURCE_CSR_STRUC IntSource; +#ifdef WORKQUEUE_BH + POS_COOKIE pObj = container_of(work, struct os_cookie, ac1_dma_done_work); + PRTMP_ADAPTER pAd = (PRTMP_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 &= ~(INT_AC1_DLY); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + pObj = (POS_COOKIE) pAd->OS_Cookie; + +/* printk("ac0_dma_done_process\n"); */ + IntSource.word = 0; + IntSource.field.Ac1DmaDone = 1; + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_pending &= ~INT_AC1_DLY; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + + bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource); + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + /* + * double check to avoid lose of interrupts + */ + if ((pAd->int_pending & INT_AC1_DLY) || bReschedule) + { +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pObj->ac1_dma_done_work); +#else + RTMP_OS_TASKLET_SCHE(&pObj->ac1_dma_done_task); +#endif /* WORKQUEUE_BH */ + + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + /* enable TxDataInt again */ + rt2860_int_enable(pAd, INT_AC1_DLY); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); +} + +#ifdef WORKQUEUE_BH +static void ac0_dma_done_workq(struct work_struct *work) +#else +static void ac0_dma_done_tasklet(unsigned long data) +#endif /* WORKQUEUE_BH */ +{ + unsigned long flags; + INT_SOURCE_CSR_STRUC IntSource; + BOOLEAN bReschedule = 0; +#ifdef WORKQUEUE_BH + POS_COOKIE pObj = container_of(work, struct os_cookie, ac0_dma_done_work); + PRTMP_ADAPTER pAd = (PRTMP_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 &= ~(INT_AC0_DLY); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + pObj = (POS_COOKIE) pAd->OS_Cookie; + +/* printk("ac0_dma_done_process\n"); */ + IntSource.word = 0; + IntSource.field.Ac0DmaDone = 1; + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_pending &= ~INT_AC0_DLY; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + +/* RTMPHandleMgmtRingDmaDoneInterrupt(pAd); */ + bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource); + + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + /* + * double check to avoid lose of interrupts + */ + if ((pAd->int_pending & INT_AC0_DLY) || bReschedule) + { +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pObj->ac0_dma_done_work); +#else + RTMP_OS_TASKLET_SCHE(&pObj->ac0_dma_done_task); +#endif /* WORKQUEUE_BH */ + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + return; + } + + /* enable TxDataInt again */ + rt2860_int_enable(pAd, INT_AC0_DLY); + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); +} + + + +#ifdef UAPSD_SUPPORT +/* +======================================================================== +Routine Description: + Used to send the EOSP frame. + +Arguments: + data Pointer to our adapter + +Return Value: + None + +Note: +======================================================================== +*/ +#ifdef WORKQUEUE_BH +static void uapsd_eosp_sent_workq(struct work_struct *work) +{ + POS_COOKIE pObj = container_of(work, struct os_cookie, uapsd_eosp_sent_work); + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) pObj->pAd_va; + + + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); +} +#else +static void uapsd_eosp_sent_tasklet(unsigned long data) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; + + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); +} +#endif /* WORKQUEUE_BH */ +#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; +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pObj->dfs_work); +#else + RTMP_OS_TASKLET_SCHE(&pObj->dfs_task); +#endif /* WORKQUEUE_BH */ +} + +#ifdef WORKQUEUE_BH +void dfs_workq(struct work_struct *work) +{ + POS_COOKIE pObj = container_of(work, struct os_cookie, dfs_work); + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) pObj->pAd_va; + + 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; + } + } + } + } +} +#else +void dfs_tasklet(unsigned long data) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data; + 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 /* WORKQUEUE_BH */ +#endif /* DFS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + +int print_int_count; + +VOID RTMPHandleInterrupt( + IN VOID *pAdSrc) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + INT_SOURCE_CSR_STRUC IntSource; + POS_COOKIE pObj; + unsigned long flags=0; + + + 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.word = 0x00000000L; +/* McuIntSource.word = 0x00000000L; */ + + /* */ + /* Get the interrupt sources & saved to local variable */ + /* */ + /*RTMP_IO_READ32(pAd, where, &McuIntSource.word); */ + /*RTMP_IO_WRITE32(pAd, , McuIntSource.word); */ + + /* */ + /* 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.word); + RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, IntSource.word); /* write 1 to clear */ + } +/* else */ +/* DBGPRINT(RT_DEBUG_TRACE, (">>>fOP_STATUS_DOZE<<<\n")); */ + +/* RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IsrAfterClear); */ +/* RTMP_IO_READ32(pAd, MCU_INT_SOURCE_CSR, &McuIsrAfterClear); */ +/* DBGPRINT(RT_DEBUG_INFO, ("====> RTMPHandleInterrupt(ISR=%08x,Mcu ISR=%08x, After clear ISR=%08x, MCU ISR=%08x)\n", */ +/* IntSource.word, McuIntSource.word, IsrAfterClear, McuIsrAfterClear)); */ + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) + return; + + /* Do nothing if Reset in progress */ + 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 + +#ifdef INF_VR9_HW_INT_WORKAROUND +redo: +#endif + + pAd->bPCIclkOff = FALSE; + + /* If required spinlock, each interrupt service routine has to acquire */ + /* and release itself. */ + /* */ + + /* Do nothing if NIC doesn't exist */ + if (IntSource.word == 0xffffffff) + { + RTMP_SET_FLAG(pAd, (fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS)); + return; + } + + + if (IntSource.word & TxCoherent) + { + /* + When the interrupt occurs, it means we kick a register to send + a packet, such as TX_MGMT CTX_IDX, but MAC finds some fields in + the transmit buffer descriptor is not correct, ex: all zeros. + */ + DBGPRINT(RT_DEBUG_WARN, (">>>TxCoherent<<<\n")); + } + + if (IntSource.word & RxCoherent) + { + DBGPRINT(RT_DEBUG_WARN, (">>>RxCoherent<<<\n")); + } + + if (IntSource.word & FifoStaFullInt) + { + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + if ((pAd->int_disable_mask & FifoStaFullInt) == 0) + { + /* mask FifoStaFullInt */ + rt2860_int_disable(pAd, FifoStaFullInt); +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pObj->fifo_statistic_full_work); +#else + RTMP_OS_TASKLET_SCHE(&pObj->fifo_statistic_full_task); +#endif /* WORKQUEUE_BH */ + } + pAd->int_pending |= FifoStaFullInt; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + } + + if (IntSource.word & INT_MGMT_DLY) + { + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + if ((pAd->int_disable_mask & INT_MGMT_DLY) ==0 ) + { + rt2860_int_disable(pAd, INT_MGMT_DLY); +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pObj->mgmt_dma_done_work); +#else + RTMP_OS_TASKLET_SCHE(&pObj->mgmt_dma_done_task); +#endif /* WORKQUEUE_BH */ + } + pAd->int_pending |= INT_MGMT_DLY ; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + } + + if (IntSource.word & INT_RX) + { + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + if ((pAd->int_disable_mask & INT_RX) == 0) + { +#ifdef UAPSD_SUPPORT + UAPSD_TIMING_RECORD_START(); + UAPSD_TIMING_RECORD(pAd, UAPSD_TIMING_RECORD_ISR); +#endif /* UAPSD_SUPPORT */ + + /* mask RxINT */ + rt2860_int_disable(pAd, INT_RX); +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pObj->rx_done_work); +#else + RTMP_OS_TASKLET_SCHE(&pObj->rx_done_task); +#endif /* WORKQUEUE_BH */ + } + pAd->int_pending |= INT_RX; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + } + + if (IntSource.word & INT_HCCA_DLY) + { + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + if ((pAd->int_disable_mask & INT_HCCA_DLY) == 0) + { + /* mask TxDataInt */ + rt2860_int_disable(pAd, INT_HCCA_DLY); +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pObj->hcca_dma_done_work); +#else + RTMP_OS_TASKLET_SCHE(&pObj->hcca_dma_done_task); +#endif /* WORKQUEUE_BH */ + } + pAd->int_pending |= INT_HCCA_DLY; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + } + + if (IntSource.word & INT_AC3_DLY) + { + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + if ((pAd->int_disable_mask & INT_AC3_DLY) == 0) + { + /* mask TxDataInt */ + rt2860_int_disable(pAd, INT_AC3_DLY); +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pObj->ac3_dma_done_work); +#else + RTMP_OS_TASKLET_SCHE(&pObj->ac3_dma_done_task); +#endif /* WORKQUEUE_BH */ + } + pAd->int_pending |= INT_AC3_DLY; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + } + + if (IntSource.word & INT_AC2_DLY) + { + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + if ((pAd->int_disable_mask & INT_AC2_DLY) == 0) + { + /* mask TxDataInt */ + rt2860_int_disable(pAd, INT_AC2_DLY); +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pObj->ac2_dma_done_work); +#else + RTMP_OS_TASKLET_SCHE(&pObj->ac2_dma_done_task); +#endif /* WORKQUEUE_BH */ + } + pAd->int_pending |= INT_AC2_DLY; + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + } + + if (IntSource.word & INT_AC1_DLY) + { + RTMP_INT_LOCK(&pAd->LockInterrupt, flags); + pAd->int_pending |= INT_AC1_DLY; + + if ((pAd->int_disable_mask & INT_AC1_DLY) == 0) + { + /* mask TxDataInt */ + rt2860_int_disable(pAd, INT_AC1_DLY); +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pObj->ac1_dma_done_work); +#else + RTMP_OS_TASKLET_SCHE(&pObj->ac1_dma_done_task); +#endif /* WORKQUEUE_BH */ + } + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + } + + if (IntSource.word & INT_AC0_DLY) + { + +/* + 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) + { + /* mask TxDataInt */ + rt2860_int_disable(pAd, INT_AC0_DLY); +#ifdef WORKQUEUE_BH + RTMP_OS_TASKLET_SCHE(&pObj->ac0_dma_done_work); +#else + RTMP_OS_TASKLET_SCHE(&pObj->ac0_dma_done_task); +#endif /* WORKQUEUE_BH */ + } + RTMP_INT_UNLOCK(&pAd->LockInterrupt, flags); + } + + if (IntSource.word & PreTBTTInt) + { + RTMPHandlePreTBTTInterrupt(pAd); + } + + if (IntSource.word & TBTTInt) + { + RTMPHandleTBTTInterrupt(pAd); + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef DFS_SUPPORT + if (IntSource.word & GPTimeOutInt) + { + NewTimerCB_Radar(pAd); + } +#endif /* DFS_SUPPORT */ + +#ifdef CARRIER_DETECTION_SUPPORT + if ((IntSource.word & INT_TONE_RADAR)) + { + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + RTMPHandleRadarInterrupt(pAd); + } +#endif /* CARRIER_DETECTION_SUPPORT*/ + + if (IntSource.word & McuCommand) + { + /*RTMPHandleMcuInterrupt(pAd);*/ + } + } + +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (IntSource.word & 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.word = 0x00000000L; + { + RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSource.word); + RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, IntSource.word); /* write 1 to clear */ + } + if (IntSource.word != 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. */ +#ifdef RT2860 + if (!((pObj->DeviceID == NIC2860_PCIe_DEVICE_ID) + ||(pObj->DeviceID == NIC2790_PCIe_DEVICE_ID))) + return; +#endif /* RT2860 */ + + + 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 */ + +#ifdef RT2860 + if (!((pObj->DeviceID == NIC2860_PCIe_DEVICE_ID) + ||(pObj->DeviceID == NIC2790_PCIe_DEVICE_ID))) + return; +#endif /* RT2860 */ + + 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; + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + pci_read_config_word(pci_dev, pConfig->ConfigDeviceID, &device_id); + device_id = le2cpu16(device_id); + pObj->DeviceID = device_id; + + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE); + if ( +#ifdef RT2860 + (device_id == NIC2860_PCIe_DEVICE_ID) || + (device_id == NIC2790_PCIe_DEVICE_ID) || + (device_id == VEN_AWT_PCIe_DEVICE_ID) || +#endif /* RT2860 */ + (RT3593_DEVICE_ID_CHECK(device_id))|| + (RT3592_DEVICE_ID_CHECK(device_id))|| + 0) + { + UINT32 MacCsr0 = 0;//, Index= 0; + WaitForAsicReady(pAd); + RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0); + +#ifdef CONFIG_STA_SUPPORT + pAd->chipCap.HW_PCIE_PS_SUPPORT=FALSE; + + if ( + RT3593_DEVICE_ID_CHECK(device_id)|| + 0) + { + /*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; + } + + + } + RtmpRaDevCtrlInit(pAd, RTMP_DEV_INF_PCI); + +} + + +#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 */ + 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, FALSE); + } + 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); +#ifdef RT2860 + if ((pObj->DeviceID == NIC2860_PCIe_DEVICE_ID) + ||(pObj->DeviceID == NIC2790_PCIe_DEVICE_ID)) + { + 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)); + } +#endif /* RT2860 */ + + 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) + { +#ifdef RT2860 + case NIC2860_PCIe_DEVICE_ID: + case NIC2790_PCIe_DEVICE_ID: + bChange = TRUE; + break; +#endif /* RT2860 */ + + 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/mt7620/src/os/linux/rt_rbus_pci_util.c b/mt7620/src/os/linux/rt_rbus_pci_util.c new file mode 100644 index 0000000..cb5b6c4 --- /dev/null +++ b/mt7620/src/os/linux/rt_rbus_pci_util.c @@ -0,0 +1,617 @@ +/**************************************************************************** + + 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 TxDesc Memory allocation. */ +void RTMP_AllocateTxDescMemory( + IN PPCI_DEV pPciDev, + IN UINT Index, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) +{ +/* POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; */ + dma_addr_t DmaAddr = (dma_addr_t)(*PhysicalAddress); + +#ifdef RTMP_RBUS_SUPPORT + *VirtualAddress = (PVOID)pci_alloc_consistent(NULL,sizeof(char)*Length, &DmaAddr); +#else + *VirtualAddress = (PVOID)pci_alloc_consistent(pPciDev,sizeof(char)*Length, &DmaAddr); +#endif + *PhysicalAddress = (NDIS_PHYSICAL_ADDRESS)DmaAddr; +} + + +/* Function for MgmtDesc Memory allocation. */ +void RTMP_AllocateMgmtDescMemory( + IN PPCI_DEV pPciDev, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) +{ +/* POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; */ + dma_addr_t DmaAddr = (dma_addr_t)(*PhysicalAddress); +#ifdef RTMP_RBUS_SUPPORT + *VirtualAddress = (PVOID)pci_alloc_consistent(NULL,sizeof(char)*Length, &DmaAddr); +#else + *VirtualAddress = (PVOID)pci_alloc_consistent(pPciDev,sizeof(char)*Length, &DmaAddr); +#endif + *PhysicalAddress = (NDIS_PHYSICAL_ADDRESS)DmaAddr; +} + + +/* Function for RxDesc Memory allocation. */ +void RTMP_AllocateRxDescMemory( + IN PPCI_DEV pPciDev, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) +{ +/* POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; */ + dma_addr_t DmaAddr = (dma_addr_t)(*PhysicalAddress); + +#ifdef DESC_32B_SUPPORT + *VirtualAddress = (PVOID)kmalloc(Length, GFP_KERNEL); + *PhysicalAddress = virt_to_phys(*VirtualAddress); +#else + +#ifdef RTMP_RBUS_SUPPORT + *VirtualAddress = (PVOID)pci_alloc_consistent(NULL,sizeof(char)*Length, &DmaAddr); +#else + *VirtualAddress = (PVOID)pci_alloc_consistent(pPciDev,sizeof(char)*Length, &DmaAddr); +#endif + *PhysicalAddress = (NDIS_PHYSICAL_ADDRESS)DmaAddr; +#endif /* DESC_32B_SUPPORT */ +} + + +/* Function for free allocated Desc Memory. */ +void RTMP_FreeDescMemory( + IN PPCI_DEV pPciDev, + IN ULONG Length, + IN PVOID VirtualAddress, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress) +{ +/* POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; */ + dma_addr_t DmaAddr = (dma_addr_t)(PhysicalAddress); +#ifdef RTMP_RBUS_SUPPORT + pci_free_consistent(NULL, Length, VirtualAddress, DmaAddr); +#else + pci_free_consistent(pPciDev, Length, VirtualAddress, DmaAddr); +#endif +} + + +/* 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 PhysicalAddress) +{ +/* POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; */ + dma_addr_t DmaAddr = (dma_addr_t)(*PhysicalAddress); +#ifdef RTMP_RBUS_SUPPORT + *VirtualAddress = (PVOID)pci_alloc_consistent(NULL,sizeof(char)*Length, &DmaAddr); +#else + *VirtualAddress = (PVOID)pci_alloc_consistent(pPciDev,sizeof(char)*Length, &DmaAddr); +#endif + *PhysicalAddress = (NDIS_PHYSICAL_ADDRESS)DmaAddr; +} + + +void RTMP_FreeFirstTxBuffer( + IN PPCI_DEV pPciDev, + IN ULONG Length, + IN BOOLEAN Cached, + IN PVOID VirtualAddress, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress) +{ +/* POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; */ + dma_addr_t DmaAddr = (dma_addr_t)(PhysicalAddress); +#ifdef RTMP_RBUS_SUPPORT + pci_free_consistent(NULL, Length, VirtualAddress, DmaAddr); +#else + pci_free_consistent(pPciDev, Length, VirtualAddress, DmaAddr); +#endif +} + + +/* + * 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 + * PhysicalAddress: 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 PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) +{ + 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) { + RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS); + *VirtualAddress = (PVOID) pkt->data; +/*#ifdef CONFIG_5VT_ENHANCE */ +/* *PhysicalAddress = PCI_MAP_SINGLE(pAd, *VirtualAddress, 1600, RTMP_PCI_DMA_FROMDEVICE); */ +/*#else */ + *PhysicalAddress = PCI_MAP_SINGLE_DEV(pPciDev, *VirtualAddress, Length, -1, RTMP_PCI_DMA_FROMDEVICE); +/*#endif */ + } else { + *VirtualAddress = (PVOID) NULL; + *PhysicalAddress = (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) +{ +/* PRTMP_ADAPTER pAd; */ +/* POS_COOKIE pObj; */ + + + 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) +{ +/* PRTMP_ADAPTER pAd; */ +/* POS_COOKIE pObj; */ + 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; + +/* pAd=(PRTMP_ADAPTER)handle; */ +/* pObj = (POS_COOKIE)pAd->OS_Cookie; */ + + if (size > 0) + pci_unmap_single(pPciDev, DmaAddr, size, direction); + +} + + + +#ifdef RTMP_PCI_SUPPORT +VOID *RTMPFindHostPCIDev( + IN VOID *pPciDevSrc) +{ + struct pci_dev *pci_dev = (struct pci_dev *)pPciDevSrc; + struct pci_dev *parent_pci_dev; + USHORT reg16; + UCHAR reg8; + UINT DevFn; + PPCI_DEV pPci_dev; +/* POS_COOKIE pObj; */ + +/* pObj = (POS_COOKIE) pAd->OS_Cookie; */ + +/* if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) */ +/* return; */ + + DBGPRINT(RT_DEBUG_TRACE, ("%s.===>\n", __FUNCTION__)); + + parent_pci_dev = NULL; + 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( + IN ULONG Value, + IN 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( + IN ULONG Value, + IN 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( + IN ULONG Value, + IN 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( + IN 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( + IN 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( + IN 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( + IN VOID *pDev, + IN UINT32 Offset, + OUT 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( + IN VOID *pDev, + IN UINT32 Offset, + IN 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( + IN VOID *pDev, + IN UINT32 Offset, + OUT 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( + IN VOID *pDev, + IN UINT32 Offset, + IN 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( + IN VOID *pDev, + IN 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( + IN 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( + IN VOID *pDev) +{ +#ifdef PCI_MSI_SUPPORT + pci_disable_msi(pDev); +#endif +} +#endif /* RTMP_PCI_SUPPORT */ + +#endif /* RTMP_MAC_PCI */ + +/* End of rt_rbus_pci_util.c */ diff --git a/mt7620/src/os/linux/rt_symb.c b/mt7620/src/os/linux/rt_symb.c new file mode 100644 index 0000000..f2f3fb5 --- /dev/null +++ b/mt7620/src/os/linux/rt_symb.c @@ -0,0 +1,10 @@ +#ifdef OS_ABL_SUPPORT + +#include +#include "rt_config.h" + +EXPORT_SYMBOL(RTMP_DRV_OPS_FUNCTION); + +#endif /* OS_ABL_SUPPORT */ + +/* End of rt_symb.c */ diff --git a/mt7620/src/os/linux/sta_ioctl.c b/mt7620/src/os/linux/sta_ioctl.c new file mode 100644 index 0000000..4775997 --- /dev/null +++ b/mt7620/src/os/linux/sta_ioctl.c @@ -0,0 +1,2842 @@ +/* + *************************************************************************** + * 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 MESH_SUPPORT + { SHOW_MESH_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "meshinfo" }, + { SHOW_NEIGHINFO_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "neighinfo" }, + { SHOW_MESH_ROUTE_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "meshrouteinfo" }, + { SHOW_MESH_ENTRY_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "meshentryinfo" }, + { SHOW_MULPATH_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "multipathinfo" }, + { SHOW_MCAST_AGEOUT_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mcastageoutinfo" }, + { SHOW_MESH_PKTSIG_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "pktsiginfo" }, + { SHOW_MESH_PROXY_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "meshproxyinfo" }, +#endif /* MESH_SUPPORT */ +#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" }, +#ifdef DOT11Z_TDLS_SUPPORT + { SHOW_TDLS_ENTRY_INFO, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "tdlsentryinfo" }, +#endif /* DOT11Z_TDLS_SUPPORT */ +/* --- 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 */ +}; + +extern INT32 ralinkrate[]; +extern UINT32 RT_RateSize; + + + + +/* +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; +/* UCHAR ch; */ + 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); + + /*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 (*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) + { + /* 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_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; +#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") == 0) + { + //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") == 0) + { + printk("STOP Turn off Wi-Fi hardware \n"); + kfree(ext); + return -1; + } + else if(rtstrcasecmp(ext,"RSSI") == 0) + { + 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") == 0) + { + snprintf(ext, min(dwrq->length, (UINT16)(strlen(ext)+1)),"LINKSPEED %d", 150); + } + else if(rtstrcasecmp(ext,"MACADDR") == 0) + { + 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") == 0) + { + snprintf(ext, min(dwrq->length, (UINT16)(strlen(ext)+1)),"OK"); + } + else if(rtstrcasecmp(ext,"SCAN-PASSIVE") == 0) + { + 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) +/* PBSS_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) + { + int rate_count = RT_RateSize/sizeof(__s32); +/* 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 rate_index = 12 + ((UCHAR)pIoctlScan->pBssTable[i].ChannelWidth * 24) + + ((UCHAR)shortGI *48) + ((UCHAR)maxMCS); + if (rate_index < 0) + rate_index = 0; + if (rate_index >= rate_count) + rate_index = rate_count-1; + iwe.u.bitrate.value = ralinkrate[rate_index] * 500000; + } + + 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( + IN struct net_device *net_dev, + IN OUT struct ifreq *rq, + IN 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: + 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/mt7620/src/os/linux/vr_bdlt.c b/mt7620/src/os/linux/vr_bdlt.c new file mode 100644 index 0000000..f802db0 --- /dev/null +++ b/mt7620/src/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/mt7620/src/os/linux/vr_ikans.c b/mt7620/src/os/linux/vr_ikans.c new file mode 100644 index 0000000..583125c --- /dev/null +++ b/mt7620/src/os/linux/vr_ikans.c @@ -0,0 +1,389 @@ +/**************************************************************************** + + 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( + IN struct sk_buff *skb_p, + IN struct net_device *net_dev); + +static INT32 IKANOS_WlanDataFramesTx( + IN void *_pAdBuf, + IN struct net_device *pNetDev); + +static void IKANOS_WlanPktFromAp( + IN apPreHeader_t *pFrame); + +static INT32 GetSpecInfoIdxFromBssid( + IN PRTMP_ADAPTER pAd, + IN INT32 FromWhichBSSID); + + + + +/* --------------------------------- 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( + IN UINT8 BssNum, + IN 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( + IN struct sk_buff *pSkb, + IN 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); +} /* End of IKANOS_DataFramesTx */ + + +/* +======================================================================== +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: +======================================================================== +*/ +/* 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( + IN PRTMP_ADAPTER pAd, + IN 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->egressList[0].pEgress = NULL; */ +/* apBuf->egressList[0].pFlowID = NULL; */ + apBuf->flags2 = 0; + + apClassify(IKANOS_PERAP_ID, apBuf, (void *)IKANOS_WlanPktFromAp); + dev_kfree_skb(pSkb); +} /* End of IKANOS_DataFrameRx */ + + + + +/* --------------------------------- 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( + IN void *_pAdBuf, + IN 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; + } /* End of if */ + + 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); +} /* End of IKANOS_WlanDataFramesTx */ + + +static INT32 GetSpecInfoIdxFromBssid( + IN PRTMP_ADAPTER pAd, + IN INT32 FromWhichBSSID) +{ + INT32 IfIdx = MAIN_MBSSID; + +#ifdef MESH_SUPPORT + if(FromWhichBSSID >= MIN_NET_DEVICE_FOR_MESH) + { + IfIdx = MAX_MBSSID_NUM(pAd) + MAX_WDS_ENTRY + MAX_APCLI_NUM; + } + else +#endif /* MESH_SUPPORT */ +#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: + Get real interface index, used in get_netdev_from_bssid() + +Arguments: + pAd - + FromWhichBSSID - + +Return Value: + None + +Note: +======================================================================== +*/ +static INT32 GetSpecInfoIdxFromBssid( + IN PRTMP_ADAPTER pAd, + IN INT32 FromWhichBSSID) +{ + INT32 IfIdx = MAIN_MBSSID; + +#ifdef MESH_SUPPORT + if(FromWhichBSSID >= MIN_NET_DEVICE_FOR_MESH) + { + IfIdx = MAX_MBSSID_NUM(pAd) + MAX_WDS_ENTRY + MAX_APCLI_NUM; + } + else +#endif /* MESH_SUPPORT */ +#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 */ +} /* End of GetSpecInfoIdxFromBssid */ + + +/* +======================================================================== +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( + IN apPreHeader_t *pFrame) +{ + PRTMP_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; + } /* End of if */ + + skb = (struct sk_buff *)translateApbuf2Mbuf(apBuf); + if (NULL == skb) + { + printk("ikanos> %s: skb is null *********************\n", __FUNCTION__); + return; + } /* End of if */ + + 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; +} /* End of IKANOS_WlanPktFromAp */ + +#endif /* IKANOS_VX_1X0 */ + +/* End of vr_ikans.c */ diff --git a/mt7620/src/rate_ctrl/alg_ags.c b/mt7620/src/rate_ctrl/alg_ags.c new file mode 100644 index 0000000..3e5833a --- /dev/null +++ b/mt7620/src/rate_ctrl/alg_ags.c @@ -0,0 +1,1375 @@ +/**************************************************************************** + * 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. + +***************************************************************************/ + +#define MODULE_AGS +#include "rt_config.h" + +#ifdef AGS_SUPPORT + + +/* */ +/* AGS: 1x1 HT-capable rate table */ +/* */ + UCHAR AGS1x1HTRateTable[] = + { + /* */ + /* [Item no.] [Mode]* [CurrMCS] [TrainUp] [TrainDown] [downMCS ] [upMCS3] [upMCS2] [upMCS1] */ + /* */ + /* [Mode]*: */ + /* bit0: STBC */ + /* bit1: Short GI */ + /* bit2: BW */ + /* bit4~bit5: Mode (0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ + /* */ + 0x09, 0x08, 0, 0, 0, 0, 0, 0, 0, /* Initial used item after association: the number of rate indexes, the initial mcs */ + 0x00, 0x21, 0, 30, 101, 0, 16, 8, 1, /* MCS 0 */ + 0x01, 0x21, 1, 20, 50, 0, 16, 9, 2, /* MCS 1 */ + 0x02, 0x21, 2, 20, 50, 1, 17, 9, 3, /* MCS 2 */ + 0x03, 0x21, 3, 15, 50, 2, 17, 10, 4, /* MCS 3 */ + 0x04, 0x21, 4, 15, 30, 3, 18, 11, 5, /* MCS 4 */ + 0x05, 0x21, 5, 10, 25, 4, 18, 12, 6, /* MCS 5 */ + 0x06, 0x21, 6, 8, 14, 5, 19, 12, 7, /* MCS 6 */ + 0x07, 0x21, 7, 8, 14, 6, 19, 12, 8, /* MCS 7 */ + 0x08, 0x23, 7, 8, 14, 7, 19, 12, 8, /* MCS 7 + Short GI */ +}; + + + +/* */ +/* AGS: 2x2 HT-capable rate table */ +/* */ + UCHAR AGS2x2HTRateTable[] = + { + /* */ + /* [Item no.] [Mode]* [CurrMCS] [TrainUp] [TrainDown] [downMCS ] [upMCS3] [upMCS2] [upMCS1] */ + /* */ + /* [Mode]*: */ + /* bit0: STBC */ + /* bit1: Short GI */ + /* bit2: BW */ + /* bit4~bit5: Mode (0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ + /* */ + 0x11, 0x10, 0, 0, 0, 0, 0, 0, 0, /* Initial used item after association: the number of rate indexes, the initial mcs */ + 0x00, 0x21, 0, 30, 101, 0, 16, 8, 1, /* MCS 0 */ + 0x01, 0x21, 1, 20, 50, 0, 16, 9, 2, /* MCS 1 */ + 0x02, 0x21, 2, 20, 50, 1, 17, 9, 3, /* MCS 2 */ + 0x03, 0x21, 3, 15, 50, 2, 17, 10, 4, /* MCS 3 */ + 0x04, 0x21, 4, 15, 30, 3, 18, 11, 5, /* MCS 4 */ + 0x05, 0x21, 5, 10, 25, 4, 18, 12, 6, /* MCS 5 */ + 0x06, 0x21, 6, 8, 14, 5, 19, 12, 7, /* MCS 6 */ + 0x07, 0x21, 7, 8, 14, 6, 19, 12, 7, /* MCS 7 */ + 0x08, 0x20, 8, 30, 50, 0, 16, 9, 2, /* MCS 8 */ + 0x09, 0x20, 9, 20, 50, 8, 17, 10, 4, /* MCS 9 */ + 0x0A, 0x20, 10, 20, 50, 9, 18, 11, 5, /* MCS 10 */ + 0x0B, 0x20, 11, 15, 30, 10, 18, 12, 6, /* MCS 11 */ + 0x0C, 0x20, 12, 15, 30, 11, 20, 13, 12, /* MCS 12 */ + 0x0D, 0x20, 13, 8, 20, 12, 20, 14, 13, /* MCS 13 */ + 0x0E, 0x20, 14, 8, 18, 13, 21, 15, 14, /* MCS 14 */ + 0x0F, 0x20, 15, 8, 25, 14, 21, 16, 15, /* MCS 15 */ + 0x10, 0x22, 15, 8, 25, 15, 21, 16, 16, /* MCS 15 + Short GI */ +}; + + + +/* */ +/* AGS: 3x3 HT-capable rate table */ +/* */ + UCHAR AGS3x3HTRateTable[] = + { + /* */ + /* [Item no.] [Mode]* [CurrMCS] [TrainUp] [TrainDown] [downMCS ] [upMCS3] [upMCS2] [upMCS1] */ + /* */ + /* [Mode]*: */ + /* bit0: STBC */ + /* bit1: Short GI */ + /* bit2: BW */ + /* bit4~bit5: Mode (0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ + /* */ + 0x19, 0x18, 0, 0, 0, 0, 0, 0, 0, /* Initial used item after association: the number of rate indexes, the initial mcs */ + 0x00, 0x21, 0, 30, 101, 0, 16, 8, 1, /* MCS 0 */ + 0x01, 0x21, 1, 20, 50, 0, 16, 9, 2, /* MCS 1 */ + 0x02, 0x21, 2, 20, 50, 1, 17, 9, 3, /* MCS 2 */ + 0x03, 0x21, 3, 15, 50, 2, 17, 10, 4, /* MCS 3 */ + 0x04, 0x21, 4, 15, 30, 3, 18, 11, 5, /* MCS 4 */ + 0x05, 0x21, 5, 10, 25, 4, 18, 12, 6, /* MCS 5 */ + 0x06, 0x21, 6, 8, 14, 5, 19, 12, 7, /* MCS 6 */ + 0x07, 0x21, 7, 8, 14, 6, 19, 12, 7, /* MCS 7 */ + 0x08, 0x20, 8, 30, 50, 0, 16, 9, 2, /* MCS 8 */ + 0x09, 0x20, 9, 20, 50, 8, 17, 10, 4, /* MCS 9 */ + 0x0A, 0x20, 10, 20, 50, 9, 18, 11, 5, /* MCS 10 */ + 0x0B, 0x20, 11, 15, 30, 10, 18, 12, 6, /* MCS 11 */ + 0x0C, 0x20, 12, 15, 30, 11, 20, 13, 12, /* MCS 12 */ + 0x0D, 0x20, 13, 8, 20, 12, 20, 14, 13, /* MCS 13 */ + 0x0E, 0x20, 14, 8, 18, 13, 21, 15, 14, /* MCS 14 */ + 0x0F, 0x20, 15, 8, 14, 14, 21, 15, 15, /* MCS 15 */ + 0x10, 0x20, 16, 30, 50, 8, 17, 9, 3, /* MCS 16 */ + 0x11, 0x20, 17, 20, 50, 16, 18, 11, 5, /* MCS 17 */ + 0x12, 0x20, 18, 20, 50, 17, 19, 12, 7, /* MCS 18 */ + 0x13, 0x20, 19, 15, 30, 18, 20, 13, 19, /* MCS 19 */ + 0x14, 0x20, 20, 15, 30, 19, 21, 15, 20, /* MCS 20 */ + 0x15, 0x20, 21, 8, 20, 20, 22, 21, 21, /* MCS 21 */ + 0x16, 0x20, 22, 8, 20, 21, 23, 22, 22, /* MCS 22 */ + 0x17, 0x20, 23, 6, 18, 22, 24, 23, 23, /* MCS 23 */ + 0x18, 0x22, 23, 6, 14, 23, 24, 24, 24, /* MCS 23 + Short GI */ +}; + + + + +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; +} + + +/* */ +/* 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; + PRTMP_TX_RATE_SWITCH_AGS pCurrTxRate = NULL; + PRTMP_TX_RATE_SWITCH pNextTxRate = NULL; + UCHAR TrainUp = 0, TrainDown = 0; + CHAR RssiOffset = 0; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n\nAGS: ---> %s\n", __FUNCTION__)); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: QuickAGS: AccuTxTotalCnt = %lu, TxSuccess = %lu, TxRetransmit = %lu, TxFailCount = %lu, TxErrorRatio = %lu\n", + __FUNCTION__, + pAGSStatisticsInfo->AccuTxTotalCnt, + pAGSStatisticsInfo->TxSuccess, + pAGSStatisticsInfo->TxRetransmit, + pAGSStatisticsInfo->TxFailCount, + pAGSStatisticsInfo->TxErrorRatio)); + + /* for 3*3, 1st time, pEntry->CurrTxRateIndex = 24 in StaAddMacTableEntry() */ + CurrRateIdx = pEntry->CurrTxRateIndex; + + if (CurrRateIdx >= TableSize) + { + CurrRateIdx = TableSize - 1; + } + + pCurrTxRate = (PRTMP_TX_RATE_SWITCH_AGS)(&pTable[(CurrRateIdx + 1) * + SIZE_OF_AGS_RATE_TABLE_ENTRY]); + + /* */ + /* Select the next upgrade rate and the next downgrade rate, if any */ + /* */ + do + { + if (InitTxRateIdx == AGS3x3HTRateTable[1]) + { + /* 3*3 table */ + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("%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, ... */ + switch (pEntry->AGSCtrl.MCSGroup) + { + case 0: /* MCS selection in round robin policy (different MCS group) */ + { + UpRateIdx = pCurrTxRate->upMcs3; + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("ags> MCSGroup = 0; UpRateIdx = %d in group 3 is better.\n", + UpRateIdx)); + + /* MCS group #2 has better Tx quality */ + if ((pEntry->TxQuality[UpRateIdx] > + pEntry->TxQuality[pCurrTxRate->upMcs2]) && + (pCurrTxRate->upMcs2 != pCurrTxRate->ItemNo)) + { + /* quality for group 2 is better */ + UpRateIdx = pCurrTxRate->upMcs2; + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("ags> MCSGroup = 0; UpRateIdx = %d in group 2 is better.\n", + UpRateIdx)); + } + + /* MCS group #1 has better Tx quality */ + if ((pEntry->TxQuality[UpRateIdx] > + pEntry->TxQuality[pCurrTxRate->upMcs1]) && + (pCurrTxRate->upMcs1 != pCurrTxRate->ItemNo)) + { + /* quality for group 1 is better */ + UpRateIdx = pCurrTxRate->upMcs1; + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("ags> MCSGroup = 0; UpRateIdx = %d in group 1 is better.\n", + UpRateIdx)); + } + } + break; + + case 3: + { + UpRateIdx = pCurrTxRate->upMcs3; + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("ags> MCSGroup = 3; UpRateIdx = %d\n", + UpRateIdx)); + } + break; + + case 2: + { + UpRateIdx = pCurrTxRate->upMcs2; + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("ags> MCSGroup = 2; UpRateIdx = %d\n", + UpRateIdx)); + } + break; + + case 1: + { + UpRateIdx = pCurrTxRate->upMcs1; + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("ags> MCSGroup = 1; UpRateIdx = %d\n", + UpRateIdx)); + } + break; + + default: + { + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("%s: AGS: [3x3 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->upMcs3] > + pEntry->TxQuality[pCurrTxRate->upMcs2]) && + (pCurrTxRate->upMcs2 != pCurrTxRate->ItemNo)) || + ((pEntry->TxQuality[pCurrTxRate->upMcs3] > + pEntry->TxQuality[pCurrTxRate->upMcs1]) && + (pCurrTxRate->upMcs1 != pCurrTxRate->ItemNo)))) + { + /* quality of group 2 or 1 is better than group 3 */ + /* just show debug information here */ + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("%s: ###################################################" + "#######################\n", + __FUNCTION__)); + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("%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 (InitTxRateIdx == AGS2x2HTRateTable[1]) + { + /* 2*2 table */ + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("%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_TRACE, + ("%s: ###################################################" + "#######################\n", + __FUNCTION__)); + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("%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_TRACE, + ("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_TRACE, + ("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 MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0; + UCHAR MCS8 = 0, MCS9 = 0, MCS10 = 0, MCS11 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0; + UCHAR MCS16 = 0, MCS17 = 0, MCS18 = 0, MCS19 = 0, MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; + + /* */ + /* Check the existence and index of each needed MCS */ + /* */ + /* for 3*3, maximum is 0x19 columns */ + while (idx < pTable[0]) + { + pCurrTxRate = (PRTMP_TX_RATE_SWITCH_AGS)(&pTable[(idx + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]); + + if (pCurrTxRate->CurrMCS == MCS_0) + { + MCS0 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_1) + { + MCS1 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_2) + { + MCS2 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_3) + { + MCS3 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_4) + { + MCS4 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_5) + { + MCS5 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_6) + { + MCS6 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_7) + { + MCS7 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_8) + { + MCS8 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_9) + { + MCS9 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_10) + { + MCS10 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_11) + { + MCS11 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_12) + { + MCS12 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_13) + { + MCS13 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_14) + { + MCS14 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_15) + { + MCS15 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_16) + { + MCS16 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_17) + { + MCS17 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_18) + { + MCS18 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_19) + { + MCS19 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_20) + { + MCS20 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_21) + { + MCS21 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_22) + { + MCS22 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_23) + { + MCS23 = idx; + } + + idx++; + } + + RssiOffset = 0; + + if (InitTxRateIdx == AGS3x3HTRateTable[1]) + { + /* */ + /* 3x3 peer device (Adhoc, DLS or AP) */ + /* */ + if (MCS23 && (pAGSStatisticsInfo->RSSI > (-67 + RssiOffset))) + { + TxRateIdx = MCS23; + } + else if (MCS22 && (pAGSStatisticsInfo->RSSI > (-69 + RssiOffset))) + { + TxRateIdx = MCS22; + } + else if (MCS21 && (pAGSStatisticsInfo->RSSI > (-72 + RssiOffset))) + { + TxRateIdx = MCS21; + } + else if (MCS20 && (pAGSStatisticsInfo->RSSI > (-74 + RssiOffset))) + { + TxRateIdx = MCS20; + } + else if (MCS19 && (pAGSStatisticsInfo->RSSI > (-78 + RssiOffset))) + { + TxRateIdx = MCS19; + } + else if (MCS18 && (pAGSStatisticsInfo->RSSI > (-80 + RssiOffset))) + { + TxRateIdx = MCS18; + } + else if (MCS17 && (pAGSStatisticsInfo->RSSI > (-85 + RssiOffset))) + { + TxRateIdx = MCS17; + } + else + { + TxRateIdx = MCS16; + } + + pEntry->AGSCtrl.MCSGroup = 3; + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("ags> Group3 RSSI = %d, TxRateIdx = %d\n", + pAGSStatisticsInfo->RSSI, TxRateIdx)); + } + else if (InitTxRateIdx == AGS2x2HTRateTable[1]) + { + /* */ + /* 2x2 peer device (Adhoc, DLS or AP) */ + /* */ + if (MCS15 && (pAGSStatisticsInfo->RSSI > (-69 + RssiOffset))) + { + TxRateIdx = MCS15; + } + else if (MCS14 && (pAGSStatisticsInfo->RSSI > (-71 + RssiOffset))) + { + TxRateIdx = MCS14; + } + else if (MCS13 && (pAGSStatisticsInfo->RSSI > (-74 + RssiOffset))) + { + TxRateIdx = MCS13; + } + else if (MCS12 && (pAGSStatisticsInfo->RSSI > (-76 + RssiOffset))) + { + TxRateIdx = MCS12; + } + else if (MCS11 && (pAGSStatisticsInfo->RSSI > (-80 + RssiOffset))) + { + TxRateIdx = MCS11; + } + else if (MCS10 && (pAGSStatisticsInfo->RSSI > (-82 + RssiOffset))) + { + TxRateIdx = MCS10; + } + else if (MCS9 && (pAGSStatisticsInfo->RSSI > (-87 + RssiOffset))) + { + TxRateIdx = MCS9; + } + else + { + TxRateIdx = MCS8; + } + + pEntry->AGSCtrl.MCSGroup = 2; + } + else + { + /* */ + /* 1x1 peer device (Adhoc, DLS or AP) */ + /* */ + if (MCS7 && (pAGSStatisticsInfo->RSSI > (-71 + RssiOffset))) + { + TxRateIdx = MCS7; + } + else if (MCS6 && (pAGSStatisticsInfo->RSSI > (-73 + RssiOffset))) + { + TxRateIdx = MCS6; + } + else if (MCS5 && (pAGSStatisticsInfo->RSSI > (-76 + RssiOffset))) + { + TxRateIdx = MCS5; + } + else if (MCS4 && (pAGSStatisticsInfo->RSSI > (-78 + RssiOffset))) + { + TxRateIdx = MCS4; + } + else if (MCS3 && (pAGSStatisticsInfo->RSSI > (-82 + RssiOffset))) + { + TxRateIdx = MCS3; + } + else if (MCS2 && (pAGSStatisticsInfo->RSSI > (-84 + RssiOffset))) + { + TxRateIdx = MCS2; + } + else if (MCS1 && (pAGSStatisticsInfo->RSSI > (-89 + RssiOffset))) + { + TxRateIdx = MCS1; + } + else + { + TxRateIdx = MCS0; + } + + pEntry->AGSCtrl.MCSGroup = 1; + } + + pEntry->AGSCtrl.lastRateIdx = pEntry->CurrTxRateIndex; + pEntry->CurrTxRateIndex = TxRateIdx; + + pNextTxRate = (PRTMP_TX_RATE_SWITCH)(&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 = 0; + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("%s: AGS: The MCS selection is based on the RSSI, and skips " + "the rate tuning this time.\n", + __FUNCTION__)); + + return; + } + + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("%s: AGS: TrainUp:%d, TrainDown:%d\n", + __FUNCTION__, TrainUp, TrainDown)); + + do + { + BOOLEAN bTrainUpDown = FALSE; + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("%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_TRACE, + ("%s: AGS: (DOWN) TxErrorRatio >= TrainDown\n",__FUNCTION__)); + bTrainUpDown = TRUE; + pEntry->TxQuality[CurrRateIdx] = AGS_TX_QUALITY_WORST_BOUND; + } + else if (pAGSStatisticsInfo->TxErrorRatio <= TrainUp) /* Good quality */ + { + /* error ratio low, maybe rate up */ + bTrainUpDown = TRUE; + bUpgradeQuality = TRUE; + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("%s: AGS: (UP) pEntry->TxQuality[CurrRateIdx] = %d, " + "pEntry->TxRateUpPenalty = %d\n", + __FUNCTION__, + pEntry->TxQuality[CurrRateIdx], + pEntry->TxRateUpPenalty)); + + if (pEntry->TxQuality[CurrRateIdx]) + { + /* Good quality in the current Tx rate */ + pEntry->TxQuality[CurrRateIdx]--; + } + + if (pEntry->TxRateUpPenalty) /* no use for the parameter */ + { + pEntry->TxRateUpPenalty--; + } + else + { + if (pEntry->TxQuality[pCurrTxRate->upMcs3] && + (pCurrTxRate->upMcs3 != CurrRateIdx)) + { + /* hope do rate up next time for the MCS */ + pEntry->TxQuality[pCurrTxRate->upMcs3]--; + } + + if (pEntry->TxQuality[pCurrTxRate->upMcs2] && + (pCurrTxRate->upMcs2 != CurrRateIdx)) + { + /* hope do rate up next time for the MCS */ + pEntry->TxQuality[pCurrTxRate->upMcs2]--; + } + + if (pEntry->TxQuality[pCurrTxRate->upMcs1] && + (pCurrTxRate->upMcs1 != CurrRateIdx)) + { + /* hope do rate up next time for the MCS */ + pEntry->TxQuality[pCurrTxRate->upMcs1]--; + } + } + } + else if (pEntry->AGSCtrl.MCSGroup > 0) /*even if TxErrorRatio > TrainUp */ + { + /* not bad and not good */ + if (UpRateIdx != 0) + { + bTrainUpDown = TRUE; + + if (pEntry->TxQuality[CurrRateIdx]) + { + /* Good quality in the current Tx rate */ + pEntry->TxQuality[CurrRateIdx]--; + } + + if (pEntry->TxQuality[UpRateIdx]) + { + /* It may improve next train-up Tx rate's quality */ + pEntry->TxQuality[UpRateIdx]--; + } + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("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_TRACE, ("%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 = 2; /* Tx 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 = 1; /* Tx rate up */ + DBGPRINT_RAW(RT_DEBUG_TRACE, ("ags> rate up!\n")); + } + } + } while (FALSE); + + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("%s: AGS: pEntry->CurrTxRateIndex = %d, CurrRateIdx = %d, pEntry->LastSecTxRateChangeAction = %d\n", + __FUNCTION__, + pEntry->CurrTxRateIndex, + CurrRateIdx, + pEntry->LastSecTxRateChangeAction)); + + /* rate up/down post handle */ + /* Tx rate up */ + if ((pEntry->CurrTxRateIndex != CurrRateIdx) && + (pEntry->LastSecTxRateChangeAction == 1)) + { + DBGPRINT_RAW(RT_DEBUG_TRACE, ("%s: AGS: ++TX rate from %d to %d\n", + __FUNCTION__, + CurrRateIdx, + pEntry->CurrTxRateIndex)); + + pEntry->TxRateUpPenalty = 0; + pEntry->LastSecTxRateChangeAction = 1; /* Tx rate up */ + RTMPZeroMemory(pEntry->PER, sizeof(UCHAR) * (MAX_TX_RATE_INDEX+1)); + pEntry->AGSCtrl.lastRateIdx = CurrRateIdx; + + /* */ + /* Tx rate fast train up */ + /* */ + if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) + { + RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, DEF_QUICK_RA_TIME_INTERVAL); + + pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE; + } + + bTxRateChanged = TRUE; + } + else if ((pEntry->CurrTxRateIndex != CurrRateIdx) && + (pEntry->LastSecTxRateChangeAction == 2)) /* Tx rate down */ + { + DBGPRINT_RAW(RT_DEBUG_TRACE, ("%s: AGS: --TX rate from %d to %d\n", + __FUNCTION__, + CurrRateIdx, + pEntry->CurrTxRateIndex)); + + pEntry->TxRateUpPenalty = 0; /* No penalty */ + pEntry->LastSecTxRateChangeAction = 2; /* Tx rate down */ + pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0; + pEntry->PER[pEntry->CurrTxRateIndex] = 0; + pEntry->AGSCtrl.lastRateIdx = CurrRateIdx; + + /* Tx rate fast train down */ + if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) + { + RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, DEF_QUICK_RA_TIME_INTERVAL); + + pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE; + } + + bTxRateChanged = TRUE; + } + else /* Tx rate remains unchanged. */ + { + pEntry->LastSecTxRateChangeAction = 0; /* Tx rate remains unchanged. */ + bTxRateChanged = FALSE; + DBGPRINT_RAW(RT_DEBUG_TRACE, ("ags> no rate up/down!\n")); + } + + pEntry->LastTxOkCount = pAGSStatisticsInfo->TxSuccess; + + /* set new tx rate */ + pNextTxRate = (PRTMP_TX_RATE_SWITCH)\ + (&pTable[(pEntry->CurrTxRateIndex + 1) * + SIZE_OF_AGS_RATE_TABLE_ENTRY]); + + if ((bTxRateChanged == TRUE) && (pNextTxRate != NULL)) + { + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("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) && (pAd->OpMode == OPMODE_STA) && (!DLS_ON(pAd)) && (!TDLS_ON(pAd))) */ + 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_TRACE, ("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_TRACE, ("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; + PRTMP_TX_RATE_SWITCH_AGS pCurrTxRate = NULL; + PRTMP_TX_RATE_SWITCH 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_TRACE, + ("%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 = (PRTMP_TX_RATE_SWITCH_AGS)(&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_TRACE, ("%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)) + { + if ((pEntry->LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount) /* Poor quality */ + { + pEntry->CurrTxRateIndex = DownRateIdx; + pEntry->TxQuality[CurrRateIdx] = AGS_TX_QUALITY_WORST_BOUND; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("%s: QuickAGS: (UP) bad Tx ok count (L:%lu, C:%lu)\n", + __FUNCTION__, + pEntry->LastTxOkCount, + OneSecTxNoRetryOKRationCount)); + } + else /* Good quality */ + { + DBGPRINT_RAW(RT_DEBUG_TRACE, ("%s: QuickAGS: (UP) keep rate-up (L:%lu, C:%lu)\n", + __FUNCTION__, + pEntry->LastTxOkCount, + OneSecTxNoRetryOKRationCount)); + + RTMPZeroMemory(pEntry->TxQuality, sizeof(USHORT) * (MAX_TX_RATE_INDEX+1)); + + if (pEntry->AGSCtrl.MCSGroup == 0) + { + if (InitTxRateIdx == AGS3x3HTRateTable[1]) + { + /* */ + /* 3x3 peer device (Adhoc, DLS or AP) */ + /* */ + pEntry->AGSCtrl.MCSGroup = 3; + } + else if (InitTxRateIdx == AGS2x2HTRateTable[1]) + { + /* */ + /* 2x2 peer device (Adhoc, DLS or AP) */ + /* */ + pEntry->AGSCtrl.MCSGroup = 2; + } + else + { + pEntry->AGSCtrl.MCSGroup = 1; + } + } + } + } + else if ((pEntry->LastSecTxRateChangeAction == 2) && + (CurrRateIdx != UpRateIdx)) /* Tx rate up */ + { + if ((pAGSStatisticsInfo->TxErrorRatio >= 50) || + (pAGSStatisticsInfo->TxErrorRatio >= TrainDown)) /* Poor quality */ + { + if (InitTxRateIdx == AGS3x3HTRateTable[1]) + { + /* */ + /* 3x3 peer device (Adhoc, DLS or AP) */ + /* */ + pEntry->AGSCtrl.MCSGroup = 3; + } + else if (InitTxRateIdx == AGS2x2HTRateTable[1]) + { + /* */ + /* 2x2 peer device (Adhoc, DLS or AP) */ + /* */ + pEntry->AGSCtrl.MCSGroup = 2; + } + else + { + pEntry->AGSCtrl.MCSGroup = 1; + } + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("%s: QuickAGS: (DOWN) direct train down (TxErrorRatio[%lu] >= TrainDown[%d])\n", + __FUNCTION__, + pAGSStatisticsInfo->TxErrorRatio, + TrainDown)); + } + else if ((pEntry->LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount) + { + pEntry->CurrTxRateIndex = UpRateIdx; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("%s: QuickAGS: (DOWN) bad tx ok count (L:%lu, C:%lu)\n", + __FUNCTION__, + pEntry->LastTxOkCount, + OneSecTxNoRetryOKRationCount)); + } + else + { + if (InitTxRateIdx == AGS3x3HTRateTable[1]) + { + /* */ + /* 3x3 peer device (Adhoc, DLS or AP) */ + /* */ + pEntry->AGSCtrl.MCSGroup = 3; + } + else if (InitTxRateIdx == AGS2x2HTRateTable[1]) + { + /* */ + /* 2x2 peer device (Adhoc, DLS or AP) */ + /* */ + pEntry->AGSCtrl.MCSGroup = 2; + } + else + { + pEntry->AGSCtrl.MCSGroup = 1; + } + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("%s: QuickAGS: (Down) keep rate-down (L:%lu, C:%lu)\n", + __FUNCTION__, + pEntry->LastTxOkCount, + OneSecTxNoRetryOKRationCount)); + } + } + }while (FALSE); + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("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 = (PRTMP_TX_RATE_SWITCH_AGS)(&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_TRACE, ("%s: QuickAGS: Incorrect MCS group, pEntry->AGSCtrl.MCSGroup = %d\n", + __FUNCTION__, + pEntry->AGSCtrl.MCSGroup)); + } + break; + } + + if (UpRateIdx == pEntry->CurrTxRateIndex) + { + pEntry->AGSCtrl.MCSGroup = 0; /* Try to escape the local optima */ + } + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("%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_TRACE, ("%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_TRACE, ("%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_TRACE, ("%s: QuickAGS: rate is not changed\n", + __FUNCTION__)); + } + + pNextTxRate = (PRTMP_TX_RATE_SWITCH)(&pTable[(pEntry->CurrTxRateIndex + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]); + if ((bTxRateChanged == TRUE) && (pNextTxRate != NULL)) + { + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("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_TRACE, ("QuickAGS: <--- %s\n", __FUNCTION__)); +} + + + +#endif /* AGS_SUPPORT */ + +/* End of ags.c */ diff --git a/mt7620/src/rate_ctrl/alg_grp.c b/mt7620/src/rate_ctrl/alg_grp.c new file mode 100644 index 0000000..48697d1 --- /dev/null +++ b/mt7620/src/rate_ctrl/alg_grp.c @@ -0,0 +1,2213 @@ +/**************************************************************************** + * 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" + + +/* + MlmeSetMcsGroup - set initial mcsGroup based on supported MCSs + On exit pEntry->mcsGroup is set to the mcsGroup +*/ +VOID MlmeSetMcsGroup( + IN PRTMP_ADAPTER pAd, + OUT PMAC_TABLE_ENTRY pEntry) +{ +#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; +} + + +/* + MlmeSelectUpRate - select UpRate based on MCS group + returns the UpRate index and updates the MCS group +*/ +UCHAR MlmeSelectUpRate( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PRTMP_TX_RATE_SWITCH_3S pCurrTxRate) +{ + UCHAR UpRateIdx = 0; + + while (1) + { + if ((pEntry->HTCapability.MCSSet[2] == 0xff) && (pAd->CommonCfg.TxStream == 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, ("wrong mcsGroup value\n")); + break; + } + + } + 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))) + { + 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, ("wrong mcsGroup value %d\n", pEntry->mcsGroup)); + break; + } + + } + else + { + switch (pEntry->mcsGroup) + { + case 1: + case 0: + UpRateIdx = pCurrTxRate->upMcs1; + break; + default: + DBGPRINT_RAW(RT_DEBUG_TRACE, ("wrong mcsGroup value %d\n", pEntry->mcsGroup)); + break; + } + } + + /* If going up from CCK to MCS32 make sure it's allowed */ + if (PTX_RATE_SWITCH_ENTRY_3S(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_RATE_SWITCH_ENTRY_3S(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_RATE_SWITCH_ENTRY_3S(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 PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR CurrRateIdx) +{ + UCHAR DownRateIdx = PTX_RATE_SWITCH_ENTRY_3S(pEntry->pTable, CurrRateIdx)->downMcs; + PRTMP_TX_RATE_SWITCH_3S pDownRate; + + /* Loop until a valid down rate is found */ + while (1) { + pDownRate = PTX_RATE_SWITCH_ENTRY_3S(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) + { + /* If 20MHz MCS0 fallback enabled and in 40MHz then MCS32 is valid and will be mapped to 20MHz MCS0 */ + if (pEntry->MaxHTPhyMode.field.BW==BW_40 && + pAd->CommonCfg.BBPCurrentBW==BW_40 +#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 (pEntry->MaxHTPhyMode.field.BW==BW_40 && + pAd->CommonCfg.BBPCurrentBW==BW_40 && + (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; +} + +/* + 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; + PRTMP_TX_RATE_SWITCH_3S pCurrTxRate; + UCHAR *pTable = pEntry->pTable; + + for (idx=0; idx<24; idx++) + mcs[idx] = -1; + + /* check the existence and index of each needed MCS */ + for (idx=0; idxpTable, 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 */ + +#if defined(RT2883) || defined(RT3883) + /* Debug Option: Limit PHY Rate if enabled */ + if (pAd->CommonCfg.PhyRateLimit != 0) + { + USHORT phyRateLimit20; + + phyRateLimit20 = pEntry->HTPhyMode.field.BW==BW_20? pAd->CommonCfg.PhyRateLimit: pAd->CommonCfg.PhyRateLimit*13/27; + + mcs[13] = mcs[14] = mcs[15] = mcs[20] = mcs[21] = mcs[22] = mcs[23] = 0; + + if (phyRateLimit20 <= 65) + mcs[7] = mcs[12] = mcs[19] = 0; + + if (phyRateLimit20 <= 40) + mcs[5] = mcs[6] = mcs[11] = mcs[18] = 0; + + if (phyRateLimit20 <= 20) + mcs[3] = mcs[4] = mcs[9] = mcs[10] = mcs[17] = 0; + } +#endif /* defined(RT2883) || defined(RT3883) */ +} + + +/* + 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 + if (ADAPT_RATE_TABLE(pTable) || + (pTable == RateSwitchTable11BGN3S) || + (pTable == RateSwitchTable11BGN3SForABand)) + {/* N mode with 3 stream */ + if ((pEntry->HTCapability.MCSSet[2] == 0xff) && (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) && + ((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; +} + +/* + MlmeRAEstimateThroughput - estimate Throughput based on PER and PHY rate + pEntry - the MAC table entry for this STA + pCurrTxRate - pointer to Rate table entry for rate + TxErrorRatio - the PER +*/ +static ULONG MlmeRAEstimateThroughput( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PRTMP_TX_RATE_SWITCH_3S pCurrTxRate, + IN ULONG TxErrorRatio) +{ + ULONG estTP = (100-TxErrorRatio)*pCurrTxRate->dataRate; + + /* Adjust rates for MCS32-40MHz mapped to MCS0-20MHz and for non-CCK 40MHz */ + if (pCurrTxRate->CurrMCS == MCS_32) + { +#ifdef DBG_CTRL_SUPPORT + if ((pAd->CommonCfg.DebugFlags & DBF_DISABLE_20MHZ_MCS0)==0) + estTP /= 2; +#endif /* DBG_CTRL_SUPPORT */ + } + else if ((pCurrTxRate->Mode==MODE_HTMIX) || (pCurrTxRate->Mode==MODE_HTGREENFIELD)) + { + if (pEntry->MaxHTPhyMode.field.BW==BW_40 +#ifdef DBG_CTRL_SUPPORT + || (pAd->CommonCfg.DebugFlags & DBF_FORCE_40MHZ) +#endif /* DBG_CTRL_SUPPORT */ + ) + estTP *= 2; + } + + return estTP; +} + +/* + 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 PRTMP_TX_RATE_SWITCH_3S pCurrTxRate, + IN ULONG NewTxOkCount, + IN ULONG TxErrorRatio) +{ + ULONG newTP, oldTP; + + if (100*NewTxOkCount < pAd->CommonCfg.TrainUpLowThrd*pEntry->LastTxOkCount) + return TRUE; + + if (100*NewTxOkCount > pAd->CommonCfg.TrainUpHighThrd*pEntry->LastTxOkCount) + return FALSE; + + newTP = MlmeRAEstimateThroughput(pAd, pEntry, pCurrTxRate, TxErrorRatio); + oldTP = MlmeRAEstimateThroughput(pAd, pEntry, PTX_RATE_SWITCH_ENTRY_3S(pEntry->pTable, pEntry->lastRateIdx), pEntry->LastTxPER); + + return (oldTP > newTP); +} + +/* + 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; + PRTMP_TX_RATE_SWITCH_3S pCurrTxRate = PTX_RATE_SWITCH_ENTRY_3S(pTable, CurrRateIdx); + + pEntry->CurrTxRateStableTime++; + + pEntry->LastSecTxRateChangeAction = RATE_NO_CHANGE; + +#if defined(RT2883) || defined(RT3883) + if (pAd->CommonCfg.PhyRateLimit != 0) + { + phyRateLimit20 = pEntry->HTPhyMode.field.BW==BW_20? pAd->CommonCfg.PhyRateLimit: pAd->CommonCfg.PhyRateLimit*13/27; + + /* Train down without 100 msec check if current rate is above the limit */ + if (pCurrTxRate->dataRate >= phyRateLimit20) + { + pEntry->CurrTxRateIndex = DownRateIdx; + MlmeNewTxRate(pAd, pEntry); + return; + } + } +#endif /* defined(RT2883) || defined(RT3883) */ + + if (TxErrorRatio >= TrainDown) + { +#ifdef TXBF_SUPPORT + PRTMP_TX_RATE_SWITCH_3S pDownRate, pLastNonBfRate; +#endif /* TXBF_SUPPORT */ + + /* Downgrade TX quality if PER >= Rate-Down threshold */ + MlmeSetTxQuality(pEntry, CurrRateIdx, DRS_TX_QUALITY_WORST_BOUND); + +#ifdef TXBF_SUPPORT + /* + 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_RATE_SWITCH_ENTRY_3S(pTable, DownRateIdx); + pLastNonBfRate = PTX_RATE_SWITCH_ENTRY_3S(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_SUPPORT */ + if (CurrRateIdx != DownRateIdx) + { + pEntry->CurrTxRateIndex = DownRateIdx; + pEntry->LastSecTxRateChangeAction = RATE_DOWN; + } + } + else + { + PRTMP_TX_RATE_SWITCH_3S pUpRate = PTX_RATE_SWITCH_ENTRY_3S(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) + { + pEntry->CurrTxRateIndex = UpRateIdx; + pEntry->LastSecTxRateChangeAction = RATE_UP; + } +#ifdef TXBF_SUPPORT + 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, (PRTMP_TX_RATE_SWITCH)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, (PRTMP_TX_RATE_SWITCH)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) +#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 + 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_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, DEF_QUICK_RA_TIME_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, DEF_QUICK_RA_TIME_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 ULONG idx) +{ + PUCHAR pTable; + UCHAR CurrRateIdx; + ULONG AccuTxTotalCnt, TxTotalCnt, TxCnt; + ULONG TxErrorRatio = 0; + MAC_TABLE_ENTRY *pEntry; + PRTMP_TX_RATE_SWITCH_3S 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]; + + + pTable = pEntry->pTable; + + /* Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2); */ + 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; + + 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 ((pEntry->Aid >= 1) && (pEntry->Aid <= 8)) + { + ULONG HwTxCnt, HwErrRatio; + + NicGetMacFifoTxCnt(pAd, pEntry); + HwTxCnt = pEntry->fifoTxSucCnt + pEntry->fifoTxRtyCnt; + if (HwTxCnt) + HwErrRatio = (pEntry->fifoTxRtyCnt * 100) / HwTxCnt; + else + HwErrRatio = 0; + + DBGPRINT(RT_DEBUG_TRACE | DBG_FUNC_RA,("%s():Aid:%d, MCS:%d, TxErrRation(Hw:0x%lx-0x%lx, Sw:0x%lx-%lx)\n", + __FUNCTION__, pEntry->Aid, pEntry->HTPhyMode.field.MCS, + HwTxCnt, HwErrRatio, TxTotalCnt, TxErrorRatio)); + + TxSuccess = pEntry->fifoTxSucCnt; + TxRetransmit = pEntry->fifoTxRtyCnt; + TxErrorRatio = HwErrRatio; + TxTotalCnt = HwTxCnt; + TxCnt = HwTxCnt; + } +#endif /* FIFO_EXT_SUPPORT */ + } + +#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_RATE_SWITCH_ENTRY_3S(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) + { + /* 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 500 msec or 500-DEF_QUICK_RA_TIME_INTERVAL interval. */ + 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/DEF_QUICK_RA_TIME_INTERVAL; + else + ratio = (RA_INTERVAL-DEF_QUICK_RA_TIME_INTERVAL)/DEF_QUICK_RA_TIME_INTERVAL; + + if (pAd->MacTab.Size == 1) + OneSecTxNoRetryOKRationCount = (TxSuccess * ratio); + else + OneSecTxNoRetryOKRationCount = pEntry->OneSecTxNoRetryOkCount * ratio + (pEntry->OneSecTxNoRetryOkCount >> 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 + { + PRTMP_TX_RATE_SWITCH_3S pLastTxRate = PTX_RATE_SWITCH_ENTRY_3S(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) + { + 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_RATE_SWITCH_ENTRY_3S(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( + IN PRTMP_ADAPTER pAd, IN ULONG i) +{ + PUCHAR pTable; + UCHAR UpRateIdx, DownRateIdx, CurrRateIdx; + ULONG TxTotalCnt; + ULONG TxErrorRatio = 0; + MAC_TABLE_ENTRY *pEntry; + PRTMP_TX_RATE_SWITCH_3S pCurrTxRate; + UCHAR TrainUp, TrainDown; + CHAR Rssi; + ULONG TxSuccess, TxRetransmit, TxFailCount; +#ifdef DOT11N_PF_DEBUG + UCHAR pEntryMaxMCS = 0, selfMaxMCS = 0; +#endif /* DOT11N_PF_DEBUG */ + + pEntry = &pAd->MacTab.Content[i]; /* point to information of the individual station */ + 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; + 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 (pEntry->Aid >= 1 && pEntry->Aid <= 8) + { + ULONG HwTxCnt, HwErrRatio; + + NicGetMacFifoTxCnt(pAd, pEntry); + HwTxCnt = pEntry->fifoTxSucCnt + pEntry->fifoTxRtyCnt; + if (HwTxCnt) + HwErrRatio = (pEntry->fifoTxRtyCnt * 100) / HwTxCnt; + else + HwErrRatio = 0; + DBGPRINT(RT_DEBUG_TRACE | DBG_FUNC_RA,("%s():Aid:%d, MCS:%d, TxErrRatio(Hw:0x%lx-0x%lx, Sw:0x%lx-%lx)\n", + __FUNCTION__, pEntry->Aid, pEntry->HTPhyMode.field.MCS, + HwTxCnt, HwErrRatio, TxTotalCnt, TxErrorRatio)); + + TxSuccess = pEntry->fifoTxSucCnt; + TxRetransmit = pEntry->fifoTxRtyCnt; + TxTotalCnt = HwTxCnt; + TxErrorRatio = HwErrRatio; + } +#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 = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2); */ + Rssi = RTMPAvgRssi(pAd, &pEntry->RssiSample); + + /* decide the next upgrade rate and downgrade rate, if any */ + CurrRateIdx = pEntry->CurrTxRateIndex; + pCurrTxRate = PTX_RATE_SWITCH_ENTRY_3S(pTable, CurrRateIdx); + UpRateIdx = MlmeSelectUpRate(pAd, pEntry, pCurrTxRate); + DownRateIdx = MlmeSelectDownRate(pAd, pEntry, CurrRateIdx); + +#ifdef DOT11N_PF_DEBUG + if (pEntry->HTCapability.MCSSet[0] == 0xff) + { + if (pEntry->HTCapability.MCSSet[1] == 0xff) + { + if(pEntry->HTCapability.MCSSet[2] == 0xff) + pEntryMaxMCS = 23; + else + pEntryMaxMCS = 15; + } + else + { + pEntryMaxMCS = 7; + } + } + + if(pAd->CommonCfg.TxStream <= 3) + selfMaxMCS = 8 * pAd->CommonCfg.TxStream - 1; +#endif /* DOT11N_PF_DEBUG */ + +#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) + { + PRTMP_TX_RATE_SWITCH 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 = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*10];/* actually = pEntry->LegalMfbRS */ + return; + } +#endif /* MFB_SUPPORT */ + +#if defined (RT2883) || defined (RT3883) + /* Debug Option: Force the MCS. FixedRate is index into current rate table. */ + if ((pAd->CommonCfg.FixedRate != -1) && (pAd->CommonCfg.FixedRate < RATE_TABLE_SIZE(pTable)) ) + { + pEntry->CurrTxRateIndex = pAd->CommonCfg.FixedRate; + MlmeNewTxRate(pAd, pEntry); + +#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); + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + eTxBFProbing(pAd, pEntry); +#endif /* TXBF_SUPPORT */ + + return; + } +#endif + + /* 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) || + (pTable == RateSwitchTable)) + { + RssiOffset = 2; + } + else if (ADAPT_RATE_TABLE(pTable)) + { + RssiOffset = 0; + } + else + { + RssiOffset = 5; + } + + /* 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(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 */ + + return; + } + + 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 TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + eTxBFProbing(pAd, pEntry); +#endif /* TXBF_SUPPORT */ + + 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); + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + eTxBFProbing(pAd, pEntry); +#endif /* TXBF_SUPPORT */ +} +#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; + PRTMP_TX_RATE_SWITCH_3S 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 */ + + /* Remember the current rate */ + CurrRateIdx = pEntry->CurrTxRateIndex; +#ifdef TXBF_SUPPORT + CurrPhyETxBf = pEntry->phyETxBf; + CurrPhyITxBf = pEntry->phyITxBf; +#endif /* TXBF_SUPPORT */ + pCurrTxRate = PTX_RATE_SWITCH_ENTRY_3S(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 500 msec or 500-DEF_QUICK_RA_TIME_INTERVAL interval. */ + 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/DEF_QUICK_RA_TIME_INTERVAL; + else + ratio = (RA_INTERVAL-DEF_QUICK_RA_TIME_INTERVAL)/DEF_QUICK_RA_TIME_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 + { + PRTMP_TX_RATE_SWITCH_3S pLastTxRate = PTX_RATE_SWITCH_ENTRY_3S(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_RATE_SWITCH_ENTRY_3S(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; + PRTMP_TX_RATE_SWITCH_3S pCurrTxRate; + UCHAR TrainUp, TrainDown; + CHAR Rssi; + + pEntry = &pAd->MacTab.Content[i]; + pTable = pEntry->pTable; + + if ((pAd->MacTab.Size == 1) || (IS_ENTRY_DLS(pEntry))) + { + /* Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2); */ + Rssi = RTMPAvgRssi(pAd, &pAd->StaCfg.RssiSample); + + /* Update statistic counter */ + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; + + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + } + else + { + /* Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2); */ + 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->Aid >= 1 && pEntry->Aid <= 8) + { + WCID_TX_CNT_STRUC wcidTxCnt; + UINT32 regAddr, offset; + ULONG HwTxCnt, HwErrRatio = 0; + + regAddr = WCID_TX_CNT_0 + (pEntry->Aid - 1) * 4; + RTMP_IO_READ32(pAd, regAddr, &wcidTxCnt.word); + + HwTxCnt = wcidTxCnt.field.succCnt + wcidTxCnt.field.reTryCnt; + if (HwTxCnt) + HwErrRatio = (wcidTxCnt.field.reTryCnt * 100) / HwTxCnt; + + DBGPRINT(RT_DEBUG_TRACE ,("%s():TxErrRatio(Aid:%d, MCS:%d, Hw:0x%x-0x%x, Sw:0x%x-%x)\n", + __FUNCTION__, pEntry->Aid, 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; + + /* decide the next upgrade rate and downgrade rate, if any */ + CurrRateIdx = pEntry->CurrTxRateIndex; + pCurrTxRate = PTX_RATE_SWITCH_ENTRY_3S(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 */ + +#if defined (RT2883) || defined (RT3883) + /* Debug Option: Force the MCS. FixedRate is index into current rate table. */ + if ((pAd->CommonCfg.FixedRate != -1) && (pAd->CommonCfg.FixedRate < RATE_TABLE_SIZE(pTable))) + { + pEntry->CurrTxRateIndex = pAd->CommonCfg.FixedRate; + MlmeNewTxRate(pAd, pEntry); + +#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); + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + eTxBFProbing(pAd, pEntry); +#endif /* TXBF_SUPPORT */ + + return; + } +#endif /* defined(RT2883) || defined(RT3883) */ + + /* + 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 = 0; + } + else + { + RssiOffset = 5; + } + } + else + { + if (pAd->NicConfig2.field.ExternalLNAForA) + { + RssiOffset = 5; + } + else if (ADAPT_RATE_TABLE(pTable)) + { + RssiOffset = 2; + } + else + { + RssiOffset = 8; + } + } + + /* 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 */ + + 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")); */ + + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + eTxBFProbing(pAd, pEntry); +#endif /* TXBF_SUPPORT */ + + 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 3SS and rx count > tx count*5 */ + MlmeCheckRDG(pAd, pEntry); +#endif /* DOT11N_SS3_SUPPORT */ + + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + eTxBFProbing(pAd, pEntry); +#endif /* TXBF_SUPPORT */ +} +#endif /* CONFIG_STA_SUPPORT */ + + +/* + Set_RateTable_Proc - Display or replace byte for item in RateSwitchTableAdapt11N3S + usage: iwpriv ra0 set RateTable=[::] +*/ +INT Set_RateTable_Proc( + IN PRTMP_ADAPTER pAd, + IN 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_RATE_SWITCH_ENTRY_3S(pTable, itemNo); + else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + pRateEntry = (UCHAR *)PTX_RATE_SWITCH_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/mt7620/src/rate_ctrl/alg_legacy.c b/mt7620/src/rate_ctrl/alg_legacy.c new file mode 100644 index 0000000..997c50e --- /dev/null +++ b/mt7620/src/rate_ctrl/alg_legacy.c @@ -0,0 +1,1880 @@ +/**************************************************************************** + * 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( + IN PRTMP_ADAPTER pAd) +{ + ULONG i; + PUCHAR pTable; + UCHAR TableSize = 0; + UCHAR UpRateIdx, DownRateIdx, CurrRateIdx; + ULONG TxTotalCnt; + ULONG TxErrorRatio = 0; + MAC_TABLE_ENTRY *pEntry; + PRTMP_TX_RATE_SWITCH pCurrTxRate, pTmpTxRate = NULL; + UCHAR InitTxRateIdx, TrainUp, TrainDown; + CHAR Rssi, TmpIdx = 0; + ULONG TxSuccess, TxRetransmit, TxFailCount; + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + return; + } +#endif /* RALINK_ATE */ + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + + /* walk through MAC table, see if need to change AP's TX rate toward each entry */ + for (i = 1; i < MaxWcidNum; 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->MatchWDSTabIdx)) + continue; +#endif /* WDS_SUPPORT */ + +#ifdef MESH_SUPPORT + if (IS_ENTRY_MESH(pEntry) && !MESH_ON(pAd)) + continue; +#endif /* MESH_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 */ + + /* 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; + + 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 (pEntry->Aid >= 1 && pEntry->Aid <= 8) + { + ULONG HwTxCnt, HwErrRatio; + + NicGetMacFifoTxCnt(pAd, pEntry); + HwTxCnt = pEntry->fifoTxSucCnt + pEntry->fifoTxRtyCnt; + if (HwTxCnt) + HwErrRatio = (pEntry->fifoTxRtyCnt * 100) / HwTxCnt; + else + HwErrRatio = 0; + + DBGPRINT(RT_DEBUG_TRACE | 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 */ + } + + /* 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 = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2); */ + 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_RATE_SWITCH_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_RATE_SWITCH_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_RATE_SWITCH_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_RATE_SWITCH_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_RATE_SWITCH_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)) + { + 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 */ + +#if defined (RT2883) || defined (RT3883) + /* Debug Option: Force the MCS. FixedRate is index into current rate table. */ + if ((pAd->CommonCfg.FixedRate != -1) && (pAd->CommonCfg.FixedRate < RATE_TABLE_SIZE(pTable))) + { + pEntry->CurrTxRateIndex = pAd->CommonCfg.FixedRate; + MlmeNewTxRate(pAd, pEntry); + + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + eTxBFProbing(pAd, pEntry); +#endif /* TXBF_SUPPORT */ + + continue; + } +#endif + + /* Check for low traffic case */ + if (TxTotalCnt <= 15) + { + UCHAR TxRateIdx; + CHAR mcs[24]; + + /* Check existence and get the index of each MCS */ + MlmeGetSupportedMcs(pAd, pTable, mcs); + + /* Select the Tx rate based on the RSSI */ + TxRateIdx = MlmeSelectTxRate(pAd, pEntry, mcs, Rssi, 0); + + + if (TxRateIdx != pEntry->CurrTxRateIndex +#ifdef TXBF_SUPPORT + || pEntry->phyETxBf || pEntry->phyITxBf +#endif /* TXBF_SUPPORT */ + ) + { + 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 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; + } + + if (pEntry->fLastSecAccordingRSSI == TRUE) + { + pEntry->fLastSecAccordingRSSI = FALSE; + pEntry->LastSecTxRateChangeAction = RATE_NO_CHANGE; + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + eTxBFProbing(pAd, pEntry); +#endif /* TXBF_SUPPORT */ + + 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); + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + eTxBFProbing(pAd, pEntry); +#endif /* TXBF_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 APQuickResponeForRateUpExec( + 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 AccuTxTotalCnt, TxTotalCnt, TxCnt; + ULONG TxErrorRatio = 0; + MAC_TABLE_ENTRY *pEntry; + PRTMP_TX_RATE_SWITCH pCurrTxRate; + UCHAR InitTxRateIdx, TrainUp, TrainDown; + CHAR Rssi, ratio; + ULONG TxSuccess, TxRetransmit, TxFailCount; +#ifdef TXBF_SUPPORT + BOOLEAN CurrPhyETxBf, CurrPhyITxBf; +#endif /* TXBF_SUPPORT */ + UINT32 MaxWcidNum = MAX_LEN_OF_MAC_TABLE; + + pAd->ApCfg.ApQuickResponeForRateUpTimerRunning = FALSE; + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + MaxWcidNum = MAX_MAC_TABLE_SIZE_WITH_REPEATER; +#endif /* MAC_REPEATER_SUPPORT */ + + /* walk through MAC table, see if need to change AP's TX rate toward each entry */ + for (i = 1; i < MaxWcidNum; 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->MatchWDSTabIdx)) + continue; +#endif /* WDS_SUPPORT */ + +#ifdef MESH_SUPPORT + if (IS_ENTRY_MESH(pEntry) && !MESH_ON(pAd)) + continue; +#endif /* MESH_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 = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2); */ + 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; + + 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 ((pEntry->Aid >= 1) && (pEntry->Aid <= 8)) + { + ULONG HwTxCnt, HwErrRatio; + + NicGetMacFifoTxCnt(pAd, pEntry); + 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, TxErrRation(Hw:0x%lx-0x%lx, Sw:0x%lx-%lx)\n", + __FUNCTION__, pEntry->Aid, pEntry->HTPhyMode.field.MCS, + HwTxCnt, HwErrRatio, TxTotalCnt, TxErrorRatio)); + + TxSuccess = pEntry->fifoTxSucCnt; + TxRetransmit = pEntry->fifoTxRtyCnt; + TxErrorRatio = HwErrRatio; + TxTotalCnt = HwTxCnt; + TxCnt = HwTxCnt; + } + } +#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_RATE_SWITCH_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.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 500 msec or 500-DEF_QUICK_RA_TIME_INTERVAL interval. */ + 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/DEF_QUICK_RA_TIME_INTERVAL; + else + ratio = (RA_INTERVAL-DEF_QUICK_RA_TIME_INTERVAL)/DEF_QUICK_RA_TIME_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 = 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) + { + 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; + PRTMP_TX_RATE_SWITCH 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 = RTMPMaxRssi(pAd, pRssi->AvgRssi0, pRssi->AvgRssi1, pRssi->AvgRssi2); */ + Rssi = RTMPAvgRssi(pAd, pRssi); + + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + + + DBGPRINT_RAW(RT_DEBUG_INFO,("DRS:Aid=%d, TxSuccess=%ld, TxRetransmit=%ld, TxFailCount=%ld \n", + pEntry->Aid, 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_RAW(RT_DEBUG_INFO,("DRS:Aid=%d, OneSecTxNoRetry=%d, OneSecTxRetry=%d, OneSecTxFail=%d\n", + pEntry->Aid, + pEntry->OneSecTxNoRetryOkCount, + pEntry->OneSecTxRetryOkCount, + pEntry->OneSecTxFailCount)); + +#ifdef FIFO_EXT_SUPPORT + if (pAd->chipCap.FlgHwFifoExtCap) + { + if (pEntry->Aid >= 1 && pEntry->Aid <= 8) + { + ULONG HwTxCnt, HwErrRatio; + + NicGetMacFifoTxCnt(pAd, pEntry); + 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)) + { +/* + *ppTable = AGS3x3HTRateTable; + *pTableSize = AGS3x3HTRateTable[0]; + *pInitTxRateIdx = AGS3x3HTRateTable[1]; +*/ + + /* The dynamic Tx rate switching for AGS (Adaptive Group Switching)*/ + + MlmeDynamicTxRateSwitchingAGS(pAd, pEntry, pTable, TableSize, &AGSStatisticsInfo, InitTxRateIdx); + + continue; /* Skip the remaining procedure of the old Tx rate switching*/ + } +#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_RATE_SWITCH_ENTRY(pTable, CurrRateIdx); + if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS) + /*&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE) */ + ) + { + /* + Need to sync Real Tx rate and our record. + Then return for next DRS. + */ + pEntry->CurrTxRateIndex = InitTxRateIdx; +#ifdef TXBF_SUPPORT + pEntry->phyETxBf = pEntry->phyITxBf = FALSE; +#endif /* TXBF_SUPPORT */ + 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 ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) + { + TmpIdx = CurrRateIdx + 1; + while(TmpIdx < TableSize) + { + pTmpTxRate = PTX_RATE_SWITCH_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_RATE_SWITCH_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_RATE_SWITCH_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_RATE_SWITCH_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--; + } + } + + pCurrTxRate = PTX_RATE_SWITCH_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 */ + +#if defined (RT2883) || defined (RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + { + /* Debug Option: Force the MCS. FixedRate is index into current rate table. */ + if ((pAd->CommonCfg.FixedRate != -1) && (pAd->CommonCfg.FixedRate < RATE_TABLE_SIZE(pTable))) + { + pEntry->CurrTxRateIndex = pAd->CommonCfg.FixedRate; + MlmeNewTxRate(pAd, pEntry); + + /* reset all OneSecTx counters */ + RESET_ONE_SEC_TX_CNT(pEntry); +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + eTxBFProbing(pAd, pEntry); +#endif /* TXBF_SUPPORT */ + + continue; + } + } +#endif /* defined (RT2883) || defined (RT3883) */ + + + /* + 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); + + + + /* if (TxRateIdx != pAd->CommonCfg.TxRateIndex) */ + { + 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 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); + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + eTxBFProbing(pAd, pEntry); +#endif /* TXBF_SUPPORT */ + + 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); + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + eTxBFProbing(pAd, pEntry); +#endif /* TXBF_SUPPORT */ + } +} + + +/* + ======================================================================== + 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; + PRTMP_TX_RATE_SWITCH 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_RATE_SWITCH_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->Aid >= 1 && pEntry->Aid <= 8) + { + WCID_TX_CNT_STRUC wcidTxCnt; + UINT32 regAddr, offset; + ULONG HwTxCnt, HwErrRatio = 0; + + regAddr = WCID_TX_CNT_0 + (pEntry->Aid - 1) * 4; + RTMP_IO_READ32(pAd, regAddr, &wcidTxCnt.word); + + HwTxCnt = wcidTxCnt.field.succCnt + wcidTxCnt.field.reTryCnt; + if (HwTxCnt) + HwErrRatio = (wcidTxCnt.field.reTryCnt * 100) / HwTxCnt; + + DBGPRINT(RT_DEBUG_INFO ,("%s():TxErrRatio(Aid:%d, MCS:%d, Hw:0x%x-0x%x, Sw:0x%x-%x)\n", + __FUNCTION__, pEntry->Aid, 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 500 msec or 500-DEF_QUICK_RA_TIME_INTERVAL interval. */ + 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/DEF_QUICK_RA_TIME_INTERVAL; + else + ratio = (RA_INTERVAL-DEF_QUICK_RA_TIME_INTERVAL)/DEF_QUICK_RA_TIME_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) + { + 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) + { + PRTMP_TX_RATE_SWITCH pUpRate = PTX_RATE_SWITCH_ENTRY(pTable, UpRateIdx); + PRTMP_TX_RATE_SWITCH pCurrTxRate = PTX_RATE_SWITCH_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, DEF_QUICK_RA_TIME_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, DEF_QUICK_RA_TIME_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/mt7620/src/rate_ctrl/ra_ctrl.c b/mt7620/src/rate_ctrl/ra_ctrl.c new file mode 100644 index 0000000..487ea92 --- /dev/null +++ b/mt7620/src/rate_ctrl/ra_ctrl.c @@ -0,0 +1,2165 @@ +/**************************************************************************** + * 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 RateSwitchTable[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)*/ + 0x11, 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, 0x21, 0, 30, 50, + 0x05, 0x21, 1, 20, 50, + 0x06, 0x21, 2, 20, 50, + 0x07, 0x21, 3, 15, 50, + 0x08, 0x21, 4, 15, 30, + 0x09, 0x21, 5, 10, 25, + 0x0a, 0x21, 6, 8, 25, + 0x0b, 0x21, 7, 8, 25, + 0x0c, 0x20, 12, 15, 30, + 0x0d, 0x20, 13, 8, 20, + 0x0e, 0x20, 14, 8, 20, + 0x0f, 0x20, 15, 8, 25, + 0x10, 0x22, 15, 8, 25, + 0x11, 0x00, 0, 0, 0, + 0x12, 0x00, 0, 0, 0, + 0x13, 0x00, 0, 0, 0, + 0x14, 0x00, 0, 0, 0, + 0x15, 0x00, 0, 0, 0, + 0x16, 0x00, 0, 0, 0, + 0x17, 0x00, 0, 0, 0, + 0x18, 0x00, 0, 0, 0, + 0x19, 0x00, 0, 0, 0, + 0x1a, 0x00, 0, 0, 0, + 0x1b, 0x00, 0, 0, 0, + 0x1c, 0x00, 0, 0, 0, + 0x1d, 0x00, 0, 0, 0, + 0x1e, 0x00, 0, 0, 0, + 0x1f, 0x00, 0, 0, 0, +}; + + +UCHAR RateSwitchTable11B[] = { +/* Item No. Mode Curr-MCS TrainUp TrainDown Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: 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,5: 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,5: 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,5: 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,5: 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,5: 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,5: 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,5: 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,5: 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,5: 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,5: 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,5: 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,5: 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,5: 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,5: 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, 0x21, 32, 30, 50, 10, 0, 8, 0, 7, /* mcs32 or 20M/mcs0 */ +}; + +#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, 0x21, 32, 30, 50, 20, 0, 8, 0, 7, /* mcs32 or 20M/mcs0 */ +}; + +#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 + 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 + 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 + 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 */ +}; +#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; + PRTMP_TX_RATE_SWITCH 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( + IN MAC_TABLE_ENTRY *pEntry) +{ +#ifdef TXBF_SUPPORT + if (pEntry->phyETxBf || pEntry->phyITxBf) + NdisZeroMemory(pEntry->BfTxQuality, sizeof(pEntry->BfTxQuality)); + else +#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( + IN MAC_TABLE_ENTRY *pEntry) +{ +#ifdef TXBF_SUPPORT + NdisZeroMemory(pEntry->BfTxQuality, sizeof(pEntry->BfTxQuality)); +#endif + NdisZeroMemory(pEntry->TxQuality, sizeof(pEntry->TxQuality)); + + NdisZeroMemory(pEntry->PER, sizeof(pEntry->PER)); +} + +/* MlmeDecTxQuality - Decrement TxQuality of specified rate table entry */ +VOID MlmeDecTxQuality( + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR rateIndex) +{ +#ifdef TXBF_SUPPORT + if (pEntry->phyETxBf || pEntry->phyITxBf) { + if (pEntry->BfTxQuality[rateIndex]) + pEntry->BfTxQuality[rateIndex]--; + } + else +#endif /* TXBF_SUPPORT */ + if (pEntry->TxQuality[rateIndex]) + pEntry->TxQuality[rateIndex]--; +} + +VOID MlmeSetTxQuality( + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR rateIndex, + IN USHORT txQuality) +{ +#ifdef TXBF_SUPPORT + if (pEntry->phyETxBf || pEntry->phyITxBf) + pEntry->BfTxQuality[rateIndex] = txQuality; + else +#endif /* TXBF_SUPPORT */ + pEntry->TxQuality[rateIndex] = txQuality; +} + + +USHORT MlmeGetTxQuality( + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR rateIndex) +{ +#ifdef TXBF_SUPPORT + if (pEntry->phyETxBf || pEntry->phyITxBf) + return pEntry->BfTxQuality[rateIndex]; +#endif /* TXBF_SUPPORT */ + return pEntry->TxQuality[rateIndex]; +} + + +#ifdef CONFIG_AP_SUPPORT +VOID APMlmeSetTxRate( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PRTMP_TX_RATE_SWITCH pTxRate) +{ +#ifdef DOT11_N_SUPPORT + if ((pTxRate->STBC) && (pEntry->MaxHTPhyMode.field.STBC)) + pEntry->HTPhyMode.field.STBC = STBC_USE; + else + pEntry->HTPhyMode.field.STBC = STBC_NONE; + + if (((pTxRate->ShortGI) && (pEntry->MaxHTPhyMode.field.ShortGI)) + || (pAd->WIFItestbed.bShortGI && pEntry->MaxHTPhyMode.field.ShortGI) ) + pEntry->HTPhyMode.field.ShortGI = GI_400; + else + pEntry->HTPhyMode.field.ShortGI = GI_800; +#endif /* DOT11_N_SUPPORT */ + + if (pTxRate->CurrMCS < MCS_AUTO) + pEntry->HTPhyMode.field.MCS = pTxRate->CurrMCS; + + pEntry->HTPhyMode.field.MODE = pTxRate->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 RANGE_EXTEND +#ifdef NEW_RATE_ADAPT_SUPPORT + /* 20 MHz Fallback */ + if (pTxRate->Mode >= MODE_HTMIX && + 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 + MlmeSetHwTxRateTable(pAd, pEntry); +#endif /* MCS_LUT_SUPPORT */ + + +} +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_STA_SUPPORT +VOID MlmeSetTxRate( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PRTMP_TX_RATE_SWITCH pTxRate) +{ + UCHAR MaxMode = MODE_OFDM; + +#ifdef DOT11_N_SUPPORT + MaxMode = MODE_HTGREENFIELD; + + if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC)) + pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE; + else +#endif /* DOT11_N_SUPPORT */ + pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE; + + if (pTxRate->CurrMCS < MCS_AUTO) + pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS; + + if (pAd->StaCfg.HTPhyMode.field.MCS > 7) + pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE; + + if (ADHOC_ON(pAd)) + { + /* If peer adhoc is b-only mode, we can't send 11g rate. */ + pAd->StaCfg.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 = pTxRate->Mode; + pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + + /* Patch speed error in status page */ + pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE; + } + else + { +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.RegTransmitSetting.field.HTMODE == HTMODE_GF) && + (pAd->MlmeAux.HtCapability.HtCapInfo.GF == HTMODE_GF)) + pAd->StaCfg.HTPhyMode.field.MODE = MODE_HTGREENFIELD; + else +#endif /* DOT11_N_SUPPORT */ + if (pTxRate->Mode <= MaxMode) + pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode; + +#ifdef DOT11_N_SUPPORT + if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI)) + pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400; + else +#endif /* DOT11_N_SUPPORT */ + pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; + +#ifdef DOT11_N_SUPPORT + /* BW depends on Negotiated BW */ + 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 RANGE_EXTEND +#ifdef NEW_RATE_ADAPT_SUPPORT + /* 20 MHz Fallback */ + if (pTxRate->Mode>=MODE_HTMIX && + pEntry->HTPhyMode.field.BW==BW_40 && + ADAPT_RATE_TABLE(pEntry->pTable)) + { + if ((pAd->StaCfg.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; + pAd->StaCfg.HTPhyMode.field.MCS = 0; + if (pTxRate->STBC && pAd->StaCfg.MaxHTPhyMode.field.STBC) + pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE; + } + else if (pAd->StaCfg.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; + pAd->StaCfg.HTPhyMode.field.MCS = 1; + } + else if (pAd->StaCfg.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)) ) + pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; + +#ifdef DBG_CTRL_SUPPORT + /* Debug option: Force Short GI */ + if (pAd->CommonCfg.DebugFlags & DBF_FORCE_SGI) + pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400; +#endif /* DBG_CTRL_SUPPORT */ + + /* Turn RTS/CTS rate to 6Mbps. */ + if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0)) + { + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + if (pAd->MacTab.fAnyBASession) + { + AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); + } + else + { + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); + } + } + else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8)) + { + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + if (pAd->MacTab.fAnyBASession) + { + AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); + } + else + { + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); + } + } + else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0)) + { + AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); + } + else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8)) + { + AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); + } +#endif /* DOT11_N_SUPPORT */ + + pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC; + pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; + } + +} +#endif /* CONFIG_STA_SUPPORT */ + + +VOID MlmeSelectTxRateTable( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR *ppTable, + IN PUCHAR pTableSize, + IN PUCHAR pInitTxRateIdx) +{ + do + { + /* decide the rate table for tuning*/ + if (pAd->CommonCfg.TxRateTableSize > 0) + { + *ppTable = RateSwitchTable; + break; + } + +#ifdef CONFIG_STA_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd)) + { + /* for ADHOC mode */ +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && + (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 ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && + (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 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 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) || pAd->CommonCfg.PhyMode==PHY_11B) +#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 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) || (pTable == RateSwitchTable) +#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( + IN PRTMP_ADAPTER pAd, + IN PMAC_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 */ + +#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; + + 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*DEF_QUICK_RA_TIME_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-DEF_QUICK_RA_TIME_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->Aid, 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->Aid, 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; + PRTMP_TX_RATE_SWITCH pTempTxRate; + +#ifdef NEW_RATE_ADAPT_SUPPORT + TableStep = ADAPT_RATE_TABLE(pTable)? 10: 5; +#else + TableStep = 5; +#endif + + pTempTxRate = (PRTMP_TX_RATE_SWITCH)(&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 */ + + +/* + MlmeNewTxRate - called when a new TX rate was selected. Sets TX PHY to + rate selected by pEntry->CurrTxRateIndex in pTable; +*/ +VOID MlmeNewTxRate( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry) +{ + PRTMP_TX_RATE_SWITCH pNextTxRate; + UCHAR *pTable = pEntry->pTable; + + /* Get pointer to CurrTxRate entry */ +#ifdef NEW_RATE_ADAPT_SUPPORT + if (ADAPT_RATE_TABLE(pTable)) + pNextTxRate = (PRTMP_TX_RATE_SWITCH)PTX_RATE_SWITCH_ENTRY_3S(pTable, pEntry->CurrTxRateIndex); + else +#endif /* NEW_RATE_ADAPT_SUPPORT */ + pNextTxRate = PTX_RATE_SWITCH_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.MCS = 0; + else + pEntry->HTPhyMode.field.STBC = 0; + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + { + /* If BF has been disabled then force a non-BF rate */ + if (pEntry->eTxBfEnCond==0) + pEntry->phyETxBf = 0; + + if (pEntry->iTxBfEn==0) + pEntry->phyITxBf = 0; + +#if defined(RT2883) || defined(RT3883) + /* Debug option: In Fixed Rate and BF Unaware mode BF follows the setting of the global option */ + if ((pAd->CommonCfg.FixedRate != -1) +#ifdef DBG_CTRL_SUPPORT + || (pAd->CommonCfg.DebugFlags & DBF_NO_BF_AWARE_RA) +#endif /* DBG_CTRL_SUPPORT */ + ) + { + if (MlmeTxBfAllowed(pAd, pEntry, pNextTxRate)) + { + pEntry->phyETxBf = pEntry->eTxBfEnCond > 0; + pEntry->phyITxBf = pEntry->iTxBfEn; + } + else + pEntry->phyETxBf = pEntry->phyITxBf = 0; + } +#endif /* defined(RT2883) || defined(RT3883) */ + + /* 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 */ + + 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, + 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_ERROR,("RTMPSetSupportMCS - wrong SUPP RATES., Len=%d\n", 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); + + 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) + { + PRT_HT_PHY_INFO pDesired_ht_phy = NULL; + UCHAR j, bitmask; + CHAR i; + +#ifdef CONFIG_STA_SUPPORT + if (OpMode == OPMODE_STA) + pDesired_ht_phy = &pAd->StaCfg.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].DesiredHtPhyInfo; + else +#endif /* WDS_SUPPORT */ +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + pDesired_ht_phy = &pAd->ApCfg.ApCliTab[pEntry->apidx].DesiredHtPhyInfo; + else +#endif /* APCLI_SUPPORT */ +#ifdef MESH_SUPPORT + if (IS_ENTRY_MESH(pEntry)) + pDesired_ht_phy = &pAd->MeshTab.DesiredHtPhyInfo; + else +#endif /* MESH_SUPPORT */ + pDesired_ht_phy = &pAd->ApCfg.MBSSID[pEntry->apidx].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 MCS_LUT_SUPPORT +VOID MlmeSetHwTxRateTable( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry) +{ + WCID_TX_RATE_LU_STRUC WcidTxRateCnt; + UINT32 regAddr; + +#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 (pEntry) + { +/* + if (IS_HW_TXRATE_LOOKUP_SUPPORT(pAd) && (pAd->bUseHwTxLURate)) +*/ + if (IS_HW_TXRATE_LOOKUP_SUPPORT(pAd)) + { + regAddr = MAC_WCID_BASE + (8 * 128) + (pEntry->Aid * 8); + WcidTxRateCnt.field.MCS = pEntry->HTPhyMode.field.MCS; + WcidTxRateCnt.field.STBC = pEntry->HTPhyMode.field.STBC; + WcidTxRateCnt.field.ShortGI = pEntry->HTPhyMode.field.ShortGI; + WcidTxRateCnt.field.MODE = pEntry->HTPhyMode.field.MODE; + WcidTxRateCnt.field.BW = pEntry->HTPhyMode.field.BW; + RTMP_IO_WRITE32(pAd, regAddr, WcidTxRateCnt.word); + } + } +} +#endif /* MCS_LUT_SUPPORT */ + +INT Set_RateAlg_Proc( + IN PRTMP_ADAPTER pAd, + IN 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/mt7620/src/sta/assoc.c b/mt7620/src/sta/assoc.c new file mode 100644 index 0000000..3c5eabe --- /dev/null +++ b/mt7620/src/sta/assoc.c @@ -0,0 +1,2161 @@ +/* + *************************************************************************** + * 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" + +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 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); +} + +/* + ========================================================================== + 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) +{ + 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)) { + /*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 */ + + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send ASSOC request...\n")); + MgtMacHeaderInit(pAd, &AssocHdr, SUBTYPE_ASSOC_REQ, 0, ApAddr, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + 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 DOT11_N_SUPPORT + /* HT */ + if ((pAd->MlmeAux.HtCapabilityLen > 0) + && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) { + 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; + } +#endif /* DOT11_N_SUPPORT */ + +#if defined(DOT11N_DRAFT3) || defined(DOT11V_WNM_SUPPORT) || defined(DOT11Z_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) && + (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + && (pAd->CommonCfg.Channel <= 14) + ) + { + extCapInfo.BssCoexistMgmtSupport = 1; + } +#endif /* DOT11N_DRAFT3 */ + +#ifdef DOT11Z_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 /* DOT11Z_TDLS_SUPPORT */ + + 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 (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) +#ifdef WAPI_SUPPORT + || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWAICERT) + || (pAd->StaCfg.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 ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) + || (pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPA2)) { + RSNIe = IE_WPA2; + } +#ifdef WAPI_SUPPORT + else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWAICERT) + || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWAIPSK)) { + RSNIe = IE_WAPI; + } +#endif /* WAPI_SUPPORT */ + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.bRSN_IE_FromWpaSupplicant == FALSE) +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, + pAd->StaCfg.WepStatus, BSS0); + + /* Check for WPA PMK cache list */ + if (pAd->StaCfg.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 ((pAd->StaCfg.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.WpaSupplicantUP & WPA_SUPPLICANT_ENABLE) + && (pAd->StaCfg.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.WpaSupplicantUP & 0x7F) != + WPA_SUPPLICANT_ENABLE) + || (pAd->StaCfg.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.WpaSupplicantUP & WPA_SUPPLICANT_ENABLE) && + (pAd->StaCfg.bRSN_IE_FromWpaSupplicant == TRUE)) { + ULONG TmpWpaAssocIeLen = 0; + MakeOutgoingFrame(pOutBuffer + FrameLen, + &TmpWpaAssocIeLen, + pAd->StaCfg.WpaAssocIeLen, + pAd->StaCfg.pWpaAssocIe, END_OF_ARGS); + + FrameLen += TmpWpaAssocIeLen; + + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, + pAd->StaCfg.pWpaAssocIe, + pAd->StaCfg.WpaAssocIeLen); + VarIesOffset += pAd->StaCfg.WpaAssocIeLen; + + /* Set Variable IEs Length */ + pAd->StaCfg.ReqVarIELen = VarIesOffset; + } +/* #endif */ +#endif /* WPA_SUPPLICANT_SUPPORT */ +#ifdef P2P_SUPPORT + else if (P2P_INF_ON(pAd)) + { + /* Check the total P2P Attribue IE in this AP.s */ + if (pAd->P2pCfg.P2pManagedParm.TotalNumOfP2pAttribute > 0) + { + PUCHAR ptr; + ptr = pOutBuffer + FrameLen; + P2pMakeP2pIE(pAd, SUBTYPE_ASSOC_REQ, ptr, &tmp); + FrameLen += tmp; + DBGPRINT(RT_DEBUG_ERROR, ("ASSOCREQ - Insert P2P IE in case for managed AP to recognize me\n")); + } + } +#endif /* P2P_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 = kmalloc(512, GFP_ATOMIC)) != NULL) */ + if (pWscBuf != NULL) { + NdisZeroMemory(pWscBuf, 512); + WscBuildAssocReqIE(&pAd->StaCfg.WscControl, pWscBuf, &WscIeLen); + + MakeOutgoingFrame(pOutBuffer + FrameLen, + &WscTmpLen, WscIeLen, pWscBuf, + END_OF_ARGS); + + FrameLen += WscTmpLen; +/* kfree(pWscBuf); */ + os_free_mem(NULL, pWscBuf); + } else + DBGPRINT(RT_DEBUG_WARN, + ("%s:: WscBuf Allocate failed!\n", + __FUNCTION__)); + } +#endif /* WSC_STA_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) +{ + 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, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + 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; + } + + 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) + && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) { + 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; + } +#endif /* DOT11_N_SUPPORT */ + + if (FALSE +#ifdef DOT11Z_TDLS_SUPPORT + || IS_TDLS_SUPPORT(pAd) +#endif /* DOT11Z_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 DOT11Z_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 /* DOT11Z_TDLS_SUPPORT */ + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &ExtCapIe, + 1 &extInfoLen, + extInfoLen, &extCapInfo, + END_OF_ARGS); + FrameLen += TmpLen; + /*printk("iverson test extCapInfo.BssTransitionManmt %x \n",extCapInfo.BssTransitionManmt); */ + } + + /* 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; + } + + 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", + pDisassocReq->Addr[0], pDisassocReq->Addr[1], + pDisassocReq->Addr[2], pDisassocReq->Addr[3], + pDisassocReq->Addr[4], pDisassocReq->Addr[5], + pDisassocReq->Reason)); + MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pDisassocReq->Addr, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + 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.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; + + if (PeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, + Addr2, &CapabilityInfo, &Status, &Aid, SupRate, + &SupRateLen, ExtRate, &ExtRateLen, &HtCapability, + &AddHtInfo, &HtCapabilityLen, &AddHtInfoLen, + &NewExtChannelOffset, &EdcaParm, &ExtCapInfo, + &CkipFlag)) { + /* The frame is for me ? */ + if (MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid)) { + DBGPRINT(RT_DEBUG_TRACE, + ("PeerAssocRspAction():ASSOC - receive ASSOC_RSP to me (status=%d)\n", + Status)); +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, + ("PeerAssocRspAction():MacTable [%d].AMsduSize = %d. ClientStatusFlags = 0x%lx \n", + Elem->Wcid, + pAd->MacTab.Content[BSSID_WCID].AMsduSize, + pAd->MacTab.Content[BSSID_WCID]. + ClientStatusFlags)); +#endif /* DOT11_N_SUPPORT */ + RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, + &TimerCancelled); + + + + if (Status == MLME_SUCCESS) { + UCHAR MaxSupportedRateIn500Kbps = 0; + UCHAR idx; + 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->Aid, pEntry->Addr); + pEntry = NULL; + } + + /* 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; + } + + for (idx = 0; idx < ExtRateLen; idx++) { + if (MaxSupportedRateIn500Kbps < (ExtRate[idx] & 0x7f)) + MaxSupportedRateIn500Kbps = ExtRate[idx] & 0x7f; + } + /* go to procedure listed on page 376 */ + AssocPostProc(pAd, Addr2, CapabilityInfo, Aid, + SupRate, SupRateLen, ExtRate, + ExtRateLen, &EdcaParm, + &HtCapability, HtCapabilityLen, + &AddHtInfo); + + StaAddMacTableEntry(pAd, + &pAd->MacTab.Content[BSSID_WCID], + MaxSupportedRateIn500Kbps, + &HtCapability, + HtCapabilityLen, &AddHtInfo, + AddHtInfoLen, + CapabilityInfo); + + RTMPSetSupportMCS(pAd, + OPMODE_STA, + &pAd->MacTab.Content[BSSID_WCID], + SupRate, + SupRateLen, + ExtRate, + ExtRateLen, + &HtCapability, + HtCapabilityLen); + + } + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, + MT2_ASSOC_CONF, 2, &Status, 0); + +#ifdef LINUX +#ifdef RT_CFG80211_SUPPORT + { + PFRAME_802_11 pFrame = + (PFRAME_802_11) (Elem->Msg); + RTEnqueueInternalCmd(pAd, + CMDTHREAD_CONNECT_RESULT_INFORM, + &pFrame->Octet[6], + Elem->MsgLen - 6 - + sizeof (HEADER_802_11)); + } +#endif /* RT_CFG80211_SUPPORT */ +#endif /* LINUX */ + } + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - PeerAssocRspAction() sanity check fail\n")); + } +} + +/* + ========================================================================== + 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; + + if (PeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, + &CapabilityInfo, &Status, &Aid, SupRate, + &SupRateLen, ExtRate, &ExtRateLen, &HtCapability, + &AddHtInfo, &HtCapabilityLen, &AddHtInfoLen, + &NewExtChannelOffset, &EdcaParm, &ExtCapInfo, + &CkipFlag)) { + if (MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid)) { /* The frame is for me ? */ + DBGPRINT(RT_DEBUG_TRACE, + ("ASSOC - receive REASSOC_RSP to me (status=%d)\n", + Status)); + RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, + &TimerCancelled); + + if (Status == MLME_SUCCESS) + { + UCHAR MaxSupportedRateIn500Kbps = 0; + UCHAR idx; + 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->Aid, pEntry->Addr); + pEntry = NULL; + } + + /* 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; + } + + for (idx = 0; idx < ExtRateLen; idx++) { + if (MaxSupportedRateIn500Kbps < (ExtRate[idx] & 0x7f)) + MaxSupportedRateIn500Kbps = ExtRate[idx] & 0x7f; + } + + /* go to procedure listed on page 376 */ + AssocPostProc(pAd, Addr2, CapabilityInfo, Aid, + SupRate, SupRateLen, ExtRate, + ExtRateLen, &EdcaParm, + &HtCapability, HtCapabilityLen, + &AddHtInfo); + + StaAddMacTableEntry(pAd, + &pAd->MacTab.Content[BSSID_WCID], + MaxSupportedRateIn500Kbps, + &HtCapability, + HtCapabilityLen, &AddHtInfo, + AddHtInfoLen, + CapabilityInfo); + + RTMPSetSupportMCS(pAd, + OPMODE_STA, + &pAd->MacTab.Content[BSSID_WCID], + SupRate, + SupRateLen, + ExtRate, + ExtRateLen, + &HtCapability, + HtCapabilityLen); + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.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 */ + + } + + /* 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, + ("ASSOC - PeerReassocRspAction() sanity check fail\n")); + } + +} + +/* + ========================================================================== + 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 HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN ADD_HT_INFO_IE *pAddHtInfo) +{ /* AP might use this additional ht info IE */ + ULONG Idx; + + 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); + +#ifdef DOT11_N_SUPPORT + if (HtCapabilityLen > 0) { + RTMPCheckHt(pAd, BSSID_WCID, pHtCapability, pAddHtInfo); + } + DBGPRINT(RT_DEBUG_TRACE, + ("AssocPostProc===> AP.AMsduSize = %d. ClientStatusFlags = 0x%lx \n", + pAd->MacTab.Content[BSSID_WCID].AMsduSize, + pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); + + DBGPRINT(RT_DEBUG_TRACE, + ("AssocPostProc===> (Mmps=%d, AmsduSize=%d, )\n", + pAd->MacTab.Content[BSSID_WCID].MmpsMode, + pAd->MacTab.Content[BSSID_WCID].AMsduSize)); +#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 { + /* Init variable */ + pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = 0; + NdisZeroMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, MAX_LEN_OF_RSNIE); + + /* Store appropriate RSN_IE for WPA SM negotiation later */ + if ((pAd->StaCfg.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)) + && (pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPA + || pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPAPSK)) { + NdisMoveMemory(pAd->MacTab. + Content[BSSID_WCID]. + RSN_IE, pVIE, + (pEid->Len + 2)); + pAd->MacTab.Content[BSSID_WCID]. + RSNIE_Len = (pEid->Len + 2); + DBGPRINT(RT_DEBUG_TRACE, + ("AssocPostProc===> Store RSN_IE for WPA SM negotiation \n")); + } + /* For WPA2/WPA2PSK */ + else if ((pEid->Eid == IE_RSN) + && + (NdisEqualMemory + (pEid->Octet + 2, RSN_OUI, 3)) + && (pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPA2 + || pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPA2PSK)) { + NdisMoveMemory(pAd->MacTab. + Content[BSSID_WCID]. + RSN_IE, pVIE, + (pEid->Len + 2)); + pAd->MacTab.Content[BSSID_WCID]. + RSNIE_Len = (pEid->Len + 2); + DBGPRINT(RT_DEBUG_TRACE, + ("AssocPostProc===> Store RSN_IE for WPA2 SM negotiation \n")); + } +#ifdef WAPI_SUPPORT + /* For WAPI */ + else if ((pEid->Eid == IE_WAPI) + && + (NdisEqualMemory + (pEid->Octet + 4, WAPI_OUI, 3)) + && (pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWAICERT + || pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWAIPSK)) { + NdisMoveMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, pVIE, + (pEid->Len + 2)); + pAd->MacTab.Content[BSSID_WCID]. + RSNIE_Len = (pEid->Len + 2); + DBGPRINT(RT_DEBUG_TRACE, + ("AssocPostProc===> Store RSN_IE for WAPI SM negotiation \n")); + } +#endif /* WAPI_SUPPORT */ + + pVIE += (pEid->Len + 2); + len -= (pEid->Len + 2); + } + + + } + + if (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == 0) { + DBGPRINT(RT_DEBUG_TRACE, + ("AssocPostProc===> no RSN_IE \n")); + } else { + hex_dump("RSN_IE", + pAd->MacTab.Content[BSSID_WCID].RSN_IE, + pAd->MacTab.Content[BSSID_WCID].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( + IN PRTMP_ADAPTER pAd, + IN 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.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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN PUCHAR 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, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + 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); +} + + +BOOLEAN StaAddMacTableEntry( + IN PRTMP_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 USHORT CapabilityInfo) +{ + UCHAR MaxSupportedRate = RATE_11; + BOOLEAN bSupportN = FALSE; +#ifdef TXBF_SUPPORT + BOOLEAN supportsETxBf = FALSE; +#endif + + if (!pEntry) + return FALSE; + + if (ADHOC_ON(pAd)) + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + + 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; + } + + if ((pAd->CommonCfg.PhyMode == PHY_11G) + && (MaxSupportedRate < RATE_FIRST_OFDM_RATE)) + return FALSE; + +#ifdef DOT11_N_SUPPORT + /* 11n only */ + if (((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) + || (pAd->CommonCfg.PhyMode == PHY_11N_5G)) + && (HtCapabilityLen == 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) || + (pAd->CommonCfg.PhyMode == PHY_11B)) { + 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; + 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->CapabilityInfo = CapabilityInfo; + CLIENT_STATUS_CLEAR_FLAG(pEntry, + fCLIENT_STATUS_AGGREGATION_CAPABLE); + CLIENT_STATUS_CLEAR_FLAG(pEntry, + fCLIENT_STATUS_PIGGYBACK_CAPABLE); + } +#ifdef DOT11_N_SUPPORT + NdisZeroMemory(&pEntry->HTCapability, sizeof (pEntry->HTCapability)); + /* If this Entry supports 802.11n, upgrade to HT rate. */ + if (((pAd->StaCfg.WepStatus != Ndis802_11WEPEnabled) + && (pAd->StaCfg.WepStatus != Ndis802_11Encryption2Enabled)) + || (pAd->CommonCfg.HT_DisallowTKIP == FALSE)) { + if ((pAd->StaCfg.BssType == BSS_INFRA) && + (HtCapabilityLen != 0) && + (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + bSupportN = TRUE; + if ((pAd->StaCfg.BssType == BSS_ADHOC) && + (pAd->StaCfg.bAdhocN == TRUE) && + (HtCapabilityLen != 0) && + (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + bSupportN = TRUE; + } + if (bSupportN) { + UCHAR j, bitmask; /*k,bitmask; */ + CHAR i; + + if (ADHOC_ON(pAd)) + CLIENT_STATUS_SET_FLAG(pEntry, + fCLIENT_STATUS_WMM_CAPABLE); + if ((pHtCapability->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 ((pHtCapability->HtCapInfo.ChannelWidth) && + (pAd->CommonCfg.DesiredHtPhy.ChannelWidth)) { + pEntry->MaxHTPhyMode.field.BW = BW_40; +#ifdef P2P_SUPPORT + if (pAd->MlmeAux.bBwFallBack == TRUE) + pEntry->MaxHTPhyMode.field.BW = BW_20; +#endif /* P2P_SUPPORT */ + 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; + } + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + supportsETxBf = clientSupportsETxBF(pAd, &pHtCapability->TxBFCap); +#endif /* TXBF_SUPPORT */ + + /* find max fixed rate */ + for (i = 23; i >= 0; i--) { /* 3*3 */ + j = i / 8; + bitmask = (1 << (i - (j * 8))); + if ((pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j] & bitmask) + && (pHtCapability->MCSSet[j] & bitmask)) { + pEntry->MaxHTPhyMode.field.MCS = i; + break; + } + if (i == 0) + break; + } + + if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) { + if (pAd->StaCfg.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.HTPhyMode.field.MCS) { + /* STA supports fixed MCS */ + pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.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 (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); + if (pHtCapability->ExtHtCapInfo.MCSFeedback == 0x03) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); + NdisMoveMemory(&pEntry->HTCapability, pHtCapability, HtCapabilityLen); + + assoc_ht_info_debugshow(pAd, pEntry, HtCapabilityLen, pHtCapability); + } 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 (pAd->StaCfg.bAutoTxRateSwitch == TRUE) { + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, pEntry, &pEntry->pTable, &TableSize, &pEntry->CurrTxRateIndex); + pEntry->bAutoTxRateSwitch = TRUE; + } else { + pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + + /* If the legacy mode is set, overwrite the transmit setting of this entry. */ + RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + + + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + pEntry->Sst = SST_ASSOC; + pEntry->AuthState = AS_AUTH_OPEN; + pEntry->AuthMode = pAd->StaCfg.AuthMode; + pEntry->WepStatus = pAd->StaCfg.WepStatus; + 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->pAd = pAd; + SET_ENTRY_CLIENT(pEntry); + pAd->MacTab.Size ++; + } + + NdisReleaseSpinLock(&pAd->MacTabLock); + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP) { +/* union iwreq_data wrqu; */ + + 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 + { +/* union iwreq_data wrqu; */ + 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 */ + +#ifdef P2P_SUPPORT + if (pAd->StaCfg.BssType == BSS_INFRA) + COPY_MAC_ADDR(pEntry->HdrAddr1, pAd->MlmeAux.Bssid); + COPY_MAC_ADDR(pEntry->HdrAddr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pEntry->HdrAddr3, pAd->MlmeAux.Bssid); +#endif /* P2P_SUPPORT */ + + return TRUE; +} diff --git a/mt7620/src/sta/auth.c b/mt7620/src/sta/auth.c new file mode 100644 index 0000000..cdd13a4 --- /dev/null +++ b/mt7620/src/sta/auth.c @@ -0,0 +1,588 @@ +/* + *************************************************************************** + * 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.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John 2004-9-3 porting from RT2500 +*/ +#include "rt_config.h" + +/* + ========================================================================== + 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 PRTMP_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); +} + +/* + ========================================================================== + Description: + function to be executed at timer thread when auth timer expires + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AuthTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *) FunctionContext; + + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - 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; + + /* 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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + USHORT Seq, Status, RemoteStatus, Alg; + UCHAR iv_hdr[4]; +/* UCHAR ChlgText[CIPHER_TEXT_LEN]; */ + UCHAR *ChlgText = NULL; +/* UCHAR CyperChlgText[CIPHER_TEXT_LEN + 8 + 8]; */ + 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; + + /* 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; + } + + 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 { + /* 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, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + pAd->MlmeAux.Bssid); + AuthHdr.FC.Wep = 1; + + /* TSC increment */ + INC_TX_TSC(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxTsc, LEN_WEP_TSC); + + /* Construct the 4-bytes WEP IV header */ + RTMPConstructWEPIVHdr(pAd->StaCfg.DefaultKeyId, + pAd->SharedKey[BSS0][pAd->StaCfg.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][pAd->StaCfg.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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN 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, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + 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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN PUCHAR 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, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + 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, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + 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 - MlmeAuthReqAction() sanity check failed\n", + pSMName)); + return FALSE; + } + + return TRUE; +} diff --git a/mt7620/src/sta/auth_rsp.c b/mt7620/src/sta/auth_rsp.c new file mode 100644 index 0000000..20c3369 --- /dev/null +++ b/mt7620/src/sta/auth_rsp.c @@ -0,0 +1,216 @@ +/* + *************************************************************************** + * 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, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + 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) + ) { + 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, + pAd->StaCfg.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.WpaSupplicantUP != + WPA_SUPPLICANT_DISABLE) + && (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) + && (pAd->StaCfg.PortSecured == + WPA_802_1X_PORT_SECURED)) + pAd->StaCfg.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 ((pAd->StaCfg.PortSecured == + WPA_802_1X_PORT_NOT_SECURED) + && + ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) + || (pAd->StaCfg.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->Aid, + 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/mt7620/src/sta/connect.c b/mt7620/src/sta/connect.c new file mode 100644 index 0000000..0763131 --- /dev/null +++ b/mt7620/src/sta/connect.c @@ -0,0 +1,4278 @@ +/* + *************************************************************************** + * 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" + +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 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->IndicateMediaState != NdisMediaStateConnected && (pAd->StaCfg.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); + } + +#ifdef P2P_SUPPORT + if (!((pAd->MlmeAux.ScanType == SCAN_P2P_SEARCH) || (pAd->MlmeAux.ScanType == SCAN_P2P))) +#endif /* P2P_SUPPORT */ + { + 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 P2P_SUPPORT + if (pAd->P2pCfg.P2pCounter.bStartScan && + ((pAd->MlmeAux.ScanType == SCAN_P2P) || (pAd->MlmeAux.ScanType == SCAN_P2P_SEARCH))) + { +#ifdef DPA_S + if (pAd->MlmeAux.ScanType == SCAN_P2P) + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_DISCOVER_START_SEARCH_LISTEN, NULL, NULL, 0); + if (pAd->MlmeAux.ScanType == SCAN_P2P_SEARCH) + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_DISCOVER_SEARCH_LISTEN_ITERATION, NULL, NULL, 0); +#endif /* DPA_S */ + + if (P2P_GO_ON(pAd)) + { + P2PSetNextScanTimer(pAd, 10); + } + else + P2PSetListenTimer(pAd, 0); + } + pAd->P2pCfg.bPeriodicListen = TRUE; +#endif /* P2P_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.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 */ +#ifdef P2P_SUPPORT + if (pAd->P2pCfg.P2pCounter.bStartScan == TRUE) + return; +#endif /* P2P_SUPPORT */ + + + /* 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; + ULONG Now; + + + /* 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) */ + /* & 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)); + + NdisGetSystemUpTime(&Now); + + 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 */ + + /* Add checking Mode "LEAP" for CCX 1.0 */ + if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef WAPI_SUPPORT + || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWAIPSK) + || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWAICERT) +#endif /* WAPI_SUPPORT */ + ) && + (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) { + /* case 1.1 For WPA, WPA-PSK, if the 1x 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) +#ifdef MESH_SUPPORT +#endif /* MESH_SUPPORT */ + ) { + MLME_SCAN_REQ_STRUCT ScanReq; + +#ifdef WAC_SUPPORT + if (pAd->StaCfg.EasyConfigInfo.bEnableWAC + && (pAd->StaCfg.EasyConfigInfo.DoAutoWAC == 0x00)) + { + if (WAC_FindWACAP(pAd)) + return; + } +#endif /* WAC_SUPPORT */ + 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)) + { + + NdisGetSystemUpTime(&Now); + 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; + /* Reset Missed scan number */ + pAd->StaCfg.LastScanTime = Now; + pAd->StaCfg.bNotFirstScan = TRUE; + } + 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 */ + pAd->StaCfg.LastScanTime = Now; + pAd->StaCfg.bNotFirstScan = TRUE; + }/*end pAd->StaCfg.ConnectinfoChannel != 0...*/ + } 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->MlmeAux.SsidBssTab. + BssEntry[pAd->MlmeAux.BssIdx].Channel == 14) + && ((pAd->CommonCfg.CountryRegion & 0x7f) == + REGION_33_BG_BAND) + && (pAd->CommonCfg.SavedPhyMode == 0xFF)) { + pAd->CommonCfg.SavedPhyMode = + pAd->CommonCfg.PhyMode; + RTMPSetPhyMode(pAd, PHY_11B); + } else + if ((pAd->MlmeAux.SsidBssTab. + BssEntry[pAd->MlmeAux.BssIdx].Channel != 14) + && (pAd->MlmeAux.SsidBssTab. + BssEntry[pAd->MlmeAux.BssIdx].Channel != 0) + && ((pAd->CommonCfg.CountryRegion & 0x7f) == + REGION_33_BG_BAND) + && (pAd->CommonCfg.SavedPhyMode != 0xFF)) { + RTMPSetPhyMode(pAd, + pAd->CommonCfg.SavedPhyMode); + pAd->CommonCfg.SavedPhyMode = 0xFF; + } + + pAd->MlmeAux.BssIdx = 0; + IterateOnBssTab(pAd); + } + } +} + +#ifdef WSC_STA_SUPPORT +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWscIterate( + IN PRTMP_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; + PBSS_ENTRY pInBss = NULL; + ULONG Now; + +#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", + pAd->StaCfg.ConnectinfoBssid[0], pAd->StaCfg.ConnectinfoBssid[1], pAd->StaCfg.ConnectinfoBssid[2], + pAd->StaCfg.ConnectinfoBssid[3], pAd->StaCfg.ConnectinfoBssid[4], pAd->StaCfg.ConnectinfoBssid[5])); + + /* 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.WpaSupplicantUP & WPA_SUPPLICANT_ENABLE_WPS) ; + else +#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 (pAd->StaCfg.AuthMode <= Ndis802_11AuthModeAutoSwitch) { + if (pAd->StaCfg.WepStatus != pInBss->WepStatus) + BssIdx = BSS_NOT_FOUND; + } else { + /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode */ + if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && + (pAd->StaCfg.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")); + NdisGetSystemUpTime(&Now); + if((pAd->StaCfg.ConnectinfoChannel != 0)&& (pAd->StaCfg.Connectinfoflag == TRUE)) + { + DBGPRINT(0, ("CntlOidRTBssidProc BSSID %02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->StaCfg.ConnectinfoBssid[0], pAd->StaCfg.ConnectinfoBssid[1], pAd->StaCfg.ConnectinfoBssid[2], + pAd->StaCfg.ConnectinfoBssid[3], pAd->StaCfg.ConnectinfoBssid[4], pAd->StaCfg.ConnectinfoBssid[5])); + 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; + /* Reset Missed scan number */ + NdisGetSystemUpTime(&pAd->StaCfg.LastScanTime); + } + 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); + +#ifdef WAC_SUPPORT + if (pAd->StaCfg.EasyConfigInfo.bEnableWAC + && (pInBss->WpsAP & 0x04) + && (pAd->StaCfg.EasyConfigInfo.DoAutoWAC == 0x01)) + { + pAd->StaCfg.EasyConfigInfo.bDoAutoWps = TRUE; + pAd->StaCfg.EasyConfigInfo.bWACAP = TRUE; + pAd->StaCfg.EasyConfigInfo.CurrentStatus = OFC_PROCEED_SECOND_PHASE; + } +#endif /* WAC_SUPPORT */ + + /* 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 = pAd->StaCfg.WepStatus; +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) +#endif /* WPA_SUPPLICANT_SUPPORT */ + pAd->StaCfg.GroupCipher = pAd->StaCfg.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 ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) + || (pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPAPSK)) { + pAd->StaCfg.GroupCipher = + pInBss->WPA.GroupCipher; + + if (pAd->StaCfg.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_11Encryption2Enabled; + } else + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) + || (pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPA2PSK)) { + pAd->StaCfg.GroupCipher = + pInBss->WPA2.GroupCipher; + + if (pAd->StaCfg.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_11Encryption2Enabled; + + /* RSN capability */ + pAd->StaCfg.RsnCapability = pInBss->WPA2.RsnCapability; + } +#ifdef WAPI_SUPPORT + else if ((pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWAICERT) + || (pAd->StaCfg.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", + pOidBssid[0], pOidBssid[1], pOidBssid[2], + pOidBssid[3], pOidBssid[4], pOidBssid[5])); + + 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) +{ + UCHAR BBPValue = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Roaming in MlmeAux.RoamTab...\n")); + + { + /*Let BBP register at 20MHz to do (fast) roaming. */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + + 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", + pAd->CommonCfg.Bssid[0], + pAd->CommonCfg.Bssid[1], + pAd->CommonCfg.Bssid[2], + pAd->CommonCfg.Bssid[3], + pAd->CommonCfg.Bssid[4], + pAd->CommonCfg.Bssid[5])); + + 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 { + { + /* either Ndis802_11AuthModeShared or Ndis802_11AuthModeAutoSwitch, try shared key first */ + if ((pAd->StaCfg.AuthMode == + Ndis802_11AuthModeShared) + || (pAd->StaCfg.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; + + 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 + NdisZeroMemory(&pAd->StaActive.SupportedPhyInfo. + MCSSet[0], 16); + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + && (pAd->StaCfg.bAdhocN == TRUE) + && (!pAd->CommonCfg.HT_DisallowTKIP + || !IS_INVALID_HT_SECURITY(pAd->StaCfg. + WepStatus))) { + N_ChannelCheck(pAd); + SetCommonHT(pAd); + if ((pAd->CommonCfg.HtCapability.HtCapInfo. + ChannelWidth == BW_40) + && (pAd->CommonCfg.AddHTInfo.AddHtInfo. + ExtChanOffset == EXTCHA_ABOVE)) { + pAd->MlmeAux.CentralChannel = + pAd->CommonCfg.Channel + 2; + } else + if ((pAd->CommonCfg.HtCapability.HtCapInfo. + ChannelWidth == BW_40) + && (pAd->CommonCfg.AddHTInfo.AddHtInfo. + ExtChanOffset == EXTCHA_BELOW)) { + pAd->MlmeAux.CentralChannel = + pAd->CommonCfg.Channel - 2; + } + NdisMoveMemory(&pAd->MlmeAux.AddHtInfo, + &pAd->CommonCfg.AddHTInfo, + sizeof (ADD_HT_INFO_IE)); + RTMPCheckHt(pAd, BSSID_WCID, + &pAd->CommonCfg.HtCapability, + &pAd->CommonCfg.AddHTInfo); + pAd->StaActive.SupportedPhyInfo.bHtEnable = + TRUE; + NdisMoveMemory(&pAd->StaActive.SupportedPhyInfo. + MCSSet[0], + &pAd->CommonCfg.HtCapability. + MCSSet[0], 16); + COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG + (pAd); + } 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", + pAd->CommonCfg.Bssid[0], + pAd->CommonCfg.Bssid[1], + pAd->CommonCfg.Bssid[2], + pAd->CommonCfg.Bssid[3], + pAd->CommonCfg.Bssid[4], + pAd->CommonCfg.Bssid[5])); + + 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; + + 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); + + { + 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")); + { + if ((pAd->StaCfg.AuthMode == + Ndis802_11AuthModeShared) + || (pAd->StaCfg.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); + { + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, + MT2_MLME_ASSOC_REQ, + sizeof (MLME_ASSOC_REQ_STRUCT), + &AssocReq, 0); + + pAd->Mlme.CntlMachine.CurrState = + CNTL_WAIT_ASSOC; + } + } else { + if ((pAd->StaCfg.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")); + 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) { + RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, NULL, + BSS0, 0); + + LinkUp(pAd, BSS_INFRA); + 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)); + 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); + + + /* */ + /* 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)); + { + pAd->MlmeAux.RoamIdx++; + IterateOnBssTab2(pAd); + } + } + } +} + +VOID AdhocTurnOnQos( + IN PRTMP_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( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssType) +{ + ULONG Now; + UINT32 Data; + BOOLEAN Cancelled; + UCHAR Value = 0, idx = 0; /*, HashIdx = 0; */ + MAC_TABLE_ENTRY *pEntry = NULL; /* *pCurrEntry = NULL; */ +#ifdef WSC_STA_SUPPORT + UCHAR tmpWscSsid[MAX_LEN_OF_SSID] = { 0 }; + UCHAR tmpWscSsidLen = 0; +#endif /* WSC_STA_SUPPORT */ + + /* 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; + + + + 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); +#ifdef MESH_SUPPORT + NdisMoveMemory(&pAd->CommonCfg.HtCapability, &pAd->MlmeAux.HtCapability, + sizeof (HT_CAPABILITY_IE)); + NdisMoveMemory(&pAd->CommonCfg.AddHTInfo, &pAd->MlmeAux.AddHtInfo, + sizeof (ADD_HT_INFO_IE)); +#endif /* MESH_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef P2P_SUPPORT + { + PAPCLI_STRUCT pApCliEntry = NULL; + + pApCliEntry = &pAd->ApCfg.ApCliTab[BSS0]; + + if (P2P_GO_ON(pAd) || (pApCliEntry->Valid == TRUE)) + { + pAd->CommonCfg.CentralChannel = pAd->MlmeAux.ConCurrentCentralChannel; +#ifdef DOT11_N_SUPPORT + if (pAd->MlmeAux.bBwFallBack == TRUE) + pAd->StaActive.SupportedHtPhy.ChannelWidth = BW_20; +#endif /* DOT11_N_SUPPORT */ + } + } +#endif /* P2P_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 ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + && (pAd->StaCfg.bAdhocN == TRUE)) + AdhocTurnOnQos(pAd); +#endif /* DOT11_N_SUPPORT */ + + InitChannelRelatedValue(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("!!!Adhoc LINK UP !!! \n")); + } 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, ("!!!Infra LINK UP !!! \n")); + } + + 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. + */ +#ifdef MESH_SUPPORT + if (!MESH_ON(pAd)) +#endif /* MESH_SUPPORT */ + 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 */ + +/* + NdisZeroMemory(&pAd->DrsCounters, sizeof (COUNTER_DRS)); +*/ + + 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 (pAd->StaCfg.WepStatus <= Ndis802_11WEPDisabled) + { +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP && + (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) && + (pAd->StaCfg.IEEE8021X == TRUE)) ; + else +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + pAd->StaCfg.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. */ + RTMP_IO_WRITE32(pAd, MAC_WCID_BASE, 0x00); + RTMP_IO_WRITE32(pAd, 0x1808, 0x00); + + /* 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 (pAd->StaCfg.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 */ + RTMP_ASIC_SHARED_KEY_TABLE(pAd, + BSS0, + idx, + &pAd->SharedKey[BSS0][idx]); + + if (idx == pAd->StaCfg.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 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) { + pAd->StaCfg.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_11Encryption2Enabled) { + 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_11Encryption2Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) + 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 */ + RTMP_ASIC_SHARED_KEY_TABLE(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 ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef WPA_SUPPLICANT_SUPPORT + && (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) +#endif /* WPA_SUPPLICANT_SUPPORT */ + ) { + USHORT Wcid = 0; + + pAd->StaCfg.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_11Encryption3Enabled) { + 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; + } + } +#ifndef DPA_S + /* 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")); +#endif /* !DPA_S */ + break; + } + + /* */ + /* On WPA mode, Remove All Keys if not connect to the last BSSID */ + /* Key will be set after 4-way handshake. */ + /* */ + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) { + /*ULONG IV; */ + + /* 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);*/ + pAd->StaCfg.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)) + && (pAd->StaCfg.WepStatus == Ndis802_11EncryptionSMS4Enabled)) + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT); + } +#endif /* WAPI_SUPPORT */ + + +#endif /* SOFT_ENCRYPT */ + + } + + /* 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 MESH_SUPPORT + if (MESH_ON(pAd)) { + AsicEnableMESHSync(pAd); + if ((pAd->CommonCfg.Channel != pAd->MeshTab.MeshChannel) +#ifdef DOT11_N_SUPPORT + || (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset != pAd->MeshTab.ExtChOffset) +#endif /* DOT11_N_SUPPORT */ + ) { + DBGPRINT(RT_DEBUG_TRACE, + ("Channel change , old channel:%d new channel:%d !! \n", + pAd->CommonCfg.Channel, + pAd->MeshTab.MeshChannel)); +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, + ("Old ExtCh:%d new ExtCh:%d !! \n", + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset, + pAd->MeshTab.ExtChOffset)); +#endif /* DOT11_N_SUPPORT */ + if (pAd->MeshTab.UCGEnable == TRUE) { + AsicSwitchChannel(pAd, + pAd->MeshTab.MeshChannel, FALSE); + AsicLockChannel(pAd, + pAd->MeshTab.MeshChannel); + pAd->MeshTab.MeshChannel = + pAd->CommonCfg.Channel; +#ifdef DOT11_N_SUPPORT + pAd->MeshTab.ExtChOffset = + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset; +#endif /* DOT11_N_SUPPORT */ + MlmeEnqueue(pAd, + MESH_CTRL_STATE_MACHINE, + MESH_CTRL_UCG_EVT, 0, NULL, + 0); + } else { + pAd->MeshTab.MeshChannel = + pAd->CommonCfg.Channel; +#ifdef DOT11_N_SUPPORT + pAd->MeshTab.ExtChOffset = + pAd->CommonCfg.AddHTInfo.AddHtInfo. + ExtChanOffset; +#endif /* DOT11_N_SUPPORT */ + MeshMakeBeacon(pAd, + MESH_BEACON_IDX(pAd)); + MeshUpdateBeaconFrame(pAd, + MESH_BEACON_IDX + (pAd)); + } + + TearDownAllMeshLink(pAd); + + } + } else +#endif /* MESH_SUPPORT */ +#ifdef P2P_SUPPORT + if (P2P_GO_ON(pAd)) + { + AsicEnableP2PGoSync(pAd); + if ((pAd->CommonCfg.Channel != pAd->P2PChannel) + ) + { + DBGPRINT(RT_DEBUG_TRACE, ("Channel change , old channel:%d new channel:%d !! \n" + ,pAd->P2PChannel,pAd->CommonCfg.Channel)); +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("Old ExtCh:%d new ExtCh:%d !! \n" + ,pAd->P2PExtChOffset,pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset)); +#endif /* DOT11_N_SUPPORT */ + P2P_GoStop(pAd); + P2P_GoStartUp(pAd, MAIN_MBSSID); + } + } + else if (P2P_CLI_ON(pAd)) + { + AsicEnableBssSync(pAd); + if ((pAd->CommonCfg.Channel != pAd->P2PChannel) + ) + { + DBGPRINT(RT_DEBUG_TRACE, ("Channel change , old channel:%d new channel:%d !! \n" + ,pAd->P2PChannel,pAd->CommonCfg.Channel)); +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("Old ExtCh:%d new ExtCh:%d !! \n" + ,pAd->P2PExtChOffset,pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset)); +#endif /* DOT11_N_SUPPORT */ + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, 0); + } + } + else +#endif /* P2P_SUPPORT */ + 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); + + /* If WEP is enabled, add paiewise and shared key */ +#ifdef WPA_SUPPLICANT_SUPPORT + if (((pAd->StaCfg.WpaSupplicantUP) && + (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) && + (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED)) || + ((pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) && + (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled))) +#else + if (pAd->StaCfg.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 */ + RTMP_ASIC_SHARED_KEY_TABLE(pAd, + BSS0, + idx, + &pAd->SharedKey[BSS0][idx]); + + if (idx == pAd->StaCfg.DefaultKeyId) { + /* STA doesn't need to set WCID attribute for group key */ + + /* Assign pairwise key info to Asic */ + pEntry->Aid = BSSID_WCID; + RTMPSetWcidSecurityInfo(pAd, + BSS0, + idx, + CipherAlg, + pEntry->Aid, + SHAREDKEYTABLE); + } + } + } + } + /* For GUI ++ */ + if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA) + { +#ifdef WPA_SUPPLICANT_SUPPORT + if (((pAd->StaCfg.WpaSupplicantUP) && (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) && (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED)) + || ((pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) && (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled)) + || (pAd->StaCfg.WepStatus == Ndis802_11WEPDisabled)) +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + pAd->ExtraInfo = GENERAL_LINK_UP; + RTMP_IndicateMediaState(pAd, NdisMediaStateConnected); + } + } else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) + { +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.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 WAC_QOS_PRIORITY + if (pAd->MlmeAux.bForcePriority) + pEntry->bSamsungForcePriority = TRUE; +#endif /* WAC_QOS_PRIORITY */ + + 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 + )) { + 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)) { + AsicEnableRDG(pAd); + } +#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 ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeOpen) + && (pAd->StaCfg.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 + /* Set LED */ + 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 = pAd->StaCfg.HTPhyMode.word; + pEntry->MaxHTPhyMode.word = pAd->StaCfg.HTPhyMode.word; + if (pAd->StaCfg.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) pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry); + } else + pEntry->bAutoTxRateSwitch = TRUE; + NdisReleaseSpinLock(&pAd->MacTabLock); + + /* Let Link Status Page display first initial rate. */ + pAd->LastTxRate = (USHORT) (pEntry->HTPhyMode.word); + +#if defined(RT2883) || defined(RT3883) + /* TODO: why we don't set it for RT2883/RT3883 */ + if (IS_RT2883(pAd) || IS_RT3883(pAd)) { + /* do nothing for DAC. */ + } else +#endif /* defined(RT2883) || defined(RT3883) */ + /* Select DAC according to HT or Legacy */ + if (pAd->StaActive.SupportedPhyInfo.MCSSet[0] != 0x00) { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &Value); + Value &= (~0x18); + + { + if (pAd->Antenna.field.TxPath >= 2) { + Value |= 0x10; + } + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, Value); + } else { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &Value); + Value &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, Value); + } + +#ifdef DOT11_N_SUPPORT + if ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE)) { + if (pEntry->MaxRAmpduFactor == 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. */ + RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x000A0fff); /* Default set to 0x1fff. But if one peer can't support 0x1fff, we need to change to 0xfff */ + } else if (pEntry->MaxRAmpduFactor == 1) { + RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x000A1fff); + } else if (pEntry->MaxRAmpduFactor == 2) { + RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x000A2fff); + } else if (pEntry->MaxRAmpduFactor == 3) { + RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x000A3fff); + } + DBGPRINT(RT_DEBUG_TRACE, + ("!!!MaxRAmpduFactor= %d \n", + pEntry->MaxRAmpduFactor)); + } +#endif /* DOT11_N_SUPPORT */ + + /* Patch for Marvel AP to gain high throughput */ + /* Need to set as following, */ + /* 1. Set txop in register-EDCA_AC0_CFG as 0x60 */ + /* 2. Set EnTXWriteBackDDONE in register-WPDMA_GLO_CFG as zero */ + /* 3. PBF_MAX_PCNT as 0x1F3FBF9F */ + /* 4. kick per two packets when dequeue */ + /* */ + /* 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)))) { + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + Data &= 0xFFFFFF00; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + + RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3F7F9F); + DBGPRINT(RT_DEBUG_TRACE, ("Txburst 1\n")); + } else +#endif /* DOT11_N_SUPPORT */ + if (pAd->CommonCfg.bEnableTxBurst) { + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + Data &= 0xFFFFFF00; + Data |= 0x60; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = TRUE; + + RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3FBF9F); + DBGPRINT(RT_DEBUG_TRACE, ("Txburst 2\n")); + } else { + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + Data &= 0xFFFFFF00; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + + RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3F7F9F); + DBGPRINT(RT_DEBUG_TRACE, ("Txburst 3\n")); + } + +#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)))) { + pAd->CommonCfg.IOTestParm.bNextDisableRxBA = TRUE; + if (pAd->CommonCfg.bEnableTxBurst) { + UINT32 MACValue = 0; + /* Force disable TXOP value in this case. The same action in MLMEUpdateProtect too. */ + /* I didn't change PBF_MAX_PCNT setting. */ + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &MACValue); + MACValue &= 0xFFFFFF00; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, MACValue); + pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = FALSE; + } + } else { + pAd->CommonCfg.IOTestParm.bNextDisableRxBA = FALSE; + } +#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) && + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) && + (NdisEqualMemory + (pAd->CommonCfg.Bssid, pAd->CommonCfg.LastBssid, + MAC_ADDR_LEN) == FALSE) && (pAd->StaCfg.bLostAp == TRUE)) { + pAd->StaCfg.bLostAp = FALSE; + } +#endif /* WPA_SUPPLICANT_SUPPORT */ + /* + Need to check this COPY. This COPY is from Windows Driver. + */ + + COPY_MAC_ADDR(pAd->CommonCfg.LastBssid, pAd->CommonCfg.Bssid); + DBGPRINT(RT_DEBUG_TRACE, + ("!!!pAd->bNextDisableRxBA= %d \n", + pAd->CommonCfg.IOTestParm.bNextDisableRxBA)); + /* 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 = pAd->StaCfg.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); + /*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, + ("pAd->StaActive.SupportedHtPhy.bHtEnable %d !!! \n", + pAd->StaActive.SupportedPhyInfo.bHtEnable)); + DBGPRINT(RT_DEBUG_TRACE, + ("pAd->MlmeAux.ExtCapInfo.BssCoexstSup %d !!! \n", + pAd->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 /* 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) && + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) && + (NdisEqualMemory + (pAd->CommonCfg.Bssid, pAd->CommonCfg.LastBssid, MAC_ADDR_LEN)) + && (pAd->StaCfg.bLostAp == TRUE)) { + WpaSendEapolStart(pAd, pAd->CommonCfg.Bssid); + pAd->StaCfg.bLostAp = FALSE; + } +#endif /* WPA_SUPPLICANT_SUPPORT */ + + pAd->MacTab.MsduLifeTime = 5; /* default 5 seconds */ +} + +/* + ========================================================================== + + 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, ByteValue = 0; + + /* 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 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 (pAd->StaCfg.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); + + + /* 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 ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED) + || (pAd->StaCfg.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 (pAd->StaCfg.WepStatus == Ndis802_11EncryptionSMS4Enabled) { + /* Clear Replay counter */ + /*NdisZeroMemory(pAd->StaCfg.rx_iv, LEN_WAPI_TSC); */ + + /* 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]) +#ifdef P2P_SUPPORT + && (!IS_P2P_GO_ENTRY(&pAd->MacTab.Content[i])) +#endif /* P2P_SUPPORT */ + ) + MacTableDeleteEntry(pAd, pAd->MacTab.Content[i].Aid, + pAd->MacTab.Content[i].Addr); + } + + AsicSetSlotTime(pAd, TRUE); /*FALSE); */ +#ifdef P2P_SUPPORT + if ((!P2P_GO_ON(pAd)) && (!P2P_CLI_ON(pAd))) +#endif /* 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 */ + +#ifdef MESH_SUPPORT + if (MESH_ON(pAd) && !ADHOC_ON(pAd)) + AsicEnableMESHSync(pAd); + else +#endif /* MESH_SUPPORT */ +#ifdef P2P_SUPPORT + if (!P2P_GO_ON(pAd)) +#endif /* P2P_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) && (pAd->StaCfg.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.WpaSupplicantUP && + (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) && + (pAd->StaCfg.IEEE8021X == FALSE)) { + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + } else +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + pAd->StaCfg.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 = pAd->StaCfg.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 + /* */ + /* After Link down, reset piggy-back setting in ASIC. Disable RDG. */ + /* */ + if (pAd->CommonCfg.BBPCurrentBW == BW_40) { +#ifdef P2P_SUPPORT + PAPCLI_STRUCT pApCliEntry = NULL; + + pApCliEntry = &pAd->ApCfg.ApCliTab[BSS0]; + + if (!P2P_GO_ON(pAd) && (pApCliEntry->Valid == FALSE)) +#endif /* P2P_SUPPORT */ + { + pAd->CommonCfg.BBPCurrentBW = BW_20; + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &ByteValue); + ByteValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, ByteValue); + } + } +#endif /* DOT11_N_SUPPORT */ + +#if defined(RT2883) || defined(RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd)) { + /* do nothing for DAC */ + } else +#endif /* defined(RT2883) || defined(RT3883) */ + { + /* Reset DAC */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &ByteValue); + ByteValue &= (~0x18); + + { + if (pAd->Antenna.field.TxPath >= 2) { + ByteValue |= 0x10; + } + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, ByteValue); + } + + 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 + AsicDisableRDG(pAd); +#endif /* DOT11_N_SUPPORT */ + pAd->CommonCfg.IOTestParm.bCurrentAtheros = FALSE; + pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = FALSE; + +#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.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 */ + + + 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( + IN PRTMP_ADAPTER pAd) +{ + MLME_START_REQ_STRUCT StartReq; + MLME_JOIN_REQ_STRUCT JoinReq; + ULONG BssIdx; + BSS_ENTRY *pInBss = NULL; + + /* Change the wepstatus to original wepstatus */ + pAd->StaCfg.PairCipher = pAd->StaCfg.WepStatus; +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) +#endif /* WPA_SUPPLICANT_SUPPORT */ + pAd->StaCfg.GroupCipher = pAd->StaCfg.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 ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) + || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) { + pAd->StaCfg.GroupCipher = pInBss->WPA.GroupCipher; + + if (pAd->StaCfg.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_11Encryption2Enabled; + } else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) + || (pAd->StaCfg.AuthMode == + Ndis802_11AuthModeWPA2PSK)) { + pAd->StaCfg.GroupCipher = pInBss->WPA2.GroupCipher; + + if (pAd->StaCfg.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_11Encryption2Enabled; + + /* RSN capability */ + pAd->StaCfg.RsnCapability = pInBss->WPA2.RsnCapability; + } +#ifdef WAPI_SUPPORT + else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWAICERT) + || (pAd->StaCfg.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 +#ifdef MESH_SUPPORT + if ((pAd->CommonCfg.BBPCurrentBW == BW_40) && MESH_ON(pAd)) { + UINT32 Data; + UCHAR Value = 0; + + /* Change to mesh channel */ + if ((pAd->CommonCfg.CentralChannel > + pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo. + ChannelWidth == BW_40)) { + /* Must using 40MHz. */ + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, + pAd->CommonCfg.CentralChannel, + FALSE); + AsicLockChannel(pAd, + pAd->CommonCfg.CentralChannel); + + 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); + + /* 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); +#ifdef RTMP_MAC_PCI + pAd->StaCfg.BBPR3 = Value; +#endif /* RTMP_MAC_PCI */ + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data &= 0xfffffffe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + 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_TRACE, + ("CNTL - All roaming failed, restore to Channel at Below. Central = %d \n", + pAd->CommonCfg.CentralChannel)); + } else + if ((pAd->CommonCfg.CentralChannel < + pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo. + ChannelWidth == BW_40)) { + /* Must using 40MHz. */ + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, + pAd->CommonCfg.CentralChannel, + FALSE); + AsicLockChannel(pAd, + pAd->CommonCfg.CentralChannel); + + 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); + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data |= 0x1; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + 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, + 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_TRACE, + ("CNTL - All roaming failed, restore to Channel at UpperCentral = %d \n", + pAd->CommonCfg.CentralChannel)); + } + + } else +#endif /* MESH_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)); + } + +#ifdef P2P_SUPPORT + if (P2P_GO_ON(pAd) || P2P_CLI_ON(pAd)) + ; /* Do NOT delete this entry here because ra interface cannot do all channel scan in this case. */ + else +#endif /* P2P_SUPPORT */ + { + 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( + IN PRTMP_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 */ + +#ifdef DOT11_N_SUPPORT +#ifdef MESH_SUPPORT + if ((pAd->CommonCfg.BBPCurrentBW == BW_40) && MESH_ON(pAd)) { + UINT32 Data; + UCHAR Value = 0; + + /* Change to mesh channel */ + if ((pAd->CommonCfg.CentralChannel > + pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo. + ChannelWidth == BW_40)) { + /* Must using 40MHz. */ + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, + pAd->CommonCfg.CentralChannel, + FALSE); + AsicLockChannel(pAd, + pAd->CommonCfg.CentralChannel); + + 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); + + /* 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); +#ifdef RTMP_MAC_PCI + pAd->StaCfg.BBPR3 = Value; +#endif /* RTMP_MAC_PCI */ + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data &= 0xfffffffe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + 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_TRACE, + ("CNTL - All roaming failed, restore to Channel at Below. Central = %d \n", + pAd->CommonCfg.CentralChannel)); + } else if ((pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) { + /* Must using 40MHz. */ + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, + pAd->CommonCfg.CentralChannel, + FALSE); + AsicLockChannel(pAd, + pAd->CommonCfg.CentralChannel); + + 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); + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data |= 0x1; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + 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, + 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_TRACE, + ("CNTL - All roaming failed, restore to Channel at UpperCentral = %d \n", + pAd->CommonCfg.CentralChannel)); + } + + } else +#endif /* MESH_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + { + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, + ("CNTL - All roaming failed, restore to channel %d, Total BSS[%02d]\n", + pAd->CommonCfg.Channel, pAd->ScanTab.BssNr)); + } + + 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 + + ========================================================================== + */ +#ifdef RTMP_MAC_PCI +VOID ComposePsPoll( + IN PRTMP_ADAPTER pAd) +{ + NdisZeroMemory(&pAd->PsPollFrame, sizeof (PSPOLL_FRAME)); + pAd->PsPollFrame.FC.Type = BTYPE_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); +} + +/* IRQL = DISPATCH_LEVEL */ +VOID ComposeNullFrame( + IN PRTMP_ADAPTER pAd) +{ + NdisZeroMemory(&pAd->NullFrame, sizeof (HEADER_802_11)); + pAd->NullFrame.FC.Type = BTYPE_DATA; + pAd->NullFrame.FC.SubType = SUBTYPE_NULL_FUNC; + 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); +} +#endif /* RTMP_MAC_PCI */ + + +/* + ========================================================================== + 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; + PTXWI_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; + + if ((pAd->CommonCfg.PhyMode == PHY_11B) + && (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, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + pAd->CommonCfg.Bssid); + Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) + || (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) + || (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled); + 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 ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) +#ifdef ADHOC_WPA2PSK_SUPPORT + || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) +#endif /* ADHOC_WPA2PSK_SUPPORT */ + ) { + UCHAR RSNIe = IE_WPA; + ULONG tmp; + + RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, + BSS0); +#ifdef ADHOC_WPA2PSK_SUPPORT + if (pAd->StaCfg.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 ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + && (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, FALSE, + &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, FALSE, &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( + IN PRTMP_ADAPTER pAd) +{ + UCHAR Value = 0; + UINT32 Data = 0; + +#ifdef RTMP_MAC_PCI + /* In power save , We will force use 1R. */ + /* So after link up, check Rx antenna # again. */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); + Value &= (~0x18); + if (pAd->Antenna.field.RxPath == 3) { + Value |= (0x10); + } else if (pAd->Antenna.field.RxPath == 2) { + Value |= (0x8); + } else if (pAd->Antenna.field.RxPath == 1) { + Value |= (0x0); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); + pAd->StaCfg.BBPR3 = Value; +#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)) { + /* Must using 40MHz. */ + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + + 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); + + /* 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); +#ifdef RTMP_MAC_PCI + pAd->StaCfg.BBPR3 = Value; +#endif /* RTMP_MAC_PCI */ + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data &= 0xfffffffe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + 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_TRACE, + ("!!!40MHz Lower !!! Control Channel at Below. Central = %d \n", + pAd->CommonCfg.CentralChannel)); + } else if ((pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == + BW_40)) { + /* Must using 40MHz. */ + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + + 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); + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data |= 0x1; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + 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, 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_TRACE, + ("!!! 40MHz Upper !!! Control Channel at UpperCentral = %d \n", + pAd->CommonCfg.CentralChannel)); + } else +#endif /* DOT11_N_SUPPORT */ + { + pAd->CommonCfg.BBPCurrentBW = BW_20; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); + Value &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data &= 0xfffffffe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + 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_TRACE, ("!!! 20MHz !!! \n")); + } + + RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW); + + /* */ + /* Save BBP_R66 value, it will be used in RTUSBResumeMsduTransmission */ + /* */ + AsicBBPReadWithRxChain(pAd, BBP_R66, &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++) + { + PBSS_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) +{ + UINT32 Value = 0; + UCHAR BBPValue = 0; + UCHAR BBP3Value = 0; +#ifdef P2P_SUPPORT + PAPCLI_STRUCT pApCliEntry = NULL; +#endif /* P2P_SUPPORT */ + BOOLEAN bChangeInitBW = FALSE; + + *pBwFallBack = 0; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("CentralChannel = %d, Channel %d, ChannelWidth = %d @@@@@@@@@@@\n", + ExtraCh, PriCh, BandWidth)); + +#ifdef P2P_SUPPORT + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; +#endif /* P2P_SUPPORT */ + + if (!INFRA_ON(pAd) +#ifdef P2P_SUPPORT + && !P2P_GO_ON(pAd) && (pApCliEntry->Valid == FALSE) +#endif /* P2P_SUPPORT */ + ) + { + bChangeInitBW = TRUE; + } +#ifdef P2P_SUPPORT + else + { + if ((P2P_GO_ON(pAd) || (pApCliEntry->Valid == TRUE)) && (pAd->CommonCfg.Channel != PriCh)) + { + bChangeInitBW = TRUE; + } + } +#endif /* P2P_SUPPORT */ + + if (bChangeInitBW == TRUE) + { + UCHAR Value = 0; + UINT32 Data = 0, MTxCycle, macStatus = 0; + + //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; + } + + 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)) + { + /* Must using 40MHz. */ + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + + 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); + + /* 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); + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data &= 0xfffffffe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + 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_TRACE, + ("!!!40MHz Lower !!! Control Channel at Below. Central = %d \n", + pAd->CommonCfg.CentralChannel)); + } + else if ((pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) && (BandWidth == BW_40)) + { + /* Must using 40MHz. */ + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + + 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); + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data |= 0x1; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + 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_TRACE, + ("!!! 40MHz Upper !!! Control Channel at UpperCentral = %d \n", + pAd->CommonCfg.CentralChannel)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + pAd->CommonCfg.BBPCurrentBW = BW_20; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); + Value &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data &= 0xfffffffe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + 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, 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_TRACE, ("!!! 20MHz !!! \n")); + } + + RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW); + + //Enable MAC Tx/Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Data); + Data |= 0x0C; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Data); + + /* */ + /* Save BBP_R66 value, it will be used in RTUSBResumeMsduTransmission */ + /* */ + AsicBBPReadWithRxChain(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue, RX_CHAIN_0); + + DBGPRINT(RT_DEBUG_TRACE, ("AdjustChannelRelatedValue ==> not any connection !!!\n")); + return; + } + + if (BandWidth) + { + if (pAd->CommonCfg.CentralChannel == pAd->CommonCfg.Channel) + { + pAd->CommonCfg.CentralChannel = ExtraCh; + pAd->CommonCfg.Channel = PriCh; + + /* Set Regsiter for extension channel position.*/ + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBP3Value); + if (ExtraCh < PriCh) + { + Value |= 0x1; + BBP3Value |= (0x20); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + } + else if (ExtraCh > PriCh) + { + Value &= 0xfe; + BBP3Value &= (~0x20); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + } + + /* Turn on BBP 40MHz mode now. */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPActive == 0) +#endif /* GREENAP_SUPPORT */ + BBPValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBP3Value); +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPActive == 1) + pAd->CommonCfg.BBPCurrentBW = BW_20; + else +#endif /* GREENAP_SUPPORT */ + pAd->CommonCfg.BBPCurrentBW = BW_40; + } + else + { + if (pAd->CommonCfg.CentralChannel != ExtraCh) + { + *pBwFallBack = 1; + } + } + } +} + diff --git a/mt7620/src/sta/dls.c b/mt7620/src/sta/dls.c new file mode 100644 index 0000000..80cbb69 --- /dev/null +++ b/mt7620/src/sta/dls.c @@ -0,0 +1,2736 @@ +/**************************************************************************** + * 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 ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) { + 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 */ + for (i = 0; i < SupportedRatesLen; i++) { + if (MaxSupportedRateIn500Kbps < (SupportedRates[i] & 0x7f)) + MaxSupportedRateIn500Kbps = SupportedRates[i] & 0x7f; + } + + 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.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.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); + + 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.MaxTxRate, + 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; + + /* 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, + ("DLS - PeerDlsReqAction() Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n", + SA[0], SA[1], SA[2], + SA[3], SA[4], SA[5])); + + 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 */ + for (ii = 15; ii >= 0; ii--) { + j = ii / 8; + bitmask = (1 << (ii - (j * 8))); + if ((pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j] & bitmask) + && (HtCapability.MCSSet[j] & bitmask)) { + pEntry->MaxHTPhyMode.field.MCS = ii; + break; + } + if (ii == 0) + break; + } + + if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) { + + DBGPRINT(RT_DEBUG_OFF, + ("@@@ pAd->CommonCfg.RegTransmitSetting.field.MCS = %d\n", + pAd->StaCfg.DesiredTransmitSetting.field.MCS)); + if (pAd->StaCfg.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.HTPhyMode.field.MCS) { + /* STA supports fixed MCS */ + pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.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.bAutoTxRateSwitch == TRUE) { + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, + pEntry, + &pEntry->pTable, + &TableSize, + &pEntry->CurrTxRateIndex); + pEntry->bAutoTxRateSwitch = TRUE; + } else { + pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + + RTMPUpdateLegacyTxSetting((UCHAR) pAd->StaCfg.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 ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) { + 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 */ + for (i = 0; i < SupportedRatesLen; i++) { + if (MaxSupportedRateIn500Kbps < (SupportedRates[i] & 0x7f)) + MaxSupportedRateIn500Kbps = SupportedRates[i] & 0x7f; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x with StatusCode=%d, CapabilityInfo=0x%x\n", + SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], 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); + + 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.MaxTxRate, + 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; + + /* 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_OFF, + ("DLS - PeerDlsRspAction Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n", + SA[0], SA[1], SA[2], SA[3], + SA[4], SA[5])); + + 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 */ + for (ii = 15; ii >= 0; ii--) { + j = ii / 8; + bitmask = (1 << (ii - (j * 8))); + if ((pAd->StaCfg. + DesiredHtPhyInfo. + MCSSet[j] & bitmask) + && (HtCapability. + MCSSet[j] & bitmask)) { + pEntry->MaxHTPhyMode. + field.MCS = ii; + break; + } + if (ii == 0) + break; + } + + if (pAd->StaCfg.DesiredTransmitSetting. + field.MCS != MCS_AUTO) { + if (pAd->StaCfg. + 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. + HTPhyMode.field. + MCS) { + /* STA supports fixed MCS */ + pEntry->MaxHTPhyMode. + field.MCS = + pAd->StaCfg. + 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.bAutoTxRateSwitch == TRUE) { + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, pEntry, + &pEntry->pTable, + &TableSize, + &pEntry->CurrTxRateIndex); + pEntry->bAutoTxRateSwitch = TRUE; + } else { + pEntry->HTPhyMode.field.MODE = + pAd->StaCfg.HTPhyMode.field.MODE; + pEntry->HTPhyMode.field.MCS = + pAd->StaCfg.HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + + RTMPUpdateLegacyTxSetting((UCHAR) pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, + pEntry); + } + pEntry->RateLen = SupportedRatesLen; + + if (pAd->StaCfg.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", + SA[0], SA[1], SA[2], SA[3], + SA[4], SA[5])); + } + + /*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); + + 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.MaxTxRate, + 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; + + /* 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, + ("DLS - PeerDlsRspAction Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n", + SA[0], SA[1], SA[2], + SA[3], SA[4], SA[5])); + + 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 */ + for (ii = 15; ii >= 0; ii--) { + j = ii / 8; + bitmask = + (1 << + (ii - (j * 8))); + if ((pAd->StaCfg. + DesiredHtPhyInfo. + MCSSet[j] & + bitmask) + && (HtCapability. + MCSSet[j] & + bitmask)) { + pEntry-> + MaxHTPhyMode. + field.MCS = + ii; + break; + } + if (ii == 0) + break; + } + + if (pAd->StaCfg. + DesiredTransmitSetting. + field.MCS != MCS_AUTO) { + DBGPRINT(RT_DEBUG_OFF, + ("@@@ pAd->CommonCfg.RegTransmitSetting.field.MCS = %d\n", + pAd->StaCfg. + DesiredTransmitSetting. + field.MCS)); + if (pAd->StaCfg. + 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. + HTPhyMode. + field.MCS) { + /* STA supports fixed MCS */ + pEntry-> + MaxHTPhyMode. + field.MCS = + pAd->StaCfg. + 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.bAutoTxRateSwitch == TRUE) { + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, + pEntry, + &pEntry->pTable, + &TableSize, + &pEntry->CurrTxRateIndex); + pEntry->bAutoTxRateSwitch = TRUE; + } else { + pEntry->HTPhyMode.field.MODE = + pAd->StaCfg.HTPhyMode.field.MODE; + pEntry->HTPhyMode.field.MCS = + pAd->StaCfg.HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + + RTMPUpdateLegacyTxSetting((UCHAR) pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + pEntry->RateLen = SupportedRatesLen; + + if (pAd->StaCfg.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", + SA[0], SA[1], SA[2], + SA[3], SA[4], SA[5])); + } + 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 PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHeader, + IN ULONG Len, + IN PRT28XX_RXD_STRUC pRxD) +{ + 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 (pRxD->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.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.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.WepStatus == + Ndis802_11Encryption3Enabled) { + /* 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", + pAddr[0], pAddr[1], pAddr[2], + pAddr[3], pAddr[4], pAddr[5], 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); + + /*PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg; */ + if (pAd->StaCfg.PairCipher == + Ndis802_11Encryption2Enabled) + PairwiseKey.CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == + Ndis802_11Encryption3Enabled) + 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 (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; + /*AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr); */ + } + } + + 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_11Encryption2Enabled) + PairwiseKey.CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == + Ndis802_11Encryption3Enabled) + 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", + pDA[0], pDA[1], pDA[2], pDA[3], pDA[4], pDA[5])); + + 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.AuthMode == Ndis802_11AuthModeWPA) + || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) { + pPacket->KeyDesc.Type = WPA1_KEY_DESC; + } else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) + || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) { + pPacket->KeyDesc.Type = WPA2_KEY_DESC; + } + + /* Key descriptor version */ + pPacket->KeyDesc.KeyInfo.KeyDescVer = + (((pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) + || (pAd->StaCfg.GroupCipher == + Ndis802_11Encryption3Enabled)) ? (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.WepStatus == Ndis802_11Encryption3Enabled) { + /* 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", + pDA[0], pDA[1], pDA[2], pDA[3], pDA[4], pDA[5])); + + 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.AuthMode == Ndis802_11AuthModeWPA) + || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) { + pPacket->KeyDesc.Type = WPA1_KEY_DESC; + } else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) + || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) { + pPacket->KeyDesc.Type = WPA2_KEY_DESC; + } + + /* Key descriptor version */ + pPacket->KeyDesc.KeyInfo.KeyDescVer = + (((pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) + || (pAd->StaCfg.GroupCipher == + Ndis802_11Encryption3Enabled)) ? (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.WepStatus == Ndis802_11Encryption3Enabled) { + /* 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", + pDLS->MacAddr[0], pDLS->MacAddr[1], pDLS->MacAddr[2], + pDLS->MacAddr[3], pDLS->MacAddr[4], pDLS->MacAddr[5])); + + 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, + DlsEntryIdx + MIN_NET_DEVICE_FOR_DLS, + OPMODE_STA, + TRUE); + if (pEntry) { + pAd->StaCfg.DLSEntry[DlsEntryIdx].MacTabMatchWCID = + pEntry->Aid; + pEntry->MatchDlsEntryIdx = DlsEntryIdx; + pEntry->AuthMode = pAd->StaCfg.AuthMode; + pEntry->WepStatus = pAd->StaCfg.WepStatus; + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + + DBGPRINT(RT_DEBUG_TRACE, + ("MacTableInsertDlsEntry - allocate entry #%d, Total= %d\n", + pEntry->Aid, 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.WepStatus == + Ndis802_11WEPEnabled)) { + UCHAR KeyIdx = 0; + UCHAR CipherAlg = 0; + + KeyIdx = pAd->StaCfg.DefaultKeyId; + + CipherAlg = + pAd->SharedKey[BSS0][KeyIdx].CipherAlg; + + RTMPSetWcidSecurityInfo(pAd, + BSS0, + pAd->StaCfg. + DefaultKeyId, + pAd-> + SharedKey[BSS0][pAd-> + StaCfg. + DefaultKeyId]. + CipherAlg, pEntry->Aid, + 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 ", + pAd->StaCfg.DLSEntry[i].MacAddr[0], + pAd->StaCfg.DLSEntry[i].MacAddr[1], + pAd->StaCfg.DLSEntry[i].MacAddr[2], + pAd->StaCfg.DLSEntry[i].MacAddr[3], + pAd->StaCfg.DLSEntry[i].MacAddr[4], + pAd->StaCfg.DLSEntry[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", + GetPhyMode(pEntry->HTPhyMode.field.MODE))); + DBGPRINT(RT_DEBUG_OFF, + ("%-6s", GetBW(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", macAddr[0], macAddr[1], + macAddr[2], macAddr[3], macAddr[4], macAddr[5])); + + 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/mt7620/src/sta/p2pcli.c b/mt7620/src/sta/p2pcli.c new file mode 100644 index 0000000..7a2fb3b --- /dev/null +++ b/mt7620/src/sta/p2pcli.c @@ -0,0 +1,2172 @@ +/* + *************************************************************************** + * 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 + MBSS_VirtualIF_PacketSend() by using RTMP_SET_PACKET_NET_DEVICE_MBSSID() + 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 P2P_SUPPORT + +#include "rt_config.h" + + +/* --------------------------------- Private -------------------------------- */ +INT ApCliIfLookUp( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr) +{ + SHORT i; + SHORT ifIndex = -1; + + do + { + for(i = 0; i < MAX_APCLI_NUM; i++) + { + if( MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[i].CurrentAddress, pAddr)) + { + ifIndex = i; + DBGPRINT(RT_DEBUG_TRACE, ("(%s) ApCliIfIndex = %d\n", __FUNCTION__, ifIndex)); + break; + } + } + } while (FALSE); + + return ifIndex; +} + +BOOLEAN isValidApCliIf( + SHORT ifIndex) +{ + if((ifIndex >= 0) && (ifIndex < MAX_APCLI_NUM)) + return TRUE; + else + return 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 PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN PUCHAR pDA, + IN PUCHAR pBssid, + IN USHORT ifIndex) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + pHdr80211->FC.Type = BTYPE_MGMT; + pHdr80211->FC.SubType = SubType; + pHdr80211->FC.ToDs = ToDs; + COPY_MAC_ADDR(pHdr80211->Addr1, pDA); + COPY_MAC_ADDR(pHdr80211->Addr2, pAd->ApCfg.ApCliTab[ifIndex].CurrentAddress); + 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 PRTMP_ADAPTER pAd, + IN USHORT IfIndex, + IN OUT HT_CAPABILITY_IE *pHtCapability, + IN OUT ADD_HT_INFO_IE *pAddHtInfo) +{ + PAPCLI_STRUCT pApCliEntry = NULL; + + if (IfIndex >= MAX_APCLI_NUM) + return FALSE; + + pApCliEntry = &pAd->ApCfg.ApCliTab[IfIndex]; + + /* If use AMSDU, set flag. */ + if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE)) + CLIENT_STATUS_SET_FLAG(pApCliEntry, fCLIENT_STATUS_AMSDU_INUSED); + /* Save Peer Capability */ + if (pHtCapability->HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(pApCliEntry, fCLIENT_STATUS_SGI20_CAPABLE); + if (pHtCapability->HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(pApCliEntry, fCLIENT_STATUS_SGI40_CAPABLE); + if (pHtCapability->HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(pApCliEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); + if (pHtCapability->HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(pApCliEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); + if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) + CLIENT_STATUS_SET_FLAG(pApCliEntry, fCLIENT_STATUS_RDG_CAPABLE); + pApCliEntry->MpduDensity = pHtCapability->HtCapParm.MpduDensity; + + if ((pAd->OpMode == OPMODE_STA)) + { + } + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[0] = 0xff; + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[4] = 0x1; + switch (pAd->CommonCfg.RxStream) + { + case 1: + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[0] = 0xff; + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[1] = 0x00; + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[2] = 0x00; + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[3] = 0x00; + break; + case 2: + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[0] = 0xff; + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[1] = 0xff; + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[2] = 0x00; + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[3] = 0x00; + break; + case 3: + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[0] = 0xff; + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[1] = 0xff; + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[2] = 0xff; + pApCliEntry->ApCliMlmeAux.HtCapability.MCSSet[3] = 0x00; + break; + } + + /* Record the RxMcs of AP */ + NdisMoveMemory(pApCliEntry->RxMcsSet, pHtCapability->MCSSet, 16); + + + /* + if (pAd->Antenna.field.TxPath == 2) // 2: 2Tx 1: 1Tx + { + pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff; + } + else + { + pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00; + } + */ + /* 2008/12/17:KH modified to fix the low throughput of AP-Client on Big-Endian Platform--> */ + + /* choose smaller setting */ + pApCliEntry->ApCliMlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth; + pApCliEntry->ApCliMlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF; + + /* Send Assoc Req with my HT capability. */ + pApCliEntry->ApCliMlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize; + pApCliEntry->ApCliMlmeAux.HtCapability.HtCapInfo.MimoPs = pHtCapability->HtCapInfo.MimoPs; + pApCliEntry->ApCliMlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20); + pApCliEntry->ApCliMlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40); + pApCliEntry->ApCliMlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC); + pApCliEntry->ApCliMlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC); + pApCliEntry->ApCliMlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = (pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor) & (pHtCapability->HtCapParm.MaxRAmpduFactor); + pApCliEntry->ApCliMlmeAux.HtCapability.HtCapParm.MpduDensity = pHtCapability->HtCapParm.MpduDensity; + pApCliEntry->ApCliMlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC; + + + if (pAd->CommonCfg.bRdg) + { + pApCliEntry->ApCliMlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport; + } + + /*COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability); */ + return TRUE; +} +#endif /* DOT11_N_SUPPORT */ + + +VOID ComposeP2PPsPoll( + IN PRTMP_ADAPTER pAd, + IN PAPCLI_STRUCT pApCliEntry) +{ + NdisZeroMemory(&pApCliEntry->PsPollFrame, sizeof (PSPOLL_FRAME)); + pApCliEntry->PsPollFrame.FC.Type = BTYPE_CNTL; + pApCliEntry->PsPollFrame.FC.SubType = SUBTYPE_PS_POLL; + pApCliEntry->PsPollFrame.Aid = pApCliEntry->ApCliMlmeAux.Aid | 0xC000; + + COPY_MAC_ADDR(pApCliEntry->PsPollFrame.Bssid, pApCliEntry->ApCliMlmeAux.Bssid); + COPY_MAC_ADDR(pApCliEntry->PsPollFrame.Ta, pApCliEntry->CurrentAddress); +} + +VOID ComposeP2PNullFrame( + IN PRTMP_ADAPTER pAd, + IN PAPCLI_STRUCT pApCliEntry) +{ + NdisZeroMemory(&pApCliEntry->NullFrame, sizeof (HEADER_802_11)); + pApCliEntry->NullFrame.FC.Type = BTYPE_DATA; + pApCliEntry->NullFrame.FC.SubType = SUBTYPE_NULL_FUNC; + pApCliEntry->NullFrame.FC.ToDs = 1; + + COPY_MAC_ADDR(pApCliEntry->NullFrame.Addr1, pApCliEntry->ApCliMlmeAux.Bssid); + COPY_MAC_ADDR(pApCliEntry->NullFrame.Addr2, pApCliEntry->CurrentAddress); + COPY_MAC_ADDR(pApCliEntry->NullFrame.Addr3, pApCliEntry->ApCliMlmeAux.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( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex) +{ + BOOLEAN result = FALSE; + PAPCLI_STRUCT pApCliEntry = NULL; + PMAC_TABLE_ENTRY pMacEntry = NULL; + + do + { + if (ifIndex < MAX_APCLI_NUM) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! APCLI LINK UP - IF(apcli%d) AuthMode(%d)=%s, WepStatus(%d)=%s !!!\n", + ifIndex, + pAd->ApCfg.ApCliTab[ifIndex].AuthMode, GetAuthMode(pAd->ApCfg.ApCliTab[ifIndex].AuthMode), + pAd->ApCfg.ApCliTab[ifIndex].WepStatus, GetEncryptType(pAd->ApCfg.ApCliTab[ifIndex].WepStatus))); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("!!! ERROR : APCLI LINK UP - IF(apcli%d)!!!\n", ifIndex)); + result = FALSE; + break; + } + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + /* Sanity check: This link had existed. */ + if (pApCliEntry->Valid) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!! ERROR : This link had existed - IF(apcli%d)!!!\n", ifIndex)); + result = FALSE; + break; + } + + /* Insert the Remote AP to our MacTable. */ + /*pMacEntry = MacTableInsertApCliEntry(pAd, (PUCHAR)(pAd->MlmeAux.Bssid)); */ + pMacEntry = MacTableInsertEntry(pAd, (PUCHAR)(pApCliEntry->ApCliMlmeAux.Bssid), + (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; + UCHAR P2pIdx = P2P_NOT_FOUND; + + DBGPRINT(RT_DEBUG_INFO, ("%s:: Insert MAC Table success. ifIndex = %d.\n", __FUNCTION__, ifIndex)); + pMacEntry->Sst = SST_ASSOC; + DBGPRINT(RT_DEBUG_TRACE, ("\n++++++++ %s:: Delete BssSearch Table on Channel = %d. ++++++++\n", __FUNCTION__, pAd->CommonCfg.Channel)); + DBGPRINT(RT_DEBUG_TRACE, (" BSSID = [%02x:%02x:%02x:%02x:%02x:%02x]. p2p_bssid = [%02x:%02x:%02x:%02x:%02x:%02x].\n", PRINT_MAC(pApCliEntry->ApCliMlmeAux.Bssid), PRINT_MAC(pAd->P2pCfg.Bssid))); + BssTableDeleteEntry(&pAd->ScanTab, + /*pAd->ApCliMlmeAux.Bssid*/pAd->P2pCfg.Bssid, + pAd->CommonCfg.Channel); + if (pApCliEntry->bP2pClient) + { + pMacEntry->bP2pClient = TRUE; + pMacEntry->P2pInfo.P2pClientState = P2PSTATE_CLIENT_ASSOC; + P2pIdx = P2pGroupTabSearch(pAd, pMacEntry->Addr); + if (P2pIdx != P2P_NOT_FOUND) + pMacEntry->P2pInfo.p2pIndex = P2pIdx; + } + else + pMacEntry->bP2pClient = FALSE; + + NdisGetSystemUpTime(&pApCliEntry->ApCliRcvBeaconTime); + pApCliEntry->Valid = TRUE; + pApCliEntry->MacTabWCID = pMacEntry->Aid; + + COPY_MAC_ADDR(APCLI_ROOT_BSSID_GET(pAd, pApCliEntry->MacTabWCID), pApCliEntry->ApCliMlmeAux.Bssid); + pApCliEntry->SsidLen = pApCliEntry->ApCliMlmeAux.SsidLen; + NdisMoveMemory(pApCliEntry->Ssid, pApCliEntry->ApCliMlmeAux.Ssid, pApCliEntry->SsidLen); + + ComposeP2PPsPoll(pAd, pApCliEntry); + ComposeP2PNullFrame(pAd, pApCliEntry); + + if (pMacEntry->AuthMode >= Ndis802_11AuthModeWPA) + pMacEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + else + pMacEntry->PortSecured = WPA_802_1X_PORT_SECURED; + + /* 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->ApCliMlmeAux.VarIELen != 0)) + { + PUCHAR pVIE; + UCHAR len; + PEID_STRUCT pEid; + + pVIE = pApCliEntry->ApCliMlmeAux.VarIEs; + len = pApCliEntry->ApCliMlmeAux.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->ApCliMlmeAux.SupRate, pApCliEntry->ApCliMlmeAux.SupRateLen, pApCliEntry->ApCliMlmeAux.ExtRate, + pApCliEntry->ApCliMlmeAux.ExtRateLen, &pRates, &RatesLen, &MaxSupportedRate); + + pMacEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); + pMacEntry->RateLen = RatesLen; + if (pMacEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE) + { + pMacEntry->MaxHTPhyMode.field.MODE = MODE_CCK; + pMacEntry->MaxHTPhyMode.field.MCS = pMacEntry->MaxSupportedRate; + pMacEntry->MinHTPhyMode.field.MODE = MODE_CCK; + pMacEntry->MinHTPhyMode.field.MCS = pMacEntry->MaxSupportedRate; + pMacEntry->HTPhyMode.field.MODE = MODE_CCK; + pMacEntry->HTPhyMode.field.MCS = pMacEntry->MaxSupportedRate; + } + else + { + pMacEntry->MaxHTPhyMode.field.MODE = MODE_OFDM; + pMacEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pMacEntry->MaxSupportedRate]; + pMacEntry->MinHTPhyMode.field.MODE = MODE_OFDM; + pMacEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pMacEntry->MaxSupportedRate]; + pMacEntry->HTPhyMode.field.MODE = MODE_OFDM; + pMacEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pMacEntry->MaxSupportedRate]; + } + pMacEntry->CapabilityInfo = pApCliEntry->ApCliMlmeAux.CapabilityInfo; + + /* If WEP is enabled, add paiewise and shared key */ + if (pApCliEntry->WepStatus == Ndis802_11WEPEnabled) + { + PCIPHER_KEY pKey; + INT idx, BssIdx; + + BssIdx = pAd->ApCfg.BssidNum + MAX_MESH_NUM + ifIndex; + + for (idx=0; idx < SHARE_KEY_NUM; idx++) + { + pKey = &pApCliEntry->SharedKey[idx]; + + if (pKey->KeyLen > 0) + { + /* Set key material and cipherAlg to Asic */ + RTMP_ASIC_SHARED_KEY_TABLE(pAd, + BssIdx, + idx, + pKey); + + if (idx == pApCliEntry->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->Aid, + SHAREDKEYTABLE); + } + } + } + } + +#ifdef DOT11_N_SUPPORT + /* If this Entry supports 802.11n, upgrade to HT rate. */ + if (pApCliEntry->ApCliMlmeAux.HtCapabilityLen != 0) + { + UCHAR j, bitmask; /* k,bitmask; */ + CHAR i; + PHT_CAPABILITY_IE pHtCapability = (PHT_CAPABILITY_IE)&(pApCliEntry->ApCliMlmeAux.HtCapability); + + if ((pApCliEntry->ApCliMlmeAux.HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) + { + pMacEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD; + } + else + { + pMacEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pAd->MacTab.fAnyStationNonGF = TRUE; + pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1; + } + + if ((pHtCapability->HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth)) + { + pMacEntry->MaxHTPhyMode.field.BW= BW_40; + pMacEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(pHtCapability->HtCapInfo.ShortGIfor40)); + } + else + { + pMacEntry->MaxHTPhyMode.field.BW = BW_20; + pMacEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(pHtCapability->HtCapInfo.ShortGIfor20)); + pAd->MacTab.fAnyStation20Only = TRUE; + } + + /* find max fixed rate */ + /* 2008/12/17:KH modified to fix the low throughput of AP-Client on Big-Endian Platform<-- */ + + /* for (i=15; i>=0; i--) */ + for (i=23; i>=0; i--) //3*3 + /* 2008/12/17:KH modified to fix the low throughput of AP-Client on Big-Endian Platform--> */ + { + j = i/8; + bitmask = (1<<(i-(j*8))); + if ((pAd->ApCfg.ApCliTab[ifIndex].DesiredHtPhyInfo.MCSSet[j] & bitmask) && (pHtCapability->MCSSet[j] & bitmask)) + { + pMacEntry->MaxHTPhyMode.field.MCS = i; + break; + } + if (i==0) + break; + } + + + if (pAd->ApCfg.ApCliTab[ifIndex].DesiredTransmitSetting.field.MCS != MCS_AUTO) + { + DBGPRINT(RT_DEBUG_TRACE, ("IF-apcli%d : Desired MCS = %d\n", ifIndex, + pAd->ApCfg.ApCliTab[ifIndex].DesiredTransmitSetting.field.MCS)); + + if (pAd->ApCfg.ApCliTab[ifIndex].DesiredTransmitSetting.field.MCS == 32) + { + /* Fix MCS as HT Duplicated Mode */ + pMacEntry->MaxHTPhyMode.field.BW = 1; + pMacEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pMacEntry->MaxHTPhyMode.field.STBC = 0; + pMacEntry->MaxHTPhyMode.field.ShortGI = 0; + pMacEntry->MaxHTPhyMode.field.MCS = 32; + } + else if (pMacEntry->MaxHTPhyMode.field.MCS > pAd->ApCfg.ApCliTab[ifIndex].HTPhyMode.field.MCS) + { + /* STA supports fixed MCS */ + pMacEntry->MaxHTPhyMode.field.MCS = pAd->ApCfg.ApCliTab[ifIndex].HTPhyMode.field.MCS; + } + } + + pMacEntry->MaxHTPhyMode.field.STBC = (pHtCapability->HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); + 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->ApCliMlmeAux.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 */ + + pMacEntry->HTPhyMode.word = pMacEntry->MaxHTPhyMode.word; + pMacEntry->CurrTxRate = pMacEntry->MaxSupportedRate; + + if (pAd->ApCfg.ApCliTab[ifIndex].bAutoTxRateSwitch == FALSE) + { + pMacEntry->bAutoTxRateSwitch = FALSE; + /* If the legacy mode is set, overwrite the transmit setting of this entry. */ + RTMPUpdateLegacyTxSetting((UCHAR)pAd->ApCfg.ApCliTab[ifIndex].DesiredTransmitSetting.field.FixedTxMode, pMacEntry); + } + else + { + UCHAR TableSize = 0; + + pMacEntry->bAutoTxRateSwitch = TRUE; + MlmeSelectTxRateTable(pAd, pMacEntry, &pMacEntry->pTable, &TableSize, &pMacEntry->CurrTxRateIndex); + } + + /* It had been set in APStartUp. Don't set again. */ + if (!INFRA_ON(pAd)) + { + NdisMoveMemory(&(pAd->CommonCfg.APEdcaParm), &(pApCliEntry->ApCliMlmeAux.APEdcaParm), sizeof(EDCA_PARM)); + + AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); + } + + /* set this entry WMM capable or not */ + if ((pApCliEntry->ApCliMlmeAux.APEdcaParm.bValid) +#ifdef DOT11_N_SUPPORT + || IS_HT_STA(pMacEntry) +#endif /* DOT11_N_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->ApCliMlmeAux.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->ApCliMlmeAux.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")); + } + } + + pApCliEntry->ApCliBeaconPeriod = pApCliEntry->ApCliMlmeAux.BeaconPeriod; + + { + ULONG TmpLen; + UCHAR P2pIdx = P2P_NOT_FOUND; + UCHAR GroupCap = 0xff, DeviceCap = 0xff, DevAddr[6] = {0}, DeviceType[8], DeviceName[32], DeviceNameLen = 0; + PUCHAR pData; + USHORT Dpid, ConfigMethod; + + pMacEntry->bP2pClient = TRUE; + pMacEntry->P2pInfo.P2pClientState = P2PSTATE_GO_OPERATING; + + P2pIdx = P2pGroupTabSearch(pAd, pMacEntry->Addr); + if (P2pIdx == P2P_NOT_FOUND) + P2pIdx = P2pGroupTabInsert(pAd, DevAddr, P2PSTATE_DISCOVERY_GO, NULL, 0, 0, 0); + + if (P2pIdx != P2P_NOT_FOUND) + pMacEntry->P2pInfo.p2pIndex = P2pIdx; + } + + result = TRUE; + + pAd->ApCfg.ApCliInfRunned++; + break; + } + result = FALSE; + + } while(FALSE); + + RTMPSetSupportMCS(pAd, + OPMODE_AP, + pMacEntry, + pApCliEntry->ApCliMlmeAux.SupRate, + pApCliEntry->ApCliMlmeAux.SupRateLen, + pApCliEntry->ApCliMlmeAux.ExtRate, + pApCliEntry->ApCliMlmeAux.ExtRateLen, + &pApCliEntry->ApCliMlmeAux.HtCapability, + pApCliEntry->ApCliMlmeAux.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_ENROLLEE) && + (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->ApCliMlmeAux.Bssid, MAC_ADDR_LEN); + WscSendEapolStart(pAd, pMacEntry->Addr, AP_MODE); + } + else + { + WscStop(pAd, TRUE, &pAd->ApCfg.ApCliTab[ifIndex].WscControl); + } +#endif /* WSC_AP_SUPPORT */ + + return result; +} + +/* + ========================================================================== + + Routine Description: + Disconnect current BSSID + + Arguments: + pAd - Pointer to our adapter + ApCliIdx - Which ApCli interface + Return Value: + None + + Note: + + ========================================================================== +*/ +VOID ApCliLinkDown( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex) +{ + PAPCLI_STRUCT pApCliEntry = NULL; + MAC_TABLE_ENTRY *pEntry; + UCHAR P2pIdx = P2P_NOT_FOUND; + UCHAR BBPValue = 0; + + if (ifIndex < MAX_APCLI_NUM) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! APCLI LINK DOWN - IF(apcli%d)!!!\n", ifIndex)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! ERROR : APCLI LINK DOWN - IF(apcli%d)!!!\n", ifIndex)); + return; + } + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + if (pApCliEntry->Valid == FALSE) + return; + + /* Find the p2p Entry and change the p2p State. */ + if (pApCliEntry->bP2pClient) + { + NdisZeroMemory(pAd->ApCfg.ApCliTab[0].CfgApCliBssid, MAC_ADDR_LEN); + pEntry = &pAd->MacTab.Content[pApCliEntry->MacTabWCID]; + P2pIdx = P2pGroupTabSearch(pAd, pEntry->Addr); + + if ((P2P_CLI_ON(pAd)) && (IS_ENTRY_APCLI(pEntry)) && + (pEntry->WpaState == AS_PTKINITDONE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Secured = %d. Addr = %02x:%02x:%02x:%02x:%02x:%02x.\n", + __FUNCTION__, pEntry->PortSecured, PRINT_MAC(pEntry->Addr))); + if (P2pIdx != P2P_NOT_FOUND) + pAd->P2pTable.Client[P2pIdx].P2pClientState = P2PSTATE_DISCOVERY; + if (pAd->P2pCfg.bP2pCliReConnect == FALSE) + P2pLinkDown(pAd, P2P_DISCONNECTED); + else + { + pAd->P2pCfg.bP2pCliReConnectTimerRunning = TRUE; + RTMPSetTimer(&pAd->P2pCfg.P2pCliReConnectTimer, P2P_CHECK_CLIENT_TIMER); + } +#ifdef DPA_S + RtmpOSWrielessEventSend(pAd->p2p_dev, RT_WLAN_EVENT_CUSTOM, P2P_NOTIF_LINK_LOSS, NULL, NULL, 0); +#endif /* DPA_S */ + } + } + + if ((INFRA_ON(pAd)) && (pAd->StaActive.SupportedHtPhy.ChannelWidth == BW_40)) + { + + } + else + { + pAd->CommonCfg.BBPCurrentBW = BW_20; + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + } + + pAd->ApCfg.ApCliInfRunned--; + MacTableDeleteEntry(pAd, pApCliEntry->MacTabWCID, APCLI_ROOT_BSSID_GET(pAd, pApCliEntry->MacTabWCID)); + + /* Clean Bss Search Table. */ + DBGPRINT(RT_DEBUG_TRACE, ("\n++++++++ %s:: Delete BssSearch Table on Channel = %d. ++++++++\n", __FUNCTION__, pAd->CommonCfg.Channel)); + DBGPRINT(RT_DEBUG_TRACE, (" BSSID = [%02x:%02x:%02x:%02x:%02x:%02x]. p2p_bssid = [%02x:%02x:%02x:%02x:%02x:%02x].\n", PRINT_MAC(pApCliEntry->ApCliMlmeAux.Bssid), PRINT_MAC(pAd->P2pCfg.Bssid))); + BssTableDeleteEntry(&pAd->ScanTab, + /*pAd->ApCliMlmeAux.Bssid*/pAd->P2pCfg.Bssid, + pAd->CommonCfg.Channel); + pApCliEntry->Valid = FALSE; /* This link doesn't associated with any remote-AP */ + +} + +/* + ========================================================================== + Description: + APCLI Interface Up. + ========================================================================== + */ +VOID ApCliIfUp( + IN PRTMP_ADAPTER pAd) +{ + UCHAR ifIndex; + PAPCLI_STRUCT pApCliEntry; + + /* 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(ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + if (APCLI_IF_UP_CHECK(pAd, ifIndex) + && (pApCliEntry->Enable == TRUE) + && (pApCliEntry->Valid == FALSE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) ApCli interface[%d] startup.\n", __FUNCTION__, ifIndex)); + COPY_MAC_ADDR(pApCliEntry->CfgApCliBssid, pAd->P2pCfg.Bssid); + DBGPRINT(RT_DEBUG_TRACE, ("SSID = [%s]. BSSID = [%02x:%02x:%02x:%02x:%02x:%02x].\n", pApCliEntry->CfgSsid, PRINT_MAC(pApCliEntry->CfgApCliBssid))); + if (pAd->ApCfg.ApCliTab[0].CtrlCurrState == APCLI_CTRL_DISCONNECTED) + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_JOIN_REQ, 0, NULL, ifIndex); + } + } + + return; +} + + +/* + ========================================================================== + Description: + APCLI Interface Down. + ========================================================================== + */ +VOID ApCliIfDown( + IN PRTMP_ADAPTER pAd) +{ + UCHAR ifIndex; + PAPCLI_STRUCT pApCliEntry; + + for(ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + DBGPRINT(RT_DEBUG_TRACE, ("(%s) ApCli interface[%d] startdown.\n", __FUNCTION__, ifIndex)); + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, ifIndex); + } + + return; +} + + + +/* + ========================================================================== + Description: + APCLI Interface Monitor. + ========================================================================== + */ +VOID ApCliIfMonitor( + IN PRTMP_ADAPTER pAd) +{ + UCHAR index; + PAPCLI_STRUCT pApCliEntry; + + /* 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++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[index]; + if ((pApCliEntry->Valid == TRUE) + && (RTMP_TIME_AFTER(pAd->Mlme.Now32 , (pApCliEntry->ApCliRcvBeaconTime + (4 * OS_HZ))))) + { + DBGPRINT(RT_DEBUG_TRACE, ("ApCliIfMonitor: IF(apcli%d) - no Beancon is received from root-AP.\n", index)); + DBGPRINT(RT_DEBUG_TRACE, ("ApCliIfMonitor: Reconnect the Root-Ap again.\n")); + 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 == BTYPE_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_ENROLLEE) + { + *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 == BTYPE_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 == BTYPE_MGMT) + { + switch (pFrame->Hdr.FC.SubType) + { + /* Beacon must be processed be 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 ULONG *P2PSubelementLen, + OUT PUCHAR pP2pSubelement, + 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) +{ + CHAR IeType, *Ptr; + PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; + PEID_STRUCT pEid; + ULONG Length = 0; + UCHAR P2POUIBYTE[4] = {0x50, 0x6f, 0x9a, 0x9}; + + *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, ("PeerAssocRspSanity fail - wrong SupportedRates IE\n")); + 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, ("PeerAssocRspSanity - wrong IE_HT_CAP. \n")); + } + + 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, ("PeerAssocRspSanity - wrong IE_ADD_HT. \n")); + } + break; + case IE_SECONDARY_CH_OFFSET: + if (pEid->Len == 1) + { + *pNewExtChannelOffset = pEid->Octet[0]; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n")); + } + break; +#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 */ + } + } + if (NdisEqualMemory(pEid->Octet, P2POUIBYTE, sizeof(P2POUIBYTE)) && (pEid->Len >= 4)) + { + if (*P2PSubelementLen == 0) + { + RTMPMoveMemory(pP2pSubelement, &pEid->Eid, (pEid->Len+2)); + *P2PSubelementLen = (pEid->Len+2); + } + else if (*P2PSubelementLen > 0) + { + RTMPMoveMemory(pP2pSubelement + *P2PSubelementLen, &pEid->Eid, (pEid->Len+2)); + *P2PSubelementLen += (pEid->Len+2); + } + DBGPRINT(RT_DEBUG_ERROR, (" ! ===>P2P - %s P2P IE Len becomes = %ld.\n", __FUNCTION__, *P2PSubelementLen)); + } + break; + default: + DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspSanity - ignore unrecognized EID = %d\n", pEid->Eid)); + break; + } + + Length = Length + 2 + pEid->Len; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + return TRUE; +} + + +MAC_TABLE_ENTRY *ApCliTableLookUpByWcid( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid, + IN PUCHAR pAddrs) +{ + /*USHORT HashIdx; */ + ULONG ApCliIndex; + PMAC_TABLE_ENTRY pCurEntry = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + + if (wcid <=0 || wcid >= MAX_LEN_OF_MAC_TABLE ) + return NULL; + + NdisAcquireSpinLock(&pAd->MacTabLock); + + do + { + pCurEntry = &pAd->MacTab.Content[wcid]; + + ApCliIndex = 0xff; + if ((pCurEntry) && IS_ENTRY_APCLI(pCurEntry)) + { + ApCliIndex = pCurEntry->MatchAPCLITabIdx; + } + + 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 WDS Entry is valid or not. + ========================================================================== + */ +static inline BOOLEAN ValidApCliEntry( + IN PRTMP_ADAPTER pAd, + IN 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; +} + + +BOOLEAN ApCliAllowToSendPacket( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + OUT UCHAR *pWcid) +{ + UCHAR apCliIdx; + BOOLEAN allowed; + + /*DBGPRINT(RT_DEBUG_TRACE, ("ApCliAllowToSendPacket():Packet to ApCli interface!\n")); */ + apCliIdx = RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_APCLI; + if (ValidApCliEntry(pAd, apCliIdx)) + { + /*DBGPRINT(RT_DEBUG_TRACE, ("ApCliAllowToSendPacket(): Set the WCID as %d!\n", pAd->ApCfg.ApCliTab[apCliIdx].MacTabWCID)); */ + + *pWcid = pAd->ApCfg.ApCliTab[apCliIdx].MacTabWCID; + /*RTMP_SET_PACKET_WCID(pPacket, pAd->ApCfg.ApCliTab[apCliIdx].MacTabWCID); *//* to ApClient links. */ + + allowed = TRUE; + } + else + { + allowed = FALSE; + } + + 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 PRTMP_ADAPTER pAd, + IN PEID_STRUCT pEid_ptr, + IN USHORT eid_len, + IN USHORT idx) +{ + PUCHAR pVIE; + PUCHAR 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; + + 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_11Encryption1Enabled; + break; + case 2: + WPA.GroupCipher = Ndis802_11Encryption2Enabled; + break; + case 4: + WPA.GroupCipher = Ndis802_11Encryption3Enabled; + 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_11Encryption1Enabled; + break; + case 2: + TmpCipher = Ndis802_11Encryption2Enabled; + break; + case 4: + TmpCipher = Ndis802_11Encryption3Enabled; + 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_11Encryption1Enabled; + break; + case 2: + WPA2.GroupCipher = Ndis802_11Encryption2Enabled; + break; + case 4: + WPA2.GroupCipher = Ndis802_11Encryption3Enabled; + 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_11Encryption1Enabled; + break; + case 2: + TmpCipher = Ndis802_11Encryption2Enabled; + break; + case 4: + TmpCipher = Ndis802_11Encryption3Enabled; + 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]; + + /* Peer AP doesn't include WPA/WPA2 capable */ + if (Sanity == 0) + { + /* Check the authenticaton mode */ + if (pApCliEntry->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; + } + } + + /* Recovery user-defined cipher suite */ + pApCliEntry->PairCipher = pApCliEntry->WepStatus; + pApCliEntry->GroupCipher = pApCliEntry->WepStatus; + pApCliEntry->bMixCipher = FALSE; + + Sanity = 0; + + /* Check AuthMode and WPA_AuthModeAux for matching, in case AP support dual-AuthMode */ + /* WPAPSK */ + if ((WPA_AuthMode == pApCliEntry->AuthMode) || + ((WPA_AuthModeAux != Ndis802_11AuthModeOpen) && (WPA_AuthModeAux == pApCliEntry->AuthMode))) + { + /* Check cipher suite, AP must have more secured cipher than station setting */ + if (WPA.bMixMode == FALSE) + { + if (pApCliEntry->WepStatus != WPA.GroupCipher) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA validate cipher suite error \n")); + return FALSE; + } + } + + /* check group cipher */ + if (pApCliEntry->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 ((pApCliEntry->WepStatus == Ndis802_11Encryption2Enabled) && + (pApCliEntry->WepStatus != WPA.PairCipher) && + (pApCliEntry->WepStatus != WPA.PairCipherAux)) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA validate pairwise cipher error \n")); + return FALSE; + } + + Sanity |= 0x1; + } + /* WPA2PSK */ + else if ((WPA2_AuthMode == pApCliEntry->AuthMode) || + ((WPA2_AuthModeAux != Ndis802_11AuthModeOpen) && (WPA2_AuthModeAux == pApCliEntry->AuthMode))) + { + /* Check cipher suite, AP must have more secured cipher than station setting */ + if (WPA2.bMixMode == FALSE) + { + if (pApCliEntry->WepStatus != WPA2.GroupCipher) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA2 validate cipher suite error \n")); + return FALSE; + } + } + + /* check group cipher */ + if (pApCliEntry->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 ((pApCliEntry->WepStatus == Ndis802_11Encryption2Enabled) && + (pApCliEntry->WepStatus != WPA2.PairCipher) && + (pApCliEntry->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 ((pApCliEntry->AuthMode == Ndis802_11AuthModeWPA) || (pApCliEntry->AuthMode == Ndis802_11AuthModeWPAPSK)) + { + pApCliEntry->GroupCipher = WPA.GroupCipher; + + if (pApCliEntry->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_11Encryption2Enabled; + } + else if ((pApCliEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pApCliEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + pApCliEntry->GroupCipher = WPA2.GroupCipher; + + if (pApCliEntry->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_11Encryption2Enabled; + } + + /* 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, pApCliEntry->AuthMode, pApCliEntry->WepStatus, (idx + MIN_NET_DEVICE_FOR_APCLI)); + + return TRUE; +} + +BOOLEAN ApCliHandleRxBroadcastFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR FromWhichBSSID) +{ + PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); + PHEADER_802_11 pHeader = pRxBlk->pHeader; + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; + PAPCLI_STRUCT pApCliEntry = NULL; + + /* It is possible to receive the multicast packet when in AP Client mode */ + /* Such as a broadcast from remote AP to AP-client, address1 is ffffff, address2 is remote AP's bssid, addr3 is sta4 mac address */ + + pApCliEntry = &pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx]; + + /* 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 */ + if (MAC_ADDR_EQUAL(pHeader->Addr3, pApCliEntry->CurrentAddress)) + return FALSE; /* give up this frame */ + + if (pEntry->PrivacyFilter != Ndis802_11PrivFilterAcceptAll) + return FALSE; /* give up this frame */ + + + /* skip the 802.11 header */ + 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 ((pRxD->MyBss == 0) && (pRxD->Decrypted == 0) && (pHeader->FC.Wep == 1)) + { + if (RTMPSoftDecryptionAction(pAd, + (PUCHAR)pHeader, 0, + &pApCliEntry->SharedKey[pRxWI->KeyIndex], + pRxBlk->pData, + &(pRxBlk->DataSize)) == NDIS_STATUS_FAILURE) + { + return FALSE; /* give up this frame */ + } + } + pRxD->MyBss = 1; + 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->MatchAPCLITabIdx; + + BssIdx = pAd->ApCfg.BssidNum + MAX_MESH_NUM + IfIdx; + + 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; + + if (!pEntry || !IS_ENTRY_APCLI(pEntry)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : This Entry doesn't exist!!! \n", __FUNCTION__)); + return FALSE; + } + + IfIdx = pEntry->MatchAPCLITabIdx; + + if (pAd->ApCfg.ApCliTab[IfIdx].GroupCipher == Ndis802_11Encryption2Enabled && KeyLen >= LEN_TKIP_GTK) + { + GTK_len = LEN_TKIP_GTK; + } + else if (pAd->ApCfg.ApCliTab[IfIdx].GroupCipher == Ndis802_11Encryption3Enabled && + KeyLen >= LEN_AES_GTK) + { + GTK_len = LEN_AES_GTK; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : GTK is invalid (GroupCipher=%d, DataLen=%d) !!! \n", + __FUNCTION__, pAd->ApCfg.ApCliTab[IfIdx].GroupCipher, KeyLen)); + return FALSE; + } + + /* Update GTK */ + /* set key material, TxMic and RxMic for WPAPSK */ + NdisMoveMemory(pAd->ApCfg.ApCliTab[IfIdx].GTK, pKey, GTK_len); + pAd->ApCfg.ApCliTab[IfIdx].DefaultKeyId = DefaultKeyIdx; + + /* Update shared key table */ + NdisZeroMemory(&pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx], sizeof(CIPHER_KEY)); + pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx].KeyLen = GTK_len; + NdisMoveMemory(pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx].Key, pKey, LEN_TK); + if (GTK_len == LEN_TKIP_GTK) + { + NdisMoveMemory(pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx].RxMic, pKey + 16, LEN_TKIP_MIC); + NdisMoveMemory(pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx].TxMic, pKey + 24, LEN_TKIP_MIC); + } + + /* Update Shared Key CipherAlg */ + pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx].CipherAlg = CIPHER_NONE; + if (pAd->ApCfg.ApCliTab[IfIdx].GroupCipher == Ndis802_11Encryption2Enabled) + pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx].CipherAlg = CIPHER_TKIP; + else if (pAd->ApCfg.ApCliTab[IfIdx].GroupCipher == Ndis802_11Encryption3Enabled) + pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx].CipherAlg = CIPHER_AES; + + return TRUE; +} + +VOID APCli_Init( + IN PRTMP_ADAPTER pAd, + IN RTMP_OS_NETDEV_OP_HOOK *pNetDevOps) +{ +#define APCLI_MAX_DEV_NUM 32 + PNET_DEV new_dev_p; +/* VIRTUAL_ADAPTER *apcli_pAd; */ + INT apcli_index; +/* RTMP_OS_NETDEV_OP_HOOK netDevOpHook; */ + APCLI_STRUCT *pApCliEntry; + + /* sanity check to avoid redundant virtual interfaces are created */ + if (pAd->flg_apcli_init != FALSE) + return; + + + /* init */ + for(apcli_index = 0; apcli_index < MAX_APCLI_NUM; apcli_index++) + pAd->ApCfg.ApCliTab[apcli_index].dev = NULL; + + /* create virtual network interface */ + for(apcli_index = 0; apcli_index < MAX_APCLI_NUM; apcli_index++) + { + UINT32 MC_RowID = 0, IoctlIF = 0; +#ifdef MULTIPLE_CARD_SUPPORT + MC_RowID = pAd->MC_RowID; +#endif /* MULTIPLE_CARD_SUPPORT */ +#ifdef HOSTAPD_SUPPORT + IoctlIF = pAd->IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + new_dev_p = RtmpOSNetDevCreate(MC_RowID, &IoctlIF, INT_APCLI, apcli_index, sizeof(PRTMP_ADAPTER), INF_APCLI_DEV_NAME); +#ifdef HOSTAPD_SUPPORT + pAd->IoctlIF = IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + RTMP_OS_NETDEV_SET_PRIV(new_dev_p, pAd); + + pApCliEntry = &pAd->ApCfg.ApCliTab[apcli_index]; + /* init MAC address of virtual network interface */ + COPY_MAC_ADDR(pApCliEntry->CurrentAddress, pAd->CurrentAddress); + + if (pAd->chipCap.MBSSIDMode == MBSSID_MODE1) + { + if (pAd->ApCfg.BssidNum > 0 || MAX_MESH_NUM > 0) + { + /* + 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. + */ + pApCliEntry->CurrentAddress[0] += 2; + pApCliEntry->CurrentAddress[0] += (((pAd->ApCfg.BssidNum + MAX_MESH_NUM) - 1) << 2); + } + } + else + { + pApCliEntry->CurrentAddress[ETH_LENGTH_OF_ADDRESS - 1] = + (pApCliEntry->CurrentAddress[ETH_LENGTH_OF_ADDRESS - 1] + pAd->ApCfg.BssidNum + MAX_MESH_NUM) & 0xFF; + } + + + pNetDevOps->priv_flags = INT_APCLI; /* we are virtual interface */ + pNetDevOps->needProtcted = TRUE; + NdisMoveMemory(pNetDevOps->devAddr, &pApCliEntry->CurrentAddress[0], MAC_ADDR_LEN); + + /* register this device to OS */ + RtmpOSNetDevAttach(pAd->OpMode, new_dev_p, pNetDevOps); + + /* backup our virtual network interface */ + pApCliEntry->dev = new_dev_p; + +#ifdef WSC_AP_SUPPORT + pApCliEntry->WscControl.pAd = pAd; + NdisZeroMemory(pApCliEntry->WscControl.EntryAddr, MAC_ADDR_LEN); + pApCliEntry->WscControl.WscConfigMethods= 0x018C; +/* WscGenerateUUID(pAd, &pApCliEntry->WscControl.Wsc_Uuid_E[0], &pApCliEntry->WscControl.Wsc_Uuid_Str[0], 0, FALSE); */ +/* WscInit(pAd, TRUE, apcli_index); */ + RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_WSC_INIT, 0, (VOID *)pApCliEntry, apcli_index); +#endif /* WSC_AP_SUPPORT */ + } /* End of for */ + + pAd->flg_apcli_init = TRUE; + +} + + +VOID ApCli_Remove( + IN PRTMP_ADAPTER pAd) +{ + UINT index; + + for(index = 0; index < MAX_APCLI_NUM; index++) + { + if (pAd->ApCfg.ApCliTab[index].dev) + { + RtmpOSNetDevDetach(pAd->ApCfg.ApCliTab[index].dev); + + RtmpOSNetDevFree(pAd->ApCfg.ApCliTab[index].dev); + + /* Clear it as NULL to prevent latter access error. */ + pAd->flg_apcli_init = FALSE; + pAd->ApCfg.ApCliTab[index].dev = NULL; + } + } +} + + +BOOLEAN ApCli_Open( + IN PRTMP_ADAPTER pAd, + IN PNET_DEV dev_p) +{ + UCHAR ifIndex; + + + for (ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) + { + if (pAd->ApCfg.ApCliTab[ifIndex].dev == dev_p) + { + RTMP_OS_NETDEV_START_QUEUE(dev_p); + ApCliIfUp(pAd); + return TRUE; + } + } + + return FALSE; +} /* End of ApCli_Open */ + + +BOOLEAN ApCli_Close( + IN PRTMP_ADAPTER pAd, + IN PNET_DEV dev_p) +{ + UCHAR ifIndex; + + + for (ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) + { + if (pAd->ApCfg.ApCliTab[ifIndex].dev == dev_p) + { + RTMP_OS_NETDEV_STOP_QUEUE(dev_p); + + /* send disconnect-req to sta State Machine. */ + if (pAd->ApCfg.ApCliTab[ifIndex].Enable) + { + 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; +} /* End of ApCli_Close */ + + +int APC_PacketSend( + IN PNDIS_PACKET skb_p, + IN PNET_DEV dev_p, + IN RTMP_NET_PACKET_TRANSMIT Func) +{ + RTMP_ADAPTER *pAd; + PAPCLI_STRUCT pApCli; + INT apcliIndex; + + + + pAd = RTMP_OS_NETDEV_GET_PRIV(dev_p); + ASSERT(pAd); + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + RELEASE_NDIS_PACKET(pAd, skb_p, NDIS_STATUS_FAILURE); + return 0; + } +#endif /* RALINK_ATE */ + + if ((RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))) + { + /* wlan is scanning/disabled/reset */ + RELEASE_NDIS_PACKET(pAd, skb_p, NDIS_STATUS_FAILURE); + return 0; + } + + + pApCli = (PAPCLI_STRUCT)&pAd->ApCfg.ApCliTab; + + for(apcliIndex = 0; apcliIndex < MAX_APCLI_NUM; apcliIndex++) + { + if (pApCli[apcliIndex].Valid != TRUE) + continue; + + /* find the device in our ApCli list */ + if (pApCli[apcliIndex].dev == dev_p) + { + /* ya! find it */ + pAd->RalinkCounters.PendingNdisPacketCount ++; + RTMP_SET_PACKET_SOURCE(skb_p, PKTSRC_NDIS); + RTMP_SET_PACKET_MOREDATA(skb_p, FALSE); + RTMP_SET_PACKET_NET_DEVICE_APCLI(skb_p, apcliIndex); + SET_OS_PKT_NETDEV(skb_p, pAd->net_dev); + + + /* transmit the packet */ + return Func(skb_p); + } + } + + RELEASE_NDIS_PACKET(pAd, skb_p, NDIS_STATUS_FAILURE); + + return 0; +} + +#endif /* P2P_SUPPORT */ + diff --git a/mt7620/src/sta/p2pcli_assoc.c b/mt7620/src/sta/p2pcli_assoc.c new file mode 100644 index 0000000..8faedad --- /dev/null +++ b/mt7620/src/sta/p2pcli_assoc.c @@ -0,0 +1,789 @@ +/* + *************************************************************************** + * 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 P2P_SUPPORT + +#include "rt_config.h" + +static VOID ApCliAssocTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +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); + +/* + ========================================================================== + 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; + + 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; + RTMPInitTimer(pAd, &pAd->ApCfg.ApCliTab[i].ApCliMlmeAux.ApCliAssocTimer, + GET_TIMER_FUNCTION(ApCliAssocTimeout), pAd, FALSE); + } + + 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; +} + +/* + ========================================================================== + 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->PortCfg.default_listen_count) + -# Transmit power (Adapter->PortCfg.tx_power) + 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 = &pAd->ApCfg.ApCliTab[ifIndex].AssocCurrState; + PAPCLI_STRUCT pApCliEntry = NULL; + + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + /* Block all authentication request durning WPA block period */ + if (pApCliEntry->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(&pApCliEntry->ApCliMlmeAux.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); + + /* Build basic frame first */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &AssocHdr, + 2, &CapabilityInfo, + 2, &ListenIntv, + 1, &SsidIe, + 1, &pApCliEntry->ApCliMlmeAux.SsidLen, + pApCliEntry->ApCliMlmeAux.SsidLen, pApCliEntry->ApCliMlmeAux.Ssid, + 1, &SupRateIe, + 1, &pApCliEntry->ApCliMlmeAux.SupRateLen, + pApCliEntry->ApCliMlmeAux.SupRateLen, pApCliEntry->ApCliMlmeAux.SupRate, + END_OF_ARGS); + + if(pApCliEntry->ApCliMlmeAux.ExtRateLen != 0) + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &pApCliEntry->ApCliMlmeAux.ExtRateLen, + pApCliEntry->ApCliMlmeAux.ExtRateLen, pApCliEntry->ApCliMlmeAux.ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + +#ifdef DOT11_N_SUPPORT + /* HT */ + if ((pApCliEntry->ApCliMlmeAux.HtCapabilityLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + ULONG TmpLen; + //UCHAR HtLen; */ + //UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; */ +/* 2008/12/17:KH modified to fix the low throughput of AP-Client on Big-Endian Platform<-- */ +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; +#endif + +#ifndef RT_BIG_ENDIAN + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &pApCliEntry->ApCliMlmeAux.HtCapabilityLen, pApCliEntry->ApCliMlmeAux.HtCapabilityLen, &pApCliEntry->ApCliMlmeAux.HtCapability, + END_OF_ARGS); + } +#else + NdisZeroMemory(&HtCapabilityTmp, sizeof(HT_CAPABILITY_IE)); + NdisMoveMemory(&HtCapabilityTmp, &pApCliEntry->ApCliMlmeAux.HtCapability, pApCliEntry->ApCliMlmeAux.HtCapabilityLen); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &pApCliEntry->ApCliMlmeAux.HtCapabilityLen, + pApCliEntry->ApCliMlmeAux.HtCapabilityLen, &HtCapabilityTmp, + END_OF_ARGS); +#endif +/* 2008/12/17:KH modified to fix the low throughput of AP-Client on Big-Endian Platform--> */ + FrameLen += TmpLen; + } +#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) && ((pApCliEntry->ApCliMlmeAux.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 (pApCliEntry->ApCliMlmeAux.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 (pApCliEntry->ApCliMlmeAux.APEdcaParm.bValid) + { + if (pApCliEntry->UapsdInfo.bAPSDCapable && + pApCliEntry->ApCliMlmeAux.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; + } + + /* Append RSN_IE when WPAPSK OR WPA2PSK, */ + if (((pApCliEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || + (pApCliEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) +#ifdef WSC_AP_SUPPORT + && (pApCliEntry->WscControl.WscConfMode == WSC_DISABLE) +#endif /* WSC_AP_SUPPORT */ + ) + { + UCHAR RSNIe = IE_WPA; + + if (pApCliEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) + RSNIe = IE_WPA2; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &RSNIe, + 1, &pApCliEntry->RSNIE_Len, + pApCliEntry->RSNIE_Len, pApCliEntry->RSN_IE, + END_OF_ARGS); + + FrameLen += tmp; + } + +#ifdef WSC_AP_SUPPORT + if (pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode != WSC_DISABLE) + { + UCHAR *pWscBuf = NULL, WscIeLen = 0; + ULONG WscTmpLen = 0; + + 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 P2P_SUPPORT + if (P2P_CLI_ON(pAd)) + { + ULONG TmpLen; + PUCHAR pData; + pData = pOutBuffer + FrameLen; + P2pMakeP2pIE(pAd, SUBTYPE_ASSOC_REQ, pData, &TmpLen); + FrameLen += TmpLen; + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC RSP - Insert P2P IE \n")); + } +#endif /* P2P_SUPPORT */ + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + RTMPSetTimer(&pApCliEntry->ApCliMlmeAux.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); + if (ifIndex >= MAX_APCLI_NUM) + return; + PULONG 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; + 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); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DisassocHdr, + 2, &pDisassocReq->Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + /* Set the control aux SSID to prevent it reconnect to old SSID */ + /* Since calling this indicate user don't want to connect to that SSID anymore. */ + /* 2004-11-10 can't reset this info, cause it may be the new SSID that user requests for */ + /* pAd->MlmeAux.SsidLen = MAX_LEN_OF_SSID; */ + /* NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); */ + /* NdisZeroMemory(pAd->MlmeAux.Bssid, MAC_ADDR_LEN); */ + + //pAd->PortCfg.DisassocReason = REASON_DISASSOC_STA_LEAVING; */ + //COPY_MAC_ADDR(pAd->PortCfg.DisassocSta, pDisassocReq->Addr); */ + + + *pCurrState = APCLI_ASSOC_IDLE; + + ApCliCtrlMsg.Status = MLME_SUCCESS; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DEASSOC_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + + 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); + if (ifIndex >= MAX_APCLI_NUM) + return; + PULONG pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AssocCurrState; + PAPCLI_STRUCT pApCliEntry = NULL; + ULONG P2PSubelementLen = 0; + UCHAR *P2pSubelement; + + os_alloc_mem(NULL, (UCHAR **)&P2pSubelement, MAX_VIE_LEN); + + if (ApCliPeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, &Aid, &P2PSubelementLen, P2pSubelement, SupRate, &SupRateLen, ExtRate, &ExtRateLen, + &HtCapability, &AddHtInfo, &HtCapabilityLen,&AddHtInfoLen,&NewExtChannelOffset, &EdcaParm, &CkipFlag)) + { + /* The frame is for me ? */ + if(MAC_ADDR_EQUAL(Addr2, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid)) + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - receive ASSOC_RSP to me (status=%d)\n", Status)); + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.ApCliAssocTimer, &Cancelled); + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + if (P2PSubelementLen > 0) + { + /*UCHAR P2pIdx = P2P_NOT_FOUND; + ULONG TmpLen; + PUCHAR pData;*/ + pApCliEntry->bP2pClient = TRUE; + } + else + pApCliEntry->bP2pClient = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: recv peer ASSOC RSP from %02x:%02x:%02x:%02x:%02x:%02x. bP2pClient = %d\n", __FUNCTION__, PRINT_MAC(Addr2), pApCliEntry->bP2pClient)); + + if(Status == MLME_SUCCESS) + { +#ifdef DPA_S +#ifdef P2P_SUPPORT + UCHAR p2pIndex = P2P_NOT_FOUND; + + p2pIndex = P2pGroupTabSearch(pAd, pAd->ApCliMlmeAux.Bssid); + if (p2pIndex != P2P_NOT_FOUND) + { + PRT_P2P_CLIENT_ENTRY pP2pEntry = &pAd->P2pTable.Client[p2pIndex]; + P2pSendSamsungEvent(pAd, P2P_NOTIF_SOFTAP_STA_ASSOC, pAd->ApCliMlmeAux.Bssid, pP2pEntry->DeviceName, pP2pEntry->DeviceNameLen); + } + else + P2pSendSamsungEvent(pAd, P2P_NOTIF_SOFTAP_STA_ASSOC, pAd->ApCliMlmeAux.Bssid, NULL, 0); +#endif /* P2P_SUPPORT */ +#endif /* DPA_S */ + /* go to procedure listed on page 376 */ + ApCliAssocPostProc(pAd, Addr2, CapabilityInfo, ifIndex, SupRate, SupRateLen, + ExtRate, ExtRateLen, &EdcaParm, &HtCapability, HtCapabilityLen, &AddHtInfo); + + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Aid=Aid; + + ApCliCtrlMsg.Status = MLME_SUCCESS; + 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 (P2pSubelement != NULL) + os_free_mem(NULL, P2pSubelement); + 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); + if ((ifIndex >= MAX_APCLI_NUM) + ) + return; + PULONG pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AssocCurrState; + + if(PeerDisassocSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason)) + { + if (MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, Addr2)) + { +#ifdef DPA_S +#ifdef P2P_SUPPORT + UCHAR p2pIndex = P2P_NOT_FOUND; +#endif /* P2P_SUPPORT */ +#endif /* DPA_S */ + + *pCurrState = APCLI_ASSOC_IDLE; + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_PEER_DISCONNECT_REQ, 0, NULL, ifIndex); + +#ifdef DPA_S +#ifdef P2P_SUPPORT + p2pIndex = P2pGroupTabSearch(pAd, Addr2); + if (p2pIndex != P2P_NOT_FOUND) + { + PRT_P2P_CLIENT_ENTRY pP2pEntry = &pAd->P2pTable.Client[p2pIndex]; + P2pSendSamsungEvent(pAd, P2P_NOTIF_SOFTAP_STA_DISASSOC, Addr2, pP2pEntry->DeviceName, pP2pEntry->DeviceNameLen); + } + else + P2pSendSamsungEvent(pAd, P2P_NOTIF_SOFTAP_STA_DISASSOC, Addr2, NULL, 0); +#endif /* P2P_SUPPORT */ +#endif /* DPA_S */ + } + } + 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 = &pAd->ApCfg.ApCliTab[ifIndex].AssocCurrState; + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - ApCliAssocTimeoutAction\n")); + if ((ifIndex >= MAX_APCLI_NUM) + ) + return; + *pCurrState = APCLI_ASSOC_IDLE; + + 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); + if ((ifIndex >= MAX_APCLI_NUM) + ) + return; + PULONG 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; + 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); + if ((ifIndex >= MAX_APCLI_NUM) + ) + return; + PULONG 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; + 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) +{ + PAPCLI_STRUCT pApCliEntry = NULL; + + if (IfIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[IfIndex]; + + + pApCliEntry->ApCliMlmeAux.BssType = BSS_INFRA; + pApCliEntry->ApCliMlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; + NdisMoveMemory(&pApCliEntry->ApCliMlmeAux.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM)); + + /* filter out un-supported rates */ + pApCliEntry->ApCliMlmeAux.SupRateLen = SupRateLen; + NdisMoveMemory(pApCliEntry->ApCliMlmeAux.SupRate, SupRate, SupRateLen); + RTMPCheckRates(pAd, pApCliEntry->ApCliMlmeAux.SupRate, &(pApCliEntry->ApCliMlmeAux.SupRateLen)); + + /* filter out un-supported rates */ + pApCliEntry->ApCliMlmeAux.ExtRateLen = ExtRateLen; + NdisMoveMemory(pApCliEntry->ApCliMlmeAux.ExtRate, ExtRate, ExtRateLen); + RTMPCheckRates(pAd, pApCliEntry->ApCliMlmeAux.ExtRate, &(pApCliEntry->ApCliMlmeAux.ExtRateLen)); + + DBGPRINT(RT_DEBUG_TRACE, (HtCapabilityLen ? "%s===> 11n HT STA\n" : "%s===> legacy STA\n", __FUNCTION__)); + +#ifdef DOT11_N_SUPPORT + if (HtCapabilityLen > 0 && (pAd->CommonCfg.PhyMode > PHY_11ABGN_MIXED)) + { + ApCliCheckHt(pAd, IfIndex, pHtCapability, pAddHtInfo); + } +#endif /* DOT11_N_SUPPORT */ + +} + +#endif /* P2P_SUPPORT */ + diff --git a/mt7620/src/sta/p2pcli_auth.c b/mt7620/src/sta/p2pcli_auth.c new file mode 100644 index 0000000..e803628 --- /dev/null +++ b/mt7620/src/sta/p2pcli_auth.c @@ -0,0 +1,552 @@ +/* + *************************************************************************** + * 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 + -------- ---------- ---------------------------------------------- + Fonchi 2006-6-23 modified for rt61-APClinent +*/ + +#ifdef P2P_SUPPORT + +#include "rt_config.h" + +static VOID ApCliAuthTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +static VOID ApCliMlmeAuthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliPeerAuthRspAtSeq2Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliPeerAuthRspAtSeq4Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliPeerDeauthAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliAuthTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliInvalidStateWhenAuth( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliMlmeDeauthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +DECLARE_TIMER_FUNCTION(ApCliAuthTimeout); +BUILD_TIMER_FUNCTION(ApCliAuthTimeout); + +/* + ========================================================================== + 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 PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + UCHAR i; + + 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].ApCliMlmeAux.ApCliAuthTimer, GET_TIMER_FUNCTION(ApCliAuthTimeout), pAd, FALSE); + } + + return; +} + +/* + ========================================================================== + 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, ("APCLI AUTH - AuthTimeout\n")); + + MlmeEnqueue(pAd, APCLI_AUTH_STATE_MACHINE, APCLI_MT2_AUTH_TIMEOUT, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); + + return; +} + +/* + ========================================================================== + 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 = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState; + + if (ifIndex >= MAX_APCLI_NUM) + return; + + /* 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; + 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)) + { + /* reset timer */ + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.ApCliAuthTimer, &Cancelled); + + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Alg = Alg; + + Seq = 1; + Status = MLME_SUCCESS; + + /* allocate and send out AuthReq frame */ + NState = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory */ + if(NState != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - MlmeAuthReqAction() allocate memory failed\n")); + *pCurrState = APCLI_AUTH_REQ_IDLE; + + ApCliCtrlMsg.Status = MLME_FAIL_NO_RESOURCE; + 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].ApCliMlmeAux.Bssid, ifIndex); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11),&AuthHdr, + 2, &Alg, + 2, &Seq, + 2, &Status, + END_OF_ARGS); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + RTMPSetTimer(&pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.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( + IN PRTMP_ADAPTER pAd, + IN 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 = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState; + + if (ifIndex >= MAX_APCLI_NUM) + return; + + /* 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(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, Addr2) && Seq == 2) + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", Alg, Status)); + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.ApCliAuthTimer, &Cancelled); + + if(Status == MLME_SUCCESS) + { + if(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Alg == Ndis802_11AuthModeOpen) + { + *pCurrState = APCLI_AUTH_REQ_IDLE; + + ApCliCtrlMsg.Status= MLME_SUCCESS; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + } + else + { + PCIPHER_KEY pKey; + UINT default_key = pAd->ApCfg.ApCliTab[ifIndex].DefaultKeyId; + + pKey = &pAd->ApCfg.ApCliTab[ifIndex].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; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + goto LabelOK; + } + + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#3...\n")); + ApCliMgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr2, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, ifIndex); + AuthHdr.FC.Wep = 1; + + /* 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; + 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); + + RTMPSetTimer(&pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.ApCliAuthTimer, AUTH_TIMEOUT); + *pCurrState = APCLI_AUTH_WAIT_SEQ4; + } + } + else + { + *pCurrState = APCLI_AUTH_REQ_IDLE; + + 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 (ChlgText != NULL) + os_free_mem(NULL, ChlgText); + if (pOutBuffer != NULL) + MlmeFreeMemory(pAd, pOutBuffer); + return; +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +static VOID ApCliPeerAuthRspAtSeq4Action( + IN PRTMP_ADAPTER pAd, + IN 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 = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState; + + if (ifIndex >= MAX_APCLI_NUM) + return; + + if(PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText)) + { + if(MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, Addr2) && Seq == 4) + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - Receive AUTH_RSP seq#4 to me\n")); + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.ApCliAuthTimer, &Cancelled); + + ApCliCtrlMsg.Status = MLME_SUCCESS; + + if(Status != MLME_SUCCESS) + { + ApCliCtrlMsg.Status = Status; + } + + *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( + IN PRTMP_ADAPTER pAd, + IN 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 = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState; + + if (ifIndex >= MAX_APCLI_NUM) + return; + + 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; + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_PEER_DISCONNECT_REQ, 0, NULL, ifIndex); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH_RSP - ApCliPeerDeauthAction() sanity check fail\n")); + } + + return; +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +static VOID ApCliAuthTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState; + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - AuthTimeoutAction\n")); + + *pCurrState = APCLI_AUTH_REQ_IDLE; + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_REQ_TIMEOUT, 0, NULL, ifIndex); + + return; +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +static VOID ApCliInvalidStateWhenAuth( + 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].AuthCurrState; + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - InvalidStateWhenAuth (state=%ld), reset AUTH state machine\n", + pAd->Mlme.ApCliAuthMachine.CurrState)); + + *pCurrState= APCLI_AUTH_REQ_IDLE; + + 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 = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState; + + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - ApCliMlmeAuthReqAction (state=%ld), reset AUTH state machine\n", + pAd->Mlme.ApCliAuthMachine.CurrState)); + + 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); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11),&DeauthHdr, + 2, &pDeauthReq->Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + +#endif /* P2P_SUPPORT */ + diff --git a/mt7620/src/sta/p2pcli_ctrl.c b/mt7620/src/sta/p2pcli_ctrl.c new file mode 100644 index 0000000..8fd0ed1 --- /dev/null +++ b/mt7620/src/sta/p2pcli_ctrl.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-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 P2P_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); + +/* + ========================================================================== + 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; + + 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); + + for (i = 0; i < MAX_APCLI_NUM; i++) + pAd->ApCfg.ApCliTab[i].CtrlCurrState = APCLI_CTRL_DISCONNECTED; + + return; +} + + +/* + ========================================================================== + 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.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); + { + bss_idx = BssSsidTableSearch(&pAd->ScanTab, pAd->P2pCfg.Bssid, (PCHAR)JoinReq.Ssid, JoinReq.SsidLen, pAd->CommonCfg.Channel); + if (bss_idx == BSS_NOT_FOUND) + { + *pCurrState = APCLI_CTRL_PROBE; + ApSiteSurvey(pAd, NULL, SCAN_WSC_ACTIVE, FALSE); + return; + } + else + { + BOOLEAN Cancelled; + INT old_conf_mode = pWpsCtrl->WscConfMode, old_wsc_mode = pWpsCtrl->WscMode; + 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 (INFRA_ON(pAd) && (pAd->StaActive.SupportedHtPhy.ExtChanOffset != RootApHtInfo.ExtChanOffset) && (pAd->StaActive.SupportedHtPhy.ChannelWidth == BW_40)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s :: Channel offset = %d not match INFRA Channel offset %d .\n", + __FUNCTION__, pAd->MlmeAux.CentralChannel, RootApCentralChannel)); + P2pLinkDown(pAd, P2P_CONNECT_FAIL); + return; + } + + 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"); + } + sprintf(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 = old_wsc_mode; + pWpsCtrl->WscConfMode = old_conf_mode; + pWpsCtrl->bWscTrigger = TRUE; + return; + } + else + { + pAd->CommonCfg.Channel = pAd->ScanTab.BssEntry[bss_idx].Channel; + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + } + } + } + } + else +#endif /* WSC_AP_SUPPORT */ + if (pApCliEntry->CfgSsidLen != 0) + { + ULONG bss_idx = 0; + + bss_idx = BssSsidTableSearch(&pAd->ScanTab, JoinReq.Bssid, (PCHAR)pApCliEntry->CfgSsid, pApCliEntry->CfgSsidLen, pAd->CommonCfg.Channel); + 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; + ApSiteSurvey(pAd, NULL, SCAN_ACTIVE, FALSE); + 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)); + /* BssSearch Table has found the pEntry, send Prob Req. directly */ + pAd->CommonCfg.Channel = pAd->ScanTab.BssEntry[bss_idx].Channel; + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + JoinReq.SsidLen = pApCliEntry->CfgSsidLen; + NdisMoveMemory(&(JoinReq.Ssid), pApCliEntry->CfgSsid, JoinReq.SsidLen); + } + + if (pApCliEntry->CfgSsidLen == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s:: ApCliEntry SSID Len is 0 !!!.\n", __FUNCTION__)); + *pCurrState = APCLI_CTRL_PROBE; + ApSiteSurvey(pAd, NULL, SCAN_WSC_ACTIVE, FALSE); + return; + } + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Probe Ssid=%s, Bssid=%02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, JoinReq.Ssid, JoinReq.Bssid[0], JoinReq.Bssid[1], JoinReq.Bssid[2], + JoinReq.Bssid[3], JoinReq.Bssid[4], JoinReq.Bssid[5])); + + *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; + } + + /* 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 ((pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode != WSC_DISABLE) && + (pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger == TRUE)) + { + ULONG bss_idx = 0; + bss_idx = BssSsidTableSearchBySSID(&pAd->ScanTab, (PCHAR)JoinReq.Ssid, JoinReq.SsidLen); + if (bss_idx == BSS_NOT_FOUND) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s:: WSC exec. start SiteSurvey!\n", __FUNCTION__)); + *pCurrState = APCLI_CTRL_PROBE; + ApSiteSurvey(pAd, NULL, SCAN_WSC_ACTIVE, FALSE); + return; + } + 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); + } + else +#endif /* WSC_AP_SUPPORT */ + if (pApCliEntry->CfgSsidLen != 0) + { + ULONG bss_idx = 0; + + 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; + ApSiteSurvey(pAd, NULL, SCAN_ACTIVE, FALSE); + 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)); + /* BssSearch Table has found the pEntry, send Prob Req. directly */ + pAd->CommonCfg.Channel = pAd->ScanTab.BssEntry[bss_idx].Channel; + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + JoinReq.SsidLen = pApCliEntry->CfgSsidLen; + NdisMoveMemory(&(JoinReq.Ssid), pApCliEntry->CfgSsid, JoinReq.SsidLen); + } + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Probe Ssid=%s, Bssid=%02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, JoinReq.Ssid, JoinReq.Bssid[0], JoinReq.Bssid[1], JoinReq.Bssid[2], + JoinReq.Bssid[3], JoinReq.Bssid[4], JoinReq.Bssid[5])); + 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 = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + if (Status == MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Probe respond success.\n", __FUNCTION__)); + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Apcli-Interface Ssid=%s.\n", __FUNCTION__, pApCliEntry->Ssid)); + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Apcli-Interface Bssid=%02x:%02x:%02x:%02x:%02x:%02x.\n", __FUNCTION__, + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid[0], + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid[1], + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid[2], + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid[3], + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid[4], + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid[5])); + + *pCurrState = APCLI_CTRL_AUTH; + + pApCliEntry->AuthReqCnt = 0; + + COPY_MAC_ADDR(AuthReq.Addr, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid); + + /* start Authentication Req. */ + /* If AuthMode is Auto, try shared key first */ + if ((pAd->ApCfg.ApCliTab[ifIndex].AuthMode == Ndis802_11AuthModeShared) || + (pAd->ApCfg.ApCliTab[ifIndex].AuthMode == Ndis802_11AuthModeAutoSwitch)) + { + AuthReq.Alg = Ndis802_11AuthModeShared; + } + else + { + AuthReq.Alg = Ndis802_11AuthModeOpen; + } + + AuthReq.Timeout = AUTH_TIMEOUT; + 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; + } + + 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 = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + if(Status == MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Auth Rsp Success.\n", __FUNCTION__)); + *pCurrState = APCLI_CTRL_ASSOC; + + pApCliEntry->AssocReqCnt = 0; + + AssocParmFill(pAd, &AssocReq, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.CapabilityInfo, + ASSOC_TIMEOUT, /*pAd->PortCfg.DefaultListenCount*/5); + MlmeEnqueue(pAd, APCLI_ASSOC_STATE_MACHINE, APCLI_MT2_MLME_ASSOC_REQ, + sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq, ifIndex); + } + else + { + if (pApCliEntry->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, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid); + AuthReq.Alg = Ndis802_11AuthModeOpen; + AuthReq.Timeout = AUTH_TIMEOUT; + MlmeEnqueue(pAd, APCLI_AUTH_STATE_MACHINE, APCLI_MT2_MLME_AUTH_REQ, + sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq, ifIndex); + } else + { + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Ssid, MAX_LEN_OF_SSID); + pApCliEntry->AuthReqCnt = 0; + *pCurrState = APCLI_CTRL_DISCONNECTED; + } + } + + 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 = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + if(Status == MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Auth2 Rsp Success.\n", __FUNCTION__)); + *pCurrState = APCLI_CTRL_ASSOC; + + pApCliEntry->AssocReqCnt = 0; + + AssocParmFill(pAd, &AssocReq, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.CapabilityInfo, + ASSOC_TIMEOUT, /*pAd->PortCfg.DefaultListenCount*/5); + MlmeEnqueue(pAd, APCLI_ASSOC_STATE_MACHINE, APCLI_MT2_MLME_ASSOC_REQ, + sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq, ifIndex); + } else + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Sta Auth Rsp Failure.\n", __FUNCTION__)); + + *pCurrState = APCLI_CTRL_DISCONNECTED; + } + + 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 = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Auth Req Timeout.\n", __FUNCTION__)); + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + pApCliEntry->AuthReqCnt++; + + if (pApCliEntry->AuthReqCnt > 5) + { + *pCurrState = APCLI_CTRL_DISCONNECTED; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Ssid, MAX_LEN_OF_SSID); + pApCliEntry->AuthReqCnt = 0; + 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, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid); + AuthReq.Alg = pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Alg; /* Ndis802_11AuthModeOpen; */ + AuthReq.Timeout = AUTH_TIMEOUT; + 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 = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + if(Status == MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) apCliIf = %d, Receive Assoc Rsp Success.\n", __FUNCTION__, ifIndex)); + + if (ApCliLinkUp(pAd, ifIndex)) + { + *pCurrState = APCLI_CTRL_CONNECTED; + } + 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; + pApCliEntry->Valid = FALSE; + } + } + 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. */ + pApCliEntry->Valid = FALSE; + } + + 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 = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + + if (ifIndex >= MAX_APCLI_NUM) + return; + + 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__)); + } + + if (pApCliEntry->Valid) + 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 = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Assoc Req Timeout.\n", __FUNCTION__)); + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + /* give up to retry authentication req after retry it 5 times. */ + pApCliEntry->AssocReqCnt++; + if (pApCliEntry->AssocReqCnt > 5) + { + *pCurrState = APCLI_CTRL_DISCONNECTED; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Ssid, MAX_LEN_OF_SSID); + pApCliEntry->AuthReqCnt = 0; + 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].ApCliMlmeAux.Bssid, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.CapabilityInfo, + ASSOC_TIMEOUT, /*pAd->PortCfg.DefaultListenCount*/5); + 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 = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) MLME Request disconnect.\n", __FUNCTION__)); + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + if (pApCliEntry->Valid) + ApCliLinkDown(pAd, ifIndex); + + /* set the apcli interface be invalid. */ + pApCliEntry->Valid = FALSE; + + /* clear MlmeAux.Ssid and Bssid. */ + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, MAC_ADDR_LEN); + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.SsidLen = 0; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Ssid, MAX_LEN_OF_SSID); + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.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 = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Peer DeAssoc Req.\n", __FUNCTION__)); + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + if (pApCliEntry->Valid) + ApCliLinkDown(pAd, ifIndex); + + /* set the apcli interface be invalid. */ + pApCliEntry->Valid = FALSE; + + /* clear MlmeAux.Ssid and Bssid. */ + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, MAC_ADDR_LEN); + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.SsidLen = 0; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Ssid, MAX_LEN_OF_SSID); + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.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 = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) MLME Request Disconnect.\n", __FUNCTION__)); + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + DisassocParmFill(pAd, &DisassocReq, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.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->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, MAC_ADDR_LEN); + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.SsidLen = 0; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Ssid, MAX_LEN_OF_SSID); + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.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 = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) MLME Request Disconnect.\n", __FUNCTION__)); + + if (ifIndex >= MAX_APCLI_NUM) + return; + + 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].ApCliMlmeAux.Bssid); + + 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->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, MAC_ADDR_LEN); + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.SsidLen = 0; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Ssid, MAX_LEN_OF_SSID); + pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Rssi = 0; + + *pCurrState = APCLI_CTRL_DISCONNECTED; + + return; +} + +#endif /* P2P_SUPPORT */ + diff --git a/mt7620/src/sta/p2pcli_sync.c b/mt7620/src/sta/p2pcli_sync.c new file mode 100644 index 0000000..ffa9bc9 --- /dev/null +++ b/mt7620/src/sta/p2pcli_sync.c @@ -0,0 +1,992 @@ +/* + *************************************************************************** + * 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 P2P_SUPPORT + +#include "rt_config.h" + +#define OBSS_BEACON_RSSI_THRESHOLD (-85) + +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, + OUT PCHAR Ssid, + IN USHORT ifIndex); + +static VOID ApCliPeerProbeRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +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; + + 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_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)ApCliPeerProbeRspAction); + + //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_PEER_BEACON, (STATE_MACHINE_FUNC)ApCliPeerProbeRspAtJoinAction); + StateMachineSetAction(Sm, APCLI_JOIN_WAIT_PROBE_RSP, APCLI_MT2_PROBE_TIMEOUT, (STATE_MACHINE_FUNC)ApCliProbeTimeoutAtJoinAction); + + for (i = 0; i < MAX_APCLI_NUM; i++) + { + /* timer init */ + RTMPInitTimer(pAd, &pAd->ApCfg.ApCliTab[i].ApCliMlmeAux.ProbeTimer, GET_TIMER_FUNCTION(ApCliProbeTimeout), pAd, FALSE); + 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) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + DBGPRINT(RT_DEBUG_TRACE, ("ApCli_SYNC - ProbeReqTimeout\n")); + + MlmeEnqueue(pAd, APCLI_SYNC_STATE_MACHINE, APCLI_MT2_PROBE_TIMEOUT, 0, NULL, 0); + 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; + PAPCLI_STRUCT pApCliEntry = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("ApCli SYNC - ApCliMlmeProbeReqAction(Ssid %s)\n", Info->Ssid)); + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + /* reset all the timers */ + RTMPCancelTimer(&(pApCliEntry->ApCliMlmeAux.ProbeTimer), &Cancelled); + + pApCliEntry->ApCliMlmeAux.Rssi = -9999; + pApCliEntry->ApCliMlmeAux.Channel = pAd->CommonCfg.Channel; + pApCliEntry->ApCliMlmeAux.SupRateLen = pAd->CommonCfg.SupRateLen; + NdisMoveMemory(pApCliEntry->ApCliMlmeAux.SupRate, pAd->CommonCfg.SupRate, pAd->CommonCfg.SupRateLen); + + /* Prepare the default value for extended rate */ + pApCliEntry->ApCliMlmeAux.ExtRateLen = pAd->CommonCfg.ExtRateLen; + NdisMoveMemory(pApCliEntry->ApCliMlmeAux.ExtRate, pAd->CommonCfg.ExtRate, pAd->CommonCfg.ExtRateLen); + + RTMPSetTimer(&(pApCliEntry->ApCliMlmeAux.ProbeTimer), PROBE_TIMEOUT); + + ApCliEnqueueProbeRequest(pAd, Info->SsidLen, (PCHAR) Info->Ssid, ifIndex); + + DBGPRINT(RT_DEBUG_TRACE, ("ApCli SYNC - Start Probe the SSID %s on channel =%d\n", pApCliEntry->ApCliMlmeAux.Ssid, pApCliEntry->ApCliMlmeAux.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) +{ + UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; + UCHAR /* Ssid[MAX_LEN_OF_SSID], */ SsidLen = 0, BssType, Channel, MessageToMe, + DtimCount, DtimPeriod, BcastFlag; + UCHAR *Ssid = NULL; + LARGE_INTEGER TimeStamp; + USHORT BeaconPeriod, AtimWin, CapabilityInfo; +/* UINT FrameLen = 0; */ + CF_PARM Cf; + UCHAR Erp; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen, ExtRateLen; + UCHAR CkipFlag; + USHORT LenVIE; + UCHAR AironetCellPowerLimit; + EDCA_PARM EdcaParm; + QBSS_LOAD_PARM QbssLoad; + QOS_CAPABILITY_PARM QosCapability; +/* UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 */ + UCHAR *VarIE = NULL; + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + ULONG RalinkIe; + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; +/* HT_CAPABILITY_IE HtCapability; */ +/* ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE */ + HT_CAPABILITY_IE *pHtCapability = NULL; + ADD_HT_INFO_IE *pAddHtInfo = NULL; /* AP might use this additional ht info IE */ + UCHAR HtCapabilityLen; + UCHAR AddHtInfoLen; + UCHAR NewChannel; + UCHAR NewExtChannelOffset = 0xff; + PAPCLI_STRUCT pApCliEntry = NULL; +#ifdef DOT11_N_SUPPORT + UCHAR CentralChannel = 0; +#endif /* DOT11_N_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + UCHAR pPreNHtCapabilityLen = 0; +#endif /* CONFIG_STA_SUPPORT */ + EXT_CAP_INFO_ELEMENT ExtCapInfo; + + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].SyncCurrState; + + if (ifIndex >= MAX_APCLI_NUM) + return; + + /* 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; + } + os_alloc_mem(NULL, (UCHAR **)&pHtCapability, sizeof(HT_CAPABILITY_IE)); + if (pHtCapability == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + os_alloc_mem(NULL, (UCHAR **)&pAddHtInfo, sizeof(ADD_HT_INFO_IE)); + if (pAddHtInfo == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + os_alloc_mem(NULL, (UCHAR **)&Ssid, MAX_LEN_OF_SSID); + if (Ssid == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + + if (pCurrState == APCLI_SYNC_IDLE) + goto LabelErr; + + /* Init Variable IE structure */ + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + RTMPZeroMemory(pHtCapability, sizeof(HT_CAPABILITY_IE)); + RTMPZeroMemory(pAddHtInfo, sizeof(ADD_HT_INFO_IE)); + RTMPZeroMemory(&QosCapability, sizeof(QOS_CAPABILITY_PARM)); + RTMPZeroMemory(&EdcaParm, sizeof(EDCA_PARM)); + + if (PeerBeaconAndProbeRspSanity(pAd, + Elem->Msg, + Elem->MsgLen, + Elem->Channel, + Addr2, + Bssid, + (PCHAR) Ssid, + &SsidLen, + &BssType, + &BeaconPeriod, + &Channel, + &NewChannel, + &TimeStamp, + &Cf, + &AtimWin, + &CapabilityInfo, + &Erp, + &DtimCount, + &DtimPeriod, + &BcastFlag, + &MessageToMe, + SupRate, + &SupRateLen, + ExtRate, + &ExtRateLen, + &CkipFlag, + &AironetCellPowerLimit, + &EdcaParm, + &QbssLoad, + &QosCapability, + &RalinkIe, + &HtCapabilityLen, +#ifdef CONFIG_STA_SUPPORT + &pPreNHtCapabilityLen, +#endif /* CONFIG_STA_SUPPORT */ + pHtCapability, + &ExtCapInfo, + &AddHtInfoLen, + pAddHtInfo, + &NewExtChannelOffset, + &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; + +#ifdef P2P_SUPPORT + MlmeEnqueue(pAd, P2P_DISC_STATE_MACHINE, P2P_DISC_PEER_PROB_RSP, Elem->MsgLen, Elem->Msg, Channel); +#endif /* P2P_SUPPORT */ + + /* + Update ScanTab + */ + Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); + if (Bssidx == BSS_NOT_FOUND) + { + /* discover new AP of this network, create BSS entry */ + Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, + &Cf, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, + pHtCapability, pAddHtInfo, HtCapabilityLen,AddHtInfoLen,NewExtChannelOffset, Channel, + -127, TimeStamp, CkipFlag, &EdcaParm, &QosCapability, + &QbssLoad, LenVIE, pVIE); + if (Bssidx == BSS_NOT_FOUND) /* return if BSS table full */ + 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, Addr2, MAC_ADDR_LEN); + } + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + /* Check the Probe-Rsp's Bssid. */ + if(!MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, ZERO_MAC_ADDR)) + bssidEqualFlag = MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, Bssid); + else + bssidEmptyFlag = TRUE; + /* Check the Probe-Rsp's Ssid. */ + if(pApCliEntry->CfgSsidLen != 0) + ssidEqualFlag = SSID_EQUAL(pApCliEntry->CfgSsid, pApCliEntry->CfgSsidLen, Ssid, 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; + + + 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 + && ((pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode == WSC_DISABLE) || + (pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger == FALSE)) +#endif /* WSC_AP_SUPPORT */ + ) + { + if (ApCliValidateRSNIE(pAd, (PEID_STRUCT)pVIE, LenVIE, ifIndex)) + { + pApCliEntry->ApCliMlmeAux.VarIELen = LenVIE; + NdisMoveMemory(pApCliEntry->ApCliMlmeAux.VarIEs, pVIE, pApCliEntry->ApCliMlmeAux.VarIELen); + } + else + { + /* ignore this response */ + pApCliEntry->ApCliMlmeAux.VarIELen = 0; + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The RSN IE of this received Probe-resp is dis-match !!!!!!!!!! \n")); + goto LabelErr; + } + } + else + { + if (pApCliEntry->AuthMode >= Ndis802_11AuthModeWPA +#ifdef WSC_AP_SUPPORT + && ((pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode == WSC_DISABLE) || + (pAd->ApCfg.ApCliTab[ifIndex].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->ApCliMlmeAux.VarIELen = 0; + } + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - receive desired PROBE_RSP at JoinWaitProbeRsp... Channel = %d\n", 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 RealRssi = (LONG)(RTMPMaxRssi(pAd, Rssi0, Rssi1, Rssi2)); + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - previous Rssi = %ld current Rssi=%ld\n", pApCliEntry->ApCliMlmeAux.Rssi, (LONG)RealRssi)); + if (pApCliEntry->ApCliMlmeAux.Rssi > (LONG)RealRssi) + goto LabelErr; + else + pApCliEntry->ApCliMlmeAux.Rssi = RealRssi; + } + else + { + BOOLEAN Cancelled; + RTMPCancelTimer(&pApCliEntry->ApCliMlmeAux.ProbeTimer, &Cancelled); + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + /* Stop Scan and resume */ + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); + pAd->MlmeAux.Channel = 0; + ScanNextChannel(pAd, OPMODE_AP); + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: Swich Channel = %d. and STOP Scanning!!\n", __FUNCTION__, Channel)); + } + + NdisMoveMemory(pApCliEntry->ApCliMlmeAux.Ssid, Ssid, SsidLen); + pApCliEntry->ApCliMlmeAux.SsidLen = SsidLen; + + NdisMoveMemory(pApCliEntry->ApCliMlmeAux.Bssid, Bssid, MAC_ADDR_LEN); + pApCliEntry->ApCliMlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; + pApCliEntry->ApCliMlmeAux.BssType = BssType; + pApCliEntry->ApCliMlmeAux.BeaconPeriod = BeaconPeriod; + pApCliEntry->ApCliMlmeAux.Channel = Channel; + pApCliEntry->ApCliMlmeAux.AtimWin = AtimWin; + pApCliEntry->ApCliMlmeAux.CfpPeriod = Cf.CfpPeriod; + pApCliEntry->ApCliMlmeAux.CfpMaxDuration = Cf.CfpMaxDuration; + pApCliEntry->ApCliMlmeAux.APRalinkIe = RalinkIe; + + /* Copy AP's supported rate to MlmeAux for creating assoication request */ + /* Also filter out not supported rate */ + pApCliEntry->ApCliMlmeAux.SupRateLen = SupRateLen; + NdisMoveMemory(pApCliEntry->ApCliMlmeAux.SupRate, SupRate, SupRateLen); + RTMPCheckRates(pAd, pApCliEntry->ApCliMlmeAux.SupRate, &(pApCliEntry->ApCliMlmeAux.SupRateLen)); + pApCliEntry->ApCliMlmeAux.ExtRateLen = ExtRateLen; + NdisMoveMemory(pApCliEntry->ApCliMlmeAux.ExtRate, ExtRate, ExtRateLen); + RTMPCheckRates(pAd, pApCliEntry->ApCliMlmeAux.ExtRate, &pApCliEntry->ApCliMlmeAux.ExtRateLen); + +#ifdef DOT11_N_SUPPORT + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].RxMcsSet,sizeof(pAd->ApCfg.ApCliTab[ifIndex].RxMcsSet)); + /* filter out un-supported ht rates */ + if ((HtCapabilityLen > 0) && + (pApCliEntry->DesiredHtPhyInfo.bHtEnable) && + (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { +#ifdef P2P_SUPPORT + BOOLEAN P2PGroup_BW; + UCHAR BwFallBack = 0; +#endif /* P2P_SUPPORT */ + + RTMPZeroMemory(&(pApCliEntry->ApCliMlmeAux.HtCapability), SIZE_HT_CAP_IE); + pApCliEntry->ApCliMlmeAux.NewExtChannelOffset = NewExtChannelOffset; + pApCliEntry->ApCliMlmeAux.HtCapabilityLen = HtCapabilityLen; + ApCliCheckHt(pAd, ifIndex, pHtCapability, pAddHtInfo); + RTMPMoveMemory(&(pApCliEntry->ApCliMlmeAux.AddHtInfo), pAddHtInfo, SIZE_ADD_HT_INFO_IE); + + if (AddHtInfoLen > 0) + { + CentralChannel = pAddHtInfo->ControlChan; + /* Check again the Bandwidth capability of this AP. */ + if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40)) + { + CentralChannel = pAddHtInfo->ControlChan - 2; + } + else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40)) + { + CentralChannel = pAddHtInfo->ControlChan + 2; + } + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction HT===>Central Channel = %d, Control Channel = %d, .\n", CentralChannel, pAddHtInfo->ControlChan)); + } +#ifdef P2P_SUPPORT + if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != CentralChannel) && (pAd->StaActive.SupportedHtPhy.ChannelWidth == BW_40)) + { + DBGPRINT(RT_DEBUG_OFF, ("PeerBeaconAtJoinAction HT===> Channel offset = %d not match INFRA Channel offset %d .\n", + pAd->MlmeAux.CentralChannel, CentralChannel)); + //goto LabelErr; + } + + /*P2PChannelInit(pAd, MAIN_MBSSID); */ + pApCliEntry->ApCliMlmeAux.CentralChannel = CentralChannel; + //P2PInitChannelRelatedValue(pAd); + if (pApCliEntry->ApCliMlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40) + P2PGroup_BW = TRUE; + else + P2PGroup_BW = FALSE; + + AdjustChannelRelatedValue(pAd, + &BwFallBack, + ifIndex, + P2PGroup_BW, + pApCliEntry->ApCliMlmeAux.Channel, + pApCliEntry->ApCliMlmeAux.CentralChannel); + + if (BwFallBack == 1) + { + DBGPRINT(RT_DEBUG_TRACE, ("Infra STA connection to 40MHz AP, but Infra extra and P2P Group extra is different!!!\n")); + pApCliEntry->ApCliMlmeAux.HtCapability.HtCapInfo.ChannelWidth = BW_20; + pApCliEntry->ApCliMlmeAux.CentralChannel = pApCliEntry->ApCliMlmeAux.Channel; + pApCliEntry->ApCliMlmeAux.bBwFallBack = TRUE; + } + else + { + pApCliEntry->ApCliMlmeAux.bBwFallBack = FALSE; + } + + pApCliEntry->ApCliMlmeAux.ConCurrentCentralChannel = pAd->CommonCfg.CentralChannel; +#endif /* P2P_SUPPORT */ + } + else +#endif /* DOT11_N_SUPPORT */ + { + RTMPZeroMemory(&(pApCliEntry->ApCliMlmeAux.HtCapability), SIZE_HT_CAP_IE); + RTMPZeroMemory(&(pApCliEntry->ApCliMlmeAux.AddHtInfo), SIZE_ADD_HT_INFO_IE); + pApCliEntry->ApCliMlmeAux.HtCapabilityLen = 0; + } +#ifdef P2P_SUPPORT + P2PUpdateMlmeRate(pAd, ifIndex); +#else + RTMPUpdateMlmeRate(pAd); +#endif /* P2P_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + /* copy QOS related information */ + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + { + NdisMoveMemory(&(pApCliEntry->ApCliMlmeAux.APEdcaParm), &EdcaParm, sizeof(EDCA_PARM)); + NdisMoveMemory(&(pApCliEntry->ApCliMlmeAux.APQbssLoad), &QbssLoad, sizeof(QBSS_LOAD_PARM)); + NdisMoveMemory(&(pApCliEntry->ApCliMlmeAux.APQosCapability), &QosCapability, sizeof(QOS_CAPABILITY_PARM)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + NdisZeroMemory(&(pApCliEntry->ApCliMlmeAux.APEdcaParm), sizeof(EDCA_PARM)); + NdisZeroMemory(&(pApCliEntry->ApCliMlmeAux.APQbssLoad), sizeof(QBSS_LOAD_PARM)); + NdisZeroMemory(&(pApCliEntry->ApCliMlmeAux.APQosCapability), sizeof(QOS_CAPABILITY_PARM)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI SYNC - after JOIN, SupRateLen=%d, ExtRateLen=%d\n", + pApCliEntry->ApCliMlmeAux.SupRateLen, pApCliEntry->ApCliMlmeAux.ExtRateLen)); + + if (AironetCellPowerLimit != 0xFF) + { + //We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power */ + ChangeToCellPowerLimit(pAd, AironetCellPowerLimit); + } + else //Used the default TX Power Percentage. */ + pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; + if(bssidEqualFlag == TRUE) + { + *pCurrState = APCLI_SYNC_IDLE; + + ApCliCtrlMsg.Status = MLME_SUCCESS; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_PROBE_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + } + } + /* not to me BEACON, ignored */ + } + /* sanity check fail, ignore this frame */ + +LabelErr: + 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 (Ssid != NULL) + os_free_mem(NULL, Ssid); + 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; + PAPCLI_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; + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_SYNC - ApCliMlmeAux.Bssid=%02x:%02x:%02x:%02x:%02x:%02x\n", + pApCliEntry->ApCliMlmeAux.Bssid[0], + pApCliEntry->ApCliMlmeAux.Bssid[1], + pApCliEntry->ApCliMlmeAux.Bssid[2], + pApCliEntry->ApCliMlmeAux.Bssid[3], + pApCliEntry->ApCliMlmeAux.Bssid[4], + pApCliEntry->ApCliMlmeAux.Bssid[5])); + + if(!MAC_ADDR_EQUAL(pApCliEntry->ApCliMlmeAux.Bssid, ZERO_MAC_ADDR)) + { + ApCliCtrlMsg.Status = MLME_SUCCESS; + 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; + 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, + OUT PCHAR Ssid, + 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]; + PUCHAR ptr; + ULONG TmpLen; + PAPCLI_STRUCT pApCliEntry = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("force out a ProbeRequest ...\n")); + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + 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(pAd->ApCfg.ApCliTab[ifIndex].CfgApCliBssid, ZERO_MAC_ADDR)) + ApCliMgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, + BROADCAST_ADDR, BROADCAST_ADDR, ifIndex); + else + ApCliMgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, + pAd->ApCfg.ApCliTab[ifIndex].CfgApCliBssid, pAd->ApCfg.ApCliTab[ifIndex].CfgApCliBssid, 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->ApCliMlmeAux.SupRateLen), + pApCliEntry->ApCliMlmeAux.SupRateLen, pApCliEntry->ApCliMlmeAux.SupRate, + END_OF_ARGS); + + /* Add the extended rate IE */ + if (pApCliEntry->ApCliMlmeAux.ExtRateLen != 0) + { + ULONG tmp; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &(pApCliEntry->ApCliMlmeAux.ExtRateLen), + pApCliEntry->ApCliMlmeAux.ExtRateLen, pApCliEntry->ApCliMlmeAux.ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + + P2pMakeProbeRspWSCIE(pAd, pOutBuffer + FrameLen, &TmpLen); + FrameLen += TmpLen; + + ptr = pOutBuffer + FrameLen; + P2pMakeP2pIE(pAd, SUBTYPE_PROBE_REQ, ptr, &TmpLen); + FrameLen += TmpLen; + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + + return; +} + +BOOLEAN ApCliWaitProbRsp( + IN PRTMP_ADAPTER pAd, + IN USHORT ifIndex) +{ + if (ifIndex >= MAX_APCLI_NUM) + return FALSE; + + return (pAd->ApCfg.ApCliTab[ifIndex].SyncCurrState == APCLI_JOIN_WAIT_PROBE_RSP) ? + TRUE : FALSE; +} + +/* + ========================================================================== + Description: + peer sends beacon back when scanning + ========================================================================== + */ +VOID ApCliPeerProbeRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; + UCHAR /* Ssid[MAX_LEN_OF_SSID], */ BssType, Channel=0, NewChannel, + SsidLen=0, DtimCount, DtimPeriod, BcastFlag, MessageToMe; + UCHAR *Ssid = NULL; + CF_PARM CfParm; + USHORT BeaconPeriod, AtimWin, CapabilityInfo; + PFRAME_802_11 pFrame; + LARGE_INTEGER TimeStamp; + UCHAR Erp; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen, ExtRateLen; + UCHAR CkipFlag; + UCHAR AironetCellPowerLimit; + EDCA_PARM EdcaParm; + QBSS_LOAD_PARM QbssLoad; + QOS_CAPABILITY_PARM QosCapability; + ULONG RalinkIe; +/* UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 */ + UCHAR *VarIE = NULL; + USHORT LenVIE; + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; +/* + HT_CAPABILITY_IE HtCapability; + ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE +*/ + HT_CAPABILITY_IE *pHtCapability = NULL; + ADD_HT_INFO_IE *pAddHtInfo = NULL; /* AP might use this additional ht info IE */ + UCHAR HtCapabilityLen; + UCHAR AddHtInfoLen; + UCHAR NewExtChannelOffset = 0xff; + CHAR RealRssi = -127; +#ifdef CONFIG_STA_SUPPORT + UCHAR pPreNHtCapabilityLen = 0; +#endif /* CONFIG_STA_SUPPORT */ + + EXT_CAP_INFO_ELEMENT ExtCapInfo; + + + /* 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; + } + os_alloc_mem(NULL, (UCHAR **)&pHtCapability, sizeof(HT_CAPABILITY_IE)); + if (pHtCapability == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + os_alloc_mem(NULL, (UCHAR **)&pAddHtInfo, sizeof(ADD_HT_INFO_IE)); + if (pAddHtInfo == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + os_alloc_mem(NULL, (UCHAR **)&Ssid, MAX_LEN_OF_SSID); + if (Ssid == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + + SsidLen = 0; + + RTMPZeroMemory(pHtCapability, sizeof(HT_CAPABILITY_IE)); + RTMPZeroMemory(pAddHtInfo, sizeof(ADD_HT_INFO_IE)); + + 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, + 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 + &pPreNHtCapabilityLen, +#endif /* CONFIG_STA_SUPPORT */ + pHtCapability, + &ExtCapInfo, + &AddHtInfoLen, + pAddHtInfo, + &NewExtChannelOffset, + &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)); + +#ifdef P2P_SUPPORT + MlmeEnqueue(pAd, P2P_DISC_STATE_MACHINE, P2P_DISC_PEER_PROB_RSP, Elem->MsgLen, Elem->Msg, Channel); +#endif /* P2P_SUPPORT */ + + + /* ignore BEACON not in this channel */ + if (Channel != pAd->MlmeAux.Channel +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + && (pAd->CommonCfg.bOverlapScanning == FALSE) +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + ) + { + goto __End_Of_APPeerBeaconAtScanAction; + } + +#ifdef DOT11_N_SUPPORT + if ((RealRssi > OBSS_BEACON_RSSI_THRESHOLD) && (pHtCapability->HtCapInfo.Forty_Mhz_Intolerant)) /* || (HtCapabilityLen == 0))) */ + { + Handle_BSS_Width_Trigger_Events(pAd); + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef IDS_SUPPORT + /* Conflict SSID detection */ + if (Channel == pAd->CommonCfg.Channel) + RTMPConflictSsidDetection(pAd, Ssid, 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, Bssid, 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, Bssid, (PCHAR)Ssid, SsidLen, BssType, BeaconPeriod, + &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, pHtCapability, + pAddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag, + &EdcaParm, &QosCapability, &QbssLoad, 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); + } + } + + /* sanity check fail, ignored */ +__End_Of_APPeerBeaconAtScanAction: + /*scan beacon in pastive */ +#ifdef CONFIG_AP_SUPPORT +IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +{ + if (Channel == pAd->ApCfg.AutoChannel_Channel) + { + if (AutoChBssSearchWithSSID(pAd, Bssid, (PUCHAR)Ssid, SsidLen, Channel) == BSS_NOT_FOUND) + pAd->pChannelInfo->ApCnt[pAd->ApCfg.current_channel_index]++; + + AutoChBssInsertEntry(pAd, Bssid, (CHAR *)Ssid, SsidLen, Channel, NewExtChannelOffset, RealRssi); + } +} +#endif /* CONFIG_AP_SUPPORT */ +LabelErr: + 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 (Ssid != NULL) + os_free_mem(NULL, Ssid); +} + +#endif /* P2P_SUPPORT */ + diff --git a/mt7620/src/sta/rtmp_ckipmic.c b/mt7620/src/sta/rtmp_ckipmic.c new file mode 100644 index 0000000..422cbc4 --- /dev/null +++ b/mt7620/src/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/mt7620/src/sta/rtmp_data.c b/mt7620/src/sta/rtmp_data.c new file mode 100644 index 0000000..5de2421 --- /dev/null +++ b/mt7620/src/sta/rtmp_data.c @@ -0,0 +1,4441 @@ +/* + *************************************************************************** + * 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) +{ + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; + UCHAR *pTmpBuf; + +#ifdef MESH_SUPPORT + if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_MESH) { + UINT mesh_header_len = GetMeshHederLen(pRxBlk->pData); + + /* skip mesh header */ + pRxBlk->pData += mesh_header_len; + pRxBlk->DataSize -= mesh_header_len; + } +#endif /* MESH_SUPPORT */ + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.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.IEEE8021X == TRUE) && + (pAd->StaCfg.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.IEEE8021x_required_keys == FALSE) { + idx = pAd->StaCfg.DesireSharedKeyId; + CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg; + Key = pAd->StaCfg.DesireSharedKey[idx].Key; + + if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0) { + /* Set key material and cipherAlg to Asic */ + RTMP_ASIC_SHARED_KEY_TABLE(pAd, + BSS0, + idx, + &pAd->StaCfg.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.DesireSharedKey[idx].KeyLen; + NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key, + pAd->StaCfg.DesireSharedKey[idx].Key, + pAd->StaCfg.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, + pRxWI->WirelessCliID, + pTmpBuf, + pRxBlk->DataSize +LENGTH_802_11, + pRxWI->RSSI0, + pRxWI->RSSI1, + pRxWI->RSSI2, + 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, pRxWI->WirelessCliID, + pTmpBuf, + pRxBlk->DataSize + + LENGTH_802_11, pRxWI->RSSI0, + pRxWI->RSSI1, pRxWI->RSSI2, + 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)) { + PRXWI_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, pRxWI->WirelessCliID, + pTmpBuf, + pRxBlk->DataSize + + LENGTH_802_11, pRxWI->RSSI0, + pRxWI->RSSI1, pRxWI->RSSI2, + 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 */ + +#ifdef MESH_SUPPORT + if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_MESH) { + /* drop all non-EAP DATA frame before */ + /* this client's Port-Access-Control is secured */ + if (pRxBlk->pHeader->FC.Wep) { + /* unsupported cipher suite */ + if (pEntry->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 ((pEntry->WepStatus != + Ndis802_11EncryptionDisabled) + && (pEntry->PortSecured == + WPA_802_1X_PORT_NOT_SECURED)) { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, + pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); + return; + } + } + + } else +#endif /* MESH_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.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.WepStatus != + Ndis802_11EncryptionDisabled) + && (pAd->StaCfg.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); + +#ifdef MESH_SUPPORT + if (pEntry && IS_ENTRY_MESH(pEntry)) { + UINT32 MeshSeq = GetMeshSeq(pRxBlk->pData); + PHEADER_802_11 pHeader = pRxBlk->pHeader; + PUCHAR pMeshDA = pHeader->Addr3; + PUCHAR pMeshSA = (PUCHAR) (pHeader->Octet); + PUCHAR pSA = GetMeshAddr6(pRxBlk->pData); + + if (PktSigCheck + (pAd, pHeader->Addr2, pMeshDA, pMeshSA, MeshSeq, + BTYPE_DATA) == FALSE) { + /* signature exist, it means it's a duplicate packet. so drop it. */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); + return; + } + + if ((pMeshSA != NULL) && (pSA != NULL) + && (pAd->MeshTab.OpMode & MESH_AP)) { + if (!MAC_ADDR_EQUAL(pMeshSA, pSA)) { + PMESH_PROXY_ENTRY pMeshProxyEntry; + + pMeshProxyEntry = + MeshProxyEntryTableLookUp(pAd, pSA); + if (!pMeshProxyEntry) + MeshProxyEntryTableInsert(pAd, + pMeshSA, + pSA); + } + } + } +#endif /* MESH_SUPPORT */ + + 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); + } + } +} + +/* 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->pRxWI->KeyIndex]; + + 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.WpaSupplicantUP) { + WpaSendMicFailureToWpaSupplicant(pAd->net_dev, + (pWpaKey->Type == + PAIRWISEKEY) ? TRUE : + FALSE); + } else +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + RTMPReportMicError(pAd, pWpaKey); + } + + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, + NDIS_STATUS_FAILURE); + return FALSE; + } + + return TRUE; +} + + +#ifdef PRE_ANT_SWITCH +#if defined (RT2883) || defined (RT3883) +/* STASelectPktDetAntenna - Selects antenna with best RSSI to be used for packet detection */ +VOID STASelectPktDetAntenna( + IN PRTMP_ADAPTER pAd) +{ + UCHAR rxAnts = ((pAd->StaCfg.BBPR3 >> 3) & 0x3) + 1; + UCHAR antValue; + + /* Use antenna with best RSSI. Last RSSI is negative number. Find largest value */ + if (pAd->CommonCfg.PreAntSwitch != 0) { + if (pAd->StaCfg.RssiSample.LastRssi0 > pAd->CommonCfg.PreAntSwitchRSSI || + (pAd->MacTab.Size != 1) || +#ifdef MESH_SUPPORT + MESH_ON(pAd) || +#endif /* MESH_SUPPORT */ + rxAnts==1) + antValue = 0; + else if (pAd->StaCfg.RssiSample.LastRssi1 > pAd->StaCfg.RssiSample.LastRssi0) + antValue = (rxAnts==3 && pAd->StaCfg.RssiSample.LastRssi2>pAd->StaCfg.RssiSample.LastRssi1)? 2: 1; + else + antValue = (rxAnts==3 && pAd->StaCfg.RssiSample.LastRssi2>pAd->StaCfg.RssiSample.LastRssi0)? 2: 0; + + if ((pAd->StaCfg.BBPR3 & 0x03) != antValue) { + pAd->StaCfg.BBPR3 = (pAd->StaCfg.BBPR3 & ~0x03) | antValue; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); + } + } +} +#endif /* defined (RT2883) || defined (RT3883) */ +#endif /* PRE_ANT_SWITCH */ + +/* + 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( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; + PHEADER_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 OldPwrMgmt = PWR_ACTIVE; + FRAME_CONTROL *pFmeCtrl = &pHeader->FC; + + if ((pHeader->FC.FrDs == 1) && (pHeader->FC.ToDs == 1)) { +#ifdef MESH_SUPPORT + /* have no valid wds entry exist, then discard the incoming packet. */ + if (((pEntry = FindMeshEntry(pAd, pRxWI->WirelessCliID, pHeader->Addr2)) != NULL) + && MESH_ON(pAd)) { + Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI); + RX_BLK_SET_FLAG(pRxBlk, fRX_MESH); + FromWhichBSSID = + pEntry->MatchMeshTabIdx + MIN_NET_DEVICE_FOR_MESH; + } else +#endif /* MESH_SUPPORT */ +#ifdef CLIENT_WDS + if ((pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE) + && IS_ENTRY_CLIENT(&pAd->MacTab.Content[pRxWI->WirelessCliID])) { + RX_BLK_SET_FLAG(pRxBlk, fRX_WDS); + } else +#endif /* CLIENT_WDS */ + { /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, + NDIS_STATUS_FAILURE); + return; + } + } else { + + +#ifdef QOS_DLS_SUPPORT + if (RTMPRcvFrameDLSCheck + (pAd, pHeader, pRxWI->MPDUtotalByteCount, pRxD)) { + return; + } +#endif /* QOS_DLS_SUPPORT */ + + /* Drop not my BSS frames */ + if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE) + pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID]; + + if (pRxD->MyBss == 0) { +#ifdef MESH_SUPPORT + /* + When the mesh-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 RxD. + The condition is below, + 1. mesh 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 "RxD->Decrypted=0" + */ + if ((MESH_ON(pAd)) && + (MAC_ADDR_EQUAL + (pAd->CommonCfg.Bssid, pHeader->Addr2)) + && (pRxD->Bcast || pRxD->Mcast) + && (pHeader->FC.FrDs == 1) + && (pHeader->FC.ToDs == 0) + && (pRxD->Decrypted == 0)) { + /* set this m-cast frame is my-bss. */ + pRxD->MyBss = 1; + } else +#endif /* MESH_SUPPORT */ +#ifdef 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 RxD. + 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 "RxD->Decrypted=0" + */ + if ((P2P_INF_ON(pAd)) && + (MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, pHeader->Addr2)) && + (pRxD->Bcast || pRxD->Mcast) && + (pHeader->FC.FrDs == 1) && + (pHeader->FC.ToDs == 0) && + (pRxD->Decrypted == 0)) + { + /* set this m-cast frame is my-bss. */ + pRxD->MyBss = 1; + } + else +#endif /* P2P_SUPPORT */ + { + /* release packet */ + 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) + { +#ifdef DOT11Z_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 /* DOT11Z_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 */ + +#ifdef DOT11Z_TDLS_SUPPORT + /* 1: PWR_SAVE, 0: PWR_ACTIVE */ + if (pEntry != NULL) + { + OldPwrMgmt = RtmpPsIndicate(pAd, pHeader->Addr2, + pRxWI->WirelessCliID, 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); + } + /* End of if */ + } + else + { + DBGPRINT(RT_DEBUG_TRACE, + ("This is a EOSP frame, not a trigger frame!\n")); + } + } + } /* End of if */ +#endif /* UAPSD_SUPPORT */ + } +#endif /* DOT11Z_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 packet */ + 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 */ +#ifdef DOT11Z_TDLS_SUPPORT + && (!IS_TDLS_SUPPORT(pAd)) +#endif /* DOT11Z_TDLS_SUPPORT */ + ) { + if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->MlmeAux.Bssid, 6)) + { + /* Receive frame not my BSSID */ + /* release packet */ + 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 packet */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + } + + /*/ find pEntry */ + if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE) { + pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID]; + + } 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(pRxWI->WirelessCliID == BSSID_WCID); + } + + /* check Atheros Client */ + if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) + && (pHeader->FC.Retry)) { + pEntry->bIAmBadAtheros = TRUE; + pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE; + pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE; + if (!STA_AES_ON(pAd)) + RTMP_UPDATE_PROTECT(pAd, 8 , ALLN_SETPROTECT, TRUE, FALSE); + } + } + + + pRxBlk->pData = (UCHAR *) pHeader; + + /* + update RxBlk->pData, DataSize + 802.11 Header, QOS, HTC, Hw Padding + */ + /* 1. skip 802.11 HEADER */ +#ifdef MESH_SUPPORT + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_MESH)) { + pRxBlk->pData += LENGTH_802_11_WITH_ADDR4; + pRxBlk->DataSize -= LENGTH_802_11_WITH_ADDR4; + } else +#endif /* MESH_SUPPORT */ +#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 */ +#ifdef DOT11Z_TDLS_SUPPORT + if (pRxD->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 /* DOT11Z_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); + } + } + } +#ifdef DOT11Z_TDLS_SUPPORT + } +#endif /* DOT11Z_TDLS_SUPPORT */ + + /* 3. Order bit: A-Ralink or HTC+ */ + if (pHeader->FC.Order) { +#ifdef AGGREGATION_SUPPORT + if ((pRxWI->PHYMODE <= 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 (pRxD->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 (pRxD->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 RxD. */ + if ((pHeader->FC.Wep == 1) && (pRxD->Decrypted == 0)) { + PCIPHER_KEY pSwKey = NULL; + + /* Cipher key table selection */ + if ((pSwKey = RTMPSwCipherKeySelection(pAd, + pRxBlk->pData, + pRxBlk, + pEntry)) == NULL) { + DBGPRINT(RT_DEBUG_TRACE, + ("No vaild cipher key for SW decryption!!!\n")); + /* release packet */ + 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 packet */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, + NDIS_STATUS_FAILURE); + return; + } + /* Record the Decrypted bit as 1 */ + pRxD->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 (pRxD->Bcast || pRxD->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 packet */ + 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 packet */ + 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(pAd, pRxBlk, FromWhichBSSID); + return; + } else if (pRxD->U2M) { + pAd->LastRxRate = (USHORT)((pRxWI->MCS) + + (pRxWI->BW << 7) + + (pRxWI->ShortGI << 8) + + (pRxWI->STBC << 9) + + (pRxWI->PHYMODE << 14)); + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(QOS_DLS_SUPPORT) + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_DLS)) { + MAC_TABLE_ENTRY *pDlsEntry = NULL; + + pDlsEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID]; + if (pDlsEntry + && (pRxWI->WirelessCliID < 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); + + pAd->StaCfg.LastSNR0 = (UCHAR) (pRxWI->SNR0); + pAd->StaCfg.LastSNR1 = (UCHAR) (pRxWI->SNR1); + +#ifdef DOT11N_SS3_SUPPORT + if (pAd->CommonCfg.RxStream == 3) + pAd->StaCfg.LastSNR2 = (UCHAR) (pRxWI->SNR2); +#endif /* DOT11N_SS3_SUPPORT */ +#if defined (RT2883) || defined (RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + { + pAd->StaCfg.BF_SNR[0] = BF_SNR_OFFSET + pRxWI->BF_SNR0; + pAd->StaCfg.BF_SNR[1] = BF_SNR_OFFSET + pRxWI->BF_SNR1; + pAd->StaCfg.BF_SNR[2] = BF_SNR_OFFSET + pRxWI->BF_SNR2; + } +#endif /* defined (RT2883) || defined (RT3883) */ + + 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)(pRxWI->FOFFSET); + pEntry->freqOffsetValid = TRUE; + +#if defined (RT2883) || defined (RT3883) + pEntry->BF_SNR[0] = BF_SNR_OFFSET + pRxWI->BF_SNR0; + pEntry->BF_SNR[1] = BF_SNR_OFFSET + pRxWI->BF_SNR1; + pEntry->BF_SNR[2] = BF_SNR_OFFSET + pRxWI->BF_SNR2; +#endif /* defined (RT2883) || defined (RT3883) */ + } + +#ifdef PRE_ANT_SWITCH +#if defined (RT2883) || defined (RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + STASelectPktDetAntenna(pAd); +#endif /* defined (RT2883) || defined (RT3883) */ +#endif /* PRE_ANT_SWITCH */ + + + 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[pRxWI->WirelessCliID]; + + /* process complete frame */ + if (bFragment && (pRxD->Decrypted) + && (pEntry->WepStatus == Ndis802_11Encryption2Enabled)) { + /* 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 */ + + ASSERT(0); + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); +} + +VOID STAHandleRxMgmtFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; + PHEADER_802_11 pHeader = pRxBlk->pHeader; + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + UCHAR MinSNR = 0; + + do { +#ifdef MESH_SUPPORT + if (pHeader->FC.SubType == SUBTYPE_MULTIHOP) { + MlmeHandleRxMeshFrame(pAd, pRxBlk); + break; + } +#endif /* MESH_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, pRxWI); + + pAd->StaCfg.LastSNR0 = (UCHAR) (pRxWI->SNR0); + pAd->StaCfg.LastSNR1 = (UCHAR) (pRxWI->SNR1); +#ifdef DOT11N_SS3_SUPPORT + pAd->StaCfg.LastSNR2 = (UCHAR) (pRxWI->SNR2); +#endif /* DOT11N_SS3_SUPPORT */ + +#ifdef PRE_ANT_SWITCH +#if defined (RT2883) || defined (RT3883) + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + STASelectPktDetAntenna(pAd); +#endif /* defined (RT2883) || defined (RT3883) */ +#endif /* PRE_ANT_SWITCH */ + } + + if ((pHeader->FC.SubType == SUBTYPE_BEACON) && + (ADHOC_ON(pAd)) && + (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE)) { + MAC_TABLE_ENTRY *pEntry = NULL; + pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID]; + if (pEntry) + Update_Rssi_Sample(pAd, &pEntry->RssiSample, + pRxWI); + } + + /* First check the size, it MUST not exceed the mlme queue size */ + if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE) { + DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount)); + break; + } + +#ifdef DOT11Z_TDLS_SUPPORT + if (pHeader->FC.SubType == SUBTYPE_ACTION) + { + /* only PM bit of ACTION frame can be set */ + if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE) + { + RtmpPsIndicate(pAd, pHeader->Addr2, pRxWI->WirelessCliID, 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 /* DOT11Z_TDLS_SUPPORT */ + + MinSNR = min((CHAR) pRxWI->SNR0, (CHAR) pRxWI->SNR1); + /* Signal in MLME_QUEUE isn't used, therefore take this item to save min SNR. */ + REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, + pRxWI->MPDUtotalByteCount, + pRxWI->RSSI0, pRxWI->RSSI1, + pRxWI->RSSI2, MinSNR, + OPMODE_STA); + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + { + pRxBlk->pData += LENGTH_802_11; + pRxBlk->DataSize -= LENGTH_802_11; + + if (pHeader->FC.Order) { + //handleHtcField(pAd, pRxBlk); // Ignore MCS FB + 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 */ + } while (FALSE); + + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); +} + +VOID STAHandleRxControlFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ +#ifdef DOT11_N_SUPPORT + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; +#endif /* DOT11_N_SUPPORT */ + PHEADER_802_11 pHeader = pRxBlk->pHeader; + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + BOOLEAN retStatus; + NDIS_STATUS status = NDIS_STATUS_FAILURE; + + switch (pHeader->FC.SubType) { + case SUBTYPE_BLOCK_ACK_REQ: +#ifdef DOT11_N_SUPPORT + { + retStatus = + CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, + (pRxWI->MPDUtotalByteCount), + (PFRAME_BA_REQ) pHeader); + status = + (retStatus == + TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE; + } + break; +#endif /* DOT11_N_SUPPORT */ + case SUBTYPE_BLOCK_ACK: + case SUBTYPE_ACK: + default: + break; + } + + RELEASE_NDIS_PACKET(pAd, pRxPacket, status); +} + +/* + ======================================================================== + + Routine Description: + Process RxDone interrupt, running in DPC level + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + This routine has to maintain Rx ring read pointer. + Need to consider QOS DATA format when converting to 802.3 + ======================================================================== +*/ +BOOLEAN STARxDoneInterruptHandle( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN argc) +{ + NDIS_STATUS Status; + UINT32 RxProcessed, RxPending; + BOOLEAN bReschedule = FALSE; + RT28XX_RXD_STRUC *pRxD; + UCHAR *pData; + PRXWI_STRUC pRxWI; + PNDIS_PACKET pRxPacket; + PHEADER_802_11 pHeader; + RX_BLK RxCell; + UINT8 RXWISize = pAd->chipCap.RXWISize; + + 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)) { + break; + } + +#ifdef RTMP_MAC_PCI + if (RxProcessed++ > MAX_RX_PROCESS_CNT) + { + bReschedule = TRUE; + break; + } +#endif /* RTMP_MAC_PCI */ + + RxProcessed++; + + /* + 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 + */ + pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending); + if (pRxPacket == NULL) + break; + + /* get rx descriptor and buffer */ + pRxD = &(RxCell.RxD); + pData = GET_OS_PKT_DATAPTR(pRxPacket); + pRxWI = (PRXWI_STRUC) pData; + pHeader = (PHEADER_802_11) (pData + RXWISize); + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR) pHeader, DIR_READ, TRUE); + RTMPWIEndianChange(pAd, (PUCHAR) pRxWI, TYPE_RXWI); +#endif + +#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 RxCell */ + RxCell.pRxWI = pRxWI; + RxCell.pHeader = pHeader; + RxCell.pRxPacket = pRxPacket; + RxCell.pData = (UCHAR *) pHeader; + RxCell.DataSize = pRxWI->MPDUtotalByteCount; + RxCell.Flags = 0; + SET_OPMODE_STA(&RxCell); + + /* Increase Total receive byte counter after real data received no mater any error or not */ + pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount; + pAd->RalinkCounters.OneSecReceivedByteCount += pRxWI->MPDUtotalByteCount; + pAd->RalinkCounters.RxCount++; + +#ifdef STATS_COUNT_SUPPORT + INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount); +#endif /* STATS_COUNT_SUPPORT */ + + if (pRxWI->MPDUtotalByteCount < 14) + { + Status = NDIS_STATUS_FAILURE; + continue; + } + + if (MONITOR_ON(pAd)) + { + STA_MonPktSend(pAd, &RxCell); + continue; + } + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) { + pAd->ate.RxCntPerSec++; + ATESampleRssi(pAd, pRxWI); +#ifdef RALINK_QA + if (pAd->ate.bQARxStart == TRUE) { + /* (*pRxD) has been swapped in GetPacketFromRxRing() */ + ATE_QA_Statistics(pAd, pRxWI, pRxD, pHeader); + } + +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + { + /* Check sounding frame */ + if (pHeader->FC.Type == BTYPE_MGMT) + { + RX_BLK *pRxBlk = &RxCell; + + 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 + //printk("Receive sounding response\n"); + 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++) + pAd->ate.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])); + } + + } + } +#endif /* TXBF_SUPPORT */ +#endif /* RALINK_QA */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); + continue; + } +#endif /* RALINK_ATE */ + + /* Check for all RxD errors */ + Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD); + + /* Handle the received frame */ + if (Status == NDIS_STATUS_SUCCESS) { + + switch (pHeader->FC.Type) { + case BTYPE_DATA: + STAHandleRxDataFrame(pAd, &RxCell); + break; + + case BTYPE_MGMT: + STAHandleRxMgmtFrame(pAd, &RxCell); + break; + + case BTYPE_CNTL: + STAHandleRxControlFrame(pAd, &RxCell); + break; + + default: + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + break; + } + } else { + pAd->Counters8023.RxErrors++; + /* discard this frame */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, + NDIS_STATUS_FAILURE); + } + } + + return bReschedule; +} + +BOOLEAN STAHandleRxDonePacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pRxPacket, + IN RX_BLK *pRxCell) +{ + RT28XX_RXD_STRUC *pRxD; + PRXWI_STRUC pRxWI; + PHEADER_802_11 pHeader; + BOOLEAN bReschedule = FALSE; + NDIS_STATUS Status; + + SET_OPMODE_STA(pRxCell); + /*pRxCell->OpMode = OPMODE_STA;*/ + pRxWI = pRxCell->pRxWI; + pRxD = &pRxCell->RxD; + pHeader = pRxCell->pHeader; + + if (MONITOR_ON(pAd)) + { + /*send_monitor_packets(pAd, pRxCell, RTMPMaxRssi, ConvertToRssi);*/ + STA_MonPktSend(pAd, pRxCell); + return bReschedule; + } + + /* STARxDoneInterruptHandle() is called in rtusb_bulk.c */ +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + pAd->ate.RxCntPerSec++; + ATESampleRssi(pAd, pRxWI); +#ifdef RALINK_QA + if (pAd->ate.bQARxStart == TRUE) + { + /* (*pRxD) has been swapped in GetPacketFromRxRing() */ + ATE_QA_Statistics(pAd, pRxWI, pRxD, pHeader); + } +#ifdef TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + { + /* Check sounding frame */ + if (pHeader->FC.Type == BTYPE_MGMT) + { + RX_BLK *pRxBlk = pRxCell; + + 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 */ + /*printk("Receive sounding response\n"); */ + 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++) + pAd->ate.soundingResp[i] = pRxBlk->pData[i]; + } + } + 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])); + } + } + } +#endif /* TXBF_SUPPORT */ +#endif /* RALINK_QA */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); + return bReschedule; + } +#endif /* RALINK_ATE */ + + /* Check for all RxD errors */ + Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD); + + /* Handle the received frame */ + if (Status == NDIS_STATUS_SUCCESS) + { + + switch (pHeader->FC.Type) + { + case BTYPE_DATA: + STAHandleRxDataFrame(pAd, pRxCell); + break; + + case BTYPE_MGMT: + STAHandleRxMgmtFrame(pAd, pRxCell); + break; + + case BTYPE_CNTL: + STAHandleRxControlFrame(pAd, pRxCell); + break; + + default: + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + break; + } + } + else + { + pAd->Counters8023.RxErrors++; + /* discard this frame */ + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + } + + return bReschedule; + +} + +/* + ======================================================================== + + Routine Description: + Arguments: + pAd Pointer to our adapter + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID RTMPHandleTwakeupInterrupt( + IN PRTMP_ADAPTER pAd) +{ + AsicForceWakeup(pAd, FALSE); +} + +/* +======================================================================== +Routine Description: + Early checking and OS-depened parsing for Tx packet send to our STA driver. + +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 & STA related code in here. +======================================================================== +*/ +VOID STASendPackets( + IN NDIS_HANDLE MiniportAdapterContext, + IN PPNDIS_PACKET ppPacketArray, + IN UINT NumberOfPackets) +{ + UINT Index; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext; + PNDIS_PACKET pPacket; + BOOLEAN allowToSend = FALSE; + + + for (Index = 0; Index < NumberOfPackets; Index++) { + pPacket = ppPacketArray[Index]; + + do { +#ifdef MESH_SUPPORT + if (RTMP_GET_PACKET_NET_DEVICE(pPacket) >= + MIN_NET_DEVICE_FOR_MESH) { + UCHAR wcid = MCAST_WCID; + allowToSend = + MeshAllowToSendPacket(pAd, pPacket, &wcid); + RTMP_SET_PACKET_WCID(pPacket, wcid); + break; + } +#endif /* MESH_SUPPORT */ + + 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_RADIO_OFF)) { + /* Drop send request since hardware is in reset state */ + break; + } else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd)) { + /* Drop send request since there are no physical connection yet */ + break; + } else { + /* Record that orignal packet source is from NDIS layer,so that */ + /* later on driver knows how to release this NDIS PACKET */ + if (INFRA_ON(pAd) && (0 +#ifdef QOS_DLS_SUPPORT + || (pAd->CommonCfg.bDLSCapable) +#endif /* QOS_DLS_SUPPORT */ +#ifdef DOT11Z_TDLS_SUPPORT + || IS_TDLS_SUPPORT(pAd) +#endif /* DOT11Z_TDLS_SUPPORT */ + )) { + MAC_TABLE_ENTRY *pEntry; + PUCHAR pSrcBufVA = + GET_OS_PKT_DATAPTR(pPacket); + + pEntry = MacTableLookup(pAd, pSrcBufVA); + + if (pEntry + && (IS_ENTRY_DLS(pEntry) +#ifdef DOT11Z_TDLS_SUPPORT + || IS_ENTRY_TDLS(pEntry) +#endif /* DOT11Z_TDLS_SUPPORT */ + )) { + RTMP_SET_PACKET_WCID(pPacket, pEntry->Aid); + } else { + RTMP_SET_PACKET_WCID(pPacket, 0); + } + } else { + RTMP_SET_PACKET_WCID(pPacket, 0); + } + + RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS); + NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING); + pAd->RalinkCounters.PendingNdisPacketCount++; + + allowToSend = TRUE; + } + } while (FALSE); + + if (allowToSend == TRUE) + STASendPacket(pAd, pPacket); + 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); + +} + +/* +======================================================================== +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 TxSwQueue 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 TxSwQueue. + NDIS_STATUS_FAILURE If failed to do en-queue. + +Note: + You only can put OS-indepened & STA related code in here. +======================================================================== +*/ +NDIS_STATUS STASendPacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket) +{ + PACKET_INFO PacketInfo; + PUCHAR pSrcBufVA; + UINT SrcBufLen; + UINT AllowFragSize; + UCHAR NumberOfFrag; + UCHAR RTSRequired; + UCHAR QueIdx, UserPriority; + MAC_TABLE_ENTRY *pEntry = NULL; + unsigned int IrqFlags; + UCHAR Rate; +#ifdef MESH_SUPPORT + USHORT Wcid; + BOOLEAN bMeshPkt = FALSE; +#endif /* MESH_SUPPORT */ + + /* 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, + ("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n", + 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, + ("STASendPacket --> Ndis Packet buffer error !!!\n")); + 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. */ +#ifdef MESH_SUPPORT + Wcid = RTMP_GET_PACKET_WCID(pPacket); + if (VALID_WCID(Wcid) && IS_ENTRY_MESH(&pAd->MacTab.Content[Wcid])) { + bMeshPkt = TRUE; + pEntry = &pAd->MacTab.Content[Wcid]; + Rate = pAd->MacTab.Content[Wcid].CurrTxRate; + if ((pEntry->AuthMode >= Ndis802_11AuthModeWPA) + && (pEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED) + && (RTMP_GET_PACKET_EAPOL(pPacket) == FALSE)) { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return (NDIS_STATUS_FAILURE); + } + } else +#endif /* MESH_SUPPORT */ + { + if (pAd->StaCfg.BssType == BSS_INFRA) { +#if defined(QOS_DLS_SUPPORT) || defined(DOT11Z_TDLS_SUPPORT) + USHORT tmpWcid; + + tmpWcid = RTMP_GET_PACKET_WCID(pPacket); + + if (VALID_WCID(tmpWcid) && + (IS_ENTRY_DLS(&pAd->MacTab.Content[tmpWcid]) || + IS_ENTRY_TDLS(&pAd->MacTab.Content[tmpWcid]))) { + pEntry = &pAd->MacTab.Content[tmpWcid]; + Rate = pAd->MacTab.Content[tmpWcid].CurrTxRate; + } else +#endif + { + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID); + Rate = pAd->CommonCfg.TxRate; + } + } else if (ADHOC_ON(pAd)) { + if (*pSrcBufVA & 0x01) { + RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID); + pEntry = &pAd->MacTab.Content[MCAST_WCID]; + } else { +#ifdef XLINK_SUPPORT + if (pAd->StaCfg.PSPXlink) { + pEntry = + &pAd->MacTab.Content[MCAST_WCID]; + pEntry->Aid = MCAST_WCID; + } else +#endif /* XLINK_SUPPORT */ + pEntry = MacTableLookup(pAd, pSrcBufVA); + + if (pEntry) + RTMP_SET_PACKET_WCID(pPacket, + pEntry->Aid); +#ifdef ETH_CONVERT_SUPPORT + else { + RTMP_SET_PACKET_WCID(pPacket, + MCAST_WCID); + } +#endif /* ETH_CONVERT_SUPPORT */ + } + Rate = pAd->CommonCfg.TxRate; + } + } + + if (!pEntry) { + DBGPRINT(RT_DEBUG_ERROR, + ("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", + 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; + } + + if (ADHOC_ON(pAd) +#ifdef MESH_SUPPORT + && (bMeshPkt == FALSE) +#endif /* MESH_SUPPORT */ + ) { + RTMP_SET_PACKET_WCID(pPacket, (UCHAR) pEntry->Aid); + } + + /* 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, pEntry, OPMODE_STA, &UserPriority, &QueIdx); + +#ifdef DOT11Z_TDLS_SUPPORT +#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 */ +#endif /* DOT11Z_TDLS_SUPPORT */ + +#ifdef WAPI_SUPPORT + /* Check the status of the controlled port and filter the outgoing frame for WAPI */ + if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWAICERT) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWAIPSK)) + && (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) + && (RTMP_GET_PACKET_WAI(pPacket) == FALSE) +#ifdef MESH_SUPPORT + && bMeshPkt == FALSE +#endif /* MESH_SUPPORT */ + ) { + DBGPRINT(RT_DEBUG_TRACE, + ("STASendPacket --> Drop packet before port secured !!!\n")); + 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 (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef WPA_SUPPLICANT_SUPPORT + || (pAd->StaCfg.IEEE8021X == TRUE) +#endif /* WPA_SUPPLICANT_SUPPORT */ + ) + && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) + || (pAd->StaCfg.MicErrCnt >= 2)) + && (RTMP_GET_PACKET_EAPOL(pPacket) == FALSE) +#ifdef MESH_SUPPORT + && bMeshPkt == FALSE +#endif /* MESH_SUPPORT */ + ) { + DBGPRINT(RT_DEBUG_TRACE, + ("STASendPacket --> Drop packet before port secured !!!\n")); + 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, + ("STASendPacket --> Drop packet before WPS process completed !!!\n")); + 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(pEntry, fCLIENT_STATUS_AMSDU_INUSED)) + NumberOfFrag = 1; /* Aggregation overwhelms fragmentation */ +#ifdef DOT11_N_SUPPORT + else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) + || (pAd->StaCfg.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, pAd->CommonCfg.TxRate); + + + 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, + pEntry, + &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 */ + +#ifdef DOT11Z_TDLS_SUPPORT +#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; + } + else + /* non-PS mode or send PS packet to AP */ +#endif /* UAPSD_SUPPORT */ +#endif /* DOT11Z_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, pEntry, &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 + if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE) && + (pEntry->NoBADataCountDown == 0) && IS_HT_STA(pEntry)) { + if (((pEntry->TXBAbitmap & (1 << UserPriority)) == 0) && + ((pEntry->BADeclineBitmap & (1 << UserPriority)) == 0) && + (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) + && + ((IS_ENTRY_CLIENT(pEntry) && pAd->MlmeAux.APRalinkIe != 0x0) + || (pEntry->WepStatus != Ndis802_11WEPEnabled + && pEntry->WepStatus != Ndis802_11Encryption2Enabled)) + && + (!(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))) + ) + { + BAOriSessionSetUp(pAd, pEntry, UserPriority, 0, 10, + FALSE); + } + } +#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; + + 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; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) { + return; + } +#endif /* RALINK_ATE */ + + /* WPA 802.1x secured port control */ + if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef WPA_SUPPLICANT_SUPPORT + || (pAd->StaCfg.IEEE8021X == TRUE) +#endif +#ifdef WAPI_SUPPORT + || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWAICERT) + || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWAIPSK) +#endif /* WAPI_SUPPORT */ + ) && (pAd->StaCfg.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 = BTYPE_DATA; + pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC; + 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_11Encryption1Enabled but the key will use PairwiseKey + Instead of the SharedKey, SharedKey Length may be Zero. +*/ +VOID STAFindCipherAlgorithm( + IN PRTMP_ADAPTER pAd, + IN 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; + + pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket); + pMacEntry = pTxBlk->pMacEntry; + +#ifdef MESH_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry)) { + 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; + } + } else if (pMacEntry->WepStatus == Ndis802_11Encryption1Enabled) { + CipherAlg = pAd->MeshTab.SharedKey.CipherAlg; + if (CipherAlg) + pKey = &pAd->MeshTab.SharedKey; + } else if (pMacEntry->WepStatus == Ndis802_11Encryption2Enabled + || pMacEntry->WepStatus == + Ndis802_11Encryption3Enabled) { + CipherAlg = pMacEntry->PairwiseKey.CipherAlg; + if (CipherAlg) + pKey = &pMacEntry->PairwiseKey; + } else { + CipherAlg = CIPHER_NONE; + pKey = NULL; + } + } else +#endif /* MESH_SUPPORT */ +#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_11Encryption1Enabled) { + KeyIdx = pAd->StaCfg.DefaultKeyId; + } else if ((Cipher == Ndis802_11Encryption2Enabled) || + (Cipher == Ndis802_11Encryption3Enabled)) { + if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) /* multicast */ + KeyIdx = pAd->StaCfg.DefaultKeyId; + else if (pAd->SharedKey[BSS0][0].KeyLen) + KeyIdx = 0; + else + KeyIdx = pAd->StaCfg.DefaultKeyId; + } + + if (KeyIdx == 0xff) + CipherAlg = CIPHER_NONE; +#ifdef ADHOC_WPA2PSK_SUPPORT + else if ((ADHOC_ON(pAd)) + && (Cipher == Ndis802_11Encryption3Enabled) + && (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) + && (pAd->StaCfg.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.WpaSupplicantUP && + (Cipher == Ndis802_11Encryption1Enabled) && + (pAd->StaCfg.IEEE8021X == TRUE) && + (pAd->StaCfg.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; +} + +VOID STABuildCommon802_11Header( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + + HEADER_802_11 *pHeader_802_11; +#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); + + pHeader_802_11 = + (HEADER_802_11 *) & pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]; + + NdisZeroMemory(pHeader_802_11, sizeof (HEADER_802_11)); + + pHeader_802_11->FC.FrDs = 0; + pHeader_802_11->FC.Type = BTYPE_DATA; + pHeader_802_11->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)) { + pHeader_802_11->Sequence = + pTxBlk->pMacEntry->NonQosDataSeq; + pTxBlk->pMacEntry->NonQosDataSeq = + (pTxBlk->pMacEntry->NonQosDataSeq + 1) & MAXSEQ; + } else { + pHeader_802_11->Sequence = + pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]; + pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = + (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] + 1) & MAXSEQ; + } + } else { + pHeader_802_11->Sequence = pAd->Sequence; + pAd->Sequence = (pAd->Sequence + 1) & MAXSEQ; /* next sequence */ + } + + pHeader_802_11->Frag = 0; + + pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); + +#ifdef MESH_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry)) { + PNDIS_PACKET pPacket = pTxBlk->pPacket; + pHeader_802_11->FC.FrDs = 1; + pHeader_802_11->FC.ToDs = 1; + COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pMacEntry->Addr); /* to AP2 */ + COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->MeshTab.CurrentAddress); /* from AP1 */ + COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pMeshDA); + if (RTMP_GET_MESH_SOURCE(pPacket) == MESH_PROXY) + COPY_MAC_ADDR(&pHeader_802_11->Octet[0], + pAd->MeshTab.CurrentAddress); + else + COPY_MAC_ADDR(&pHeader_802_11->Octet[0], pTxBlk->pSrcBufHeader + MAC_ADDR_LEN); /* ADDR4 = SA */ + pTxBlk->MpduHeaderLen += MAC_ADDR_LEN; + } else +#endif /* MESH_SUPPORT */ + { + if (pAd->StaCfg.BssType == BSS_INFRA) { +#ifdef QOS_DLS_SUPPORT + if (bDLSFrame) { + COPY_MAC_ADDR(pHeader_802_11->Addr1, + pTxBlk->pSrcBufHeader); + COPY_MAC_ADDR(pHeader_802_11->Addr2, + pAd->CurrentAddress); + COPY_MAC_ADDR(pHeader_802_11->Addr3, + pAd->CommonCfg.Bssid); + pHeader_802_11->FC.ToDs = 0; + } else +#endif /* QOS_DLS_SUPPORT */ +#ifdef DOT11Z_TDLS_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bTdlsEntry)) { + COPY_MAC_ADDR(pHeader_802_11->Addr1, + pTxBlk->pSrcBufHeader); + COPY_MAC_ADDR(pHeader_802_11->Addr2, + pAd->CurrentAddress); + COPY_MAC_ADDR(pHeader_802_11->Addr3, + pAd->CommonCfg.Bssid); + pHeader_802_11->FC.ToDs = 0; + } else +#endif /* DOT11Z_TDLS_SUPPORT */ + { + 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, + pTxBlk->pSrcBufHeader); + pHeader_802_11->FC.ToDs = 1; +#ifdef CLIENT_WDS + if (!MAC_ADDR_EQUAL + ((pTxBlk->pSrcBufHeader + MAC_ADDR_LEN), + pAd->CurrentAddress)) { + pHeader_802_11->FC.FrDs = 1; + COPY_MAC_ADDR(&pHeader_802_11->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(pHeader_802_11->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(pHeader_802_11->Addr2, + pTxBlk->pSrcBufHeader + + MAC_ADDR_LEN); + else +#endif /* XLINK_SUPPORT */ + COPY_MAC_ADDR(pHeader_802_11->Addr2, + pAd->CurrentAddress); + COPY_MAC_ADDR(pHeader_802_11->Addr3, + pAd->CommonCfg.Bssid); + pHeader_802_11->FC.ToDs = 0; + } + } + + if (pTxBlk->CipherAlg != CIPHER_NONE) + pHeader_802_11->FC.Wep = 1; + + /* + ----------------------------------------------------------------- + STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. + ----------------------------------------------------------------- + */ + if (pAd->CommonCfg.bAPSDForcePowerSave) + pHeader_802_11->FC.PwrMgmt = PWR_SAVE; + else + pHeader_802_11->FC.PwrMgmt = (RtmpPktPmBitCheck(pAd) == TRUE); +} + +#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; + +#ifdef MESH_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry)) { + PNDIS_PACKET pPacket = pTxBlk->pPacket; + COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pMeshDA); + if (RTMP_GET_MESH_SOURCE(pPacket) == MESH_PROXY) + COPY_MAC_ADDR(&pHeader80211->Octet[0], pAd->MeshTab.CurrentAddress); + else + COPY_MAC_ADDR(&pHeader80211->Octet[0], pTxBlk->pSrcBufHeader + MAC_ADDR_LEN); /* ADDR4 = SA */ + pTxBlk->MpduHeaderLen += MAC_ADDR_LEN; + } else +#endif /* MESH_SUPPORT */ + { + /* 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 */ +#ifdef DOT11Z_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 /* DOT11Z_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); + +#ifdef DOT11Z_TDLS_SUPPORT +#ifdef UAPSD_SUPPORT + UAPSD_MR_EOSP_SET(pHeaderBufPtr, pTxBlk); +#endif /* UAPSD_SUPPORT */ +#endif /* DOT11Z_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); + +#ifdef DOT11Z_TDLS_SUPPORT +#ifdef UAPSD_SUPPORT + UAPSD_MR_EOSP_SET(pHeaderBufPtr, pTxBlk); +#endif /* UAPSD_SUPPORT */ +#endif /* DOT11Z_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; + +} + +VOID STA_AMPDU_Frame_Tx( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + 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 + && (pMacEntry->TxSndgType == 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 = + (PUCHAR) (&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 MESH_SUPPORT + && !TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry) +#endif /* MESH_SUPPORT */ +#ifdef SOFT_ENCRYPT + && !TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt) +#endif /* SOFT_ENCRYPT */ +#ifdef TXBF_SUPPORT + && (pMacEntry->TxSndgType == 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 DOT11Z_TDLS_SUPPORT +#ifdef UAPSD_SUPPORT + UAPSD_MR_EOSP_SET(pHeaderBufPtr, pTxBlk); +#endif /* UAPSD_SUPPORT */ +#endif /* DOT11Z_TDLS_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 DOT11Z_TDLS_SUPPORT +#ifdef UAPSD_SUPPORT + UAPSD_MR_EOSP_SET(pHeaderBufPtr, pTxBlk); +#endif /* UAPSD_SUPPORT */ +#endif /* DOT11Z_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 + && (pMacEntry->TxSndgType != 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 (pMacEntry->TxSndgType >= SNDG_TYPE_SOUNDING) + { + DBGPRINT(RT_DEBUG_TRACE, ("--Sounding in AMPDU: TxSndgType=%d, MCS=%d\n", + pMacEntry->TxSndgType, + pMacEntry->TxSndgType==SNDG_TYPE_NDP? pMacEntry->sndgMcs: pTxBlk->pTransmit->field.MCS)); + + // Set HTC bit + if (bHTCPlus == FALSE) + { + bHTCPlus = TRUE; + 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; + + } + 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; + 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 */ + { +#ifdef MESH_SUPPORT + /* Insert Mesh Header. */ + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry)) + InsertPktMeshHeader(pAd, pTxBlk, + &pHeaderBufPtr); +#endif /* MESH_SUPPORT */ + + /* + 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, + (PTXWI_STRUC) (&pTxBlk->HeaderBuf[TXINFO_SIZE]), + pTxBlk); + } else { + RTMPWriteTxWI_Data(pAd, + (PTXWI_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++; + } +} + +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->MPDUtotalByteCount will be updated after final frame was handled. */ + RTMPWriteTxWI_Data(pAd, + (PTXWI_STRUC) (&pTxBlk-> + HeaderBuf + [TXINFO_SIZE]), + pTxBlk); + } else { + pHeaderBufPtr = &pTxBlk->HeaderBuf[0]; + padding = + ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + + subFramePayloadLen, + 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + + subFramePayloadLen); + NdisZeroMemory(pHeaderBufPtr, + padding + LENGTH_AMSDU_SUBFRAMEHEAD); + 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 += LENGTH_AMSDU_SUBFRAMEHEAD; + pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD; + + /* 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( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + HEADER_802_11 *pHeader_802_11; + PUCHAR 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 (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); + 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 */ + 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) | (pAd->CommonCfg. + AckPolicy[pTxBlk-> + QueIdx] << 5)); +#ifdef DOT11Z_TDLS_SUPPORT +#ifdef UAPSD_SUPPORT + UAPSD_MR_EOSP_SET(pHeaderBufPtr, pTxBlk); +#endif /* UAPSD_SUPPORT */ +#endif /* DOT11Z_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, + (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 */ + { +#ifdef MESH_SUPPORT + /* Insert Mesh Header. */ + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry)) + InsertPktMeshHeader(pAd, pTxBlk, &pHeaderBufPtr); +#endif /* MESH_SUPPORT */ + + /* + 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.AuthMode == Ndis802_11AuthModeWPA2PSK) + && (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled) + && (!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, (PTXWI_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 *)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); +} + +VOID STA_ARalink_Frame_Tx( + IN PRTMP_ADAPTER pAd, + IN TX_BLK * pTxBlk) +{ + PUCHAR pHeaderBufPtr; + USHORT FreeNumber = 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->MPDUtotalByteCount + will be updated after final frame was handled. + */ + RTMPWriteTxWI_Data(pAd, + (PTXWI_STRUC) (&pTxBlk-> + HeaderBuf + [TXINFO_SIZE]), + pTxBlk); + +#ifdef MESH_SUPPORT + /* Insert Mesh Header. */ + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry)) + InsertPktMeshHeader(pAd, pTxBlk, + &pHeaderBufPtr); +#endif /* MESH_SUPPORT */ + + /* + 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 = LENGTH_ARALINK_SUBFRAMEHEAD; + } + + totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + + /* FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */ + 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.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 FreeNumber = 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); + +#ifdef DOT11Z_TDLS_SUPPORT +#ifdef UAPSD_SUPPORT + UAPSD_MR_EOSP_SET(pHeaderBufPtr, pTxBlk); +#endif /* UAPSD_SUPPORT */ +#endif /* DOT11Z_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 */ + { + +#ifdef MESH_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry)) + InsertPktMeshHeader(pAd, pTxBlk, &pHeaderBufPtr); +#endif /* MESH_SUPPORT */ + + /* + 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; + + 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 */ + + RTMPWriteTxWI_Data(pAd, + (PTXWI_STRUC) (&pTxBlk-> + HeaderBuf[TXINFO_SIZE]), + pTxBlk); + + HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &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++; + + /* 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); \ + } + +/* + ======================================================================== + + 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: + + ======================================================================== +*/ +NDIS_STATUS STAHardTransmit( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR QueIdx) +{ + NDIS_PACKET *pPacket; + PQUEUE_ENTRY pQEntry; + + /* + --------------------------------------------- + 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); + + + + /* ------------------------------------------------------------------ + 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); + } + + switch (pTxBlk->TxFrameType) { +#ifdef DOT11_N_SUPPORT + case TX_AMPDU_FRAME: + STA_AMPDU_Frame_Tx(pAd, pTxBlk); + break; + case TX_AMSDU_FRAME: + STA_AMSDU_Frame_Tx(pAd, pTxBlk); + break; +#endif /* DOT11_N_SUPPORT */ + case TX_LEGACY_FRAME: + 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); + +} + +ULONG HashBytesPolynomial( + UCHAR *value, + unsigned int len) +{ + unsigned char *word = value; + unsigned int ret = 0; + unsigned int i; + + for (i = 0; i < len; i++) { + int mod = i % 32; + ret ^= (unsigned int)(word[i]) << mod; + ret ^= (unsigned int)(word[i]) >> (32 - mod); + } + return ret; +} + +VOID Sta_Announce_or_Forward_802_3_Packet( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR FromWhichBSSID) +{ + if (TRUE +#ifdef MESH_SUPPORT + && MeshWirelessForward(pAd, pPacket, FromWhichBSSID) +#endif /* MESH_SUPPORT */ + ) { + announce_802_3_packet(pAd, pPacket, OPMODE_STA); + } else { + /* release packet */ + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } +} diff --git a/mt7620/src/sta/sanity.c b/mt7620/src/sta/sanity.c new file mode 100644 index 0000000..bace359 --- /dev/null +++ b/mt7620/src/sta/sanity.c @@ -0,0 +1,332 @@ +/* + *************************************************************************** + * 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" + +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, + ("MlmeStartReqSanity fail - wrong SSID length\n")); + 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) +{ + CHAR IeType, *Ptr; + 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); + Ptr = (PCHAR) 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, + ("PeerAssocRspSanity fail - wrong SupportedRates IE\n")); + 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; + + 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, + ("PeerAssocRspSanity - wrong IE_HT_CAP. \n")); + } + + break; +#ifdef DOT11_N_SUPPORT + 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, + ("PeerAssocRspSanity - wrong IE_ADD_HT. \n")); + } + + break; + case IE_SECONDARY_CH_OFFSET: + if (pEid->Len == 1) { + *pNewExtChannelOffset = pEid->Octet[0]; + } else { + DBGPRINT(RT_DEBUG_WARN, + ("PeerAssocRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n")); + } +#endif /* DOT11_N_SUPPORT */ + 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->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; + 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, + ("PeerAssocRspSanity - ignore unrecognized EID = %d\n", + pEid->Eid)); + break; + } + + Length = Length + 2 + pEid->Len; + pEid = (PEID_STRUCT) ((UCHAR *) pEid + 2 + pEid->Len); + } + + + 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/mt7620/src/sta/sta_cfg.c b/mt7620/src/sta/sta_cfg.c new file mode 100644 index 0000000..28ceea5 --- /dev/null +++ b/mt7620/src/sta/sta_cfg.c @@ -0,0 +1,10352 @@ +/* + *************************************************************************** + * 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 +*/ + +#include "rt_config.h" + +#ifdef P2P_SUPPORT +extern INT Set_P2p_OpMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +extern INT Set_AP_WscPinCode_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +#endif /* P2P_SUPPORT */ + + +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 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 */ + + +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 AGGREGATION_SUPPORT + {"PktAggregate", Set_PktAggregate_Proc}, +#endif /* AGGREGATION_SUPPORT */ + +#ifdef WMM_SUPPORT + {"WmmCapable", Set_WmmCapable_Proc}, +#endif + {"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}, +#endif /* DBG */ + +#ifdef TXBF_SUPPORT + {"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}, + {"ITxBfEn", Set_ITxBfEn_Proc}, +#endif /* STA_ITXBF_SUPPORT */ + {"ETxBfEnCond", Set_ETxBfEnCond_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}, +#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 */ + +#if defined (RT2883) || defined (RT3883) + {"PhyRateLimit", Set_PhyRateLimit_Proc}, +#ifdef DBG + {"FixedRate", Set_FixedRate_Proc}, +#endif /* DBG */ +#endif /* defined (RT2883) || defined (RT3883) */ + +#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}, + {"ATESHOWTSSI", Set_ATE_SHOW_TSSI_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 */ + {"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}, +#ifndef RTMP_RF_RW_SUPPORT + {"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 /* RTMP_RF_RW_SUPPORT */ + {"ATELDE2P", Set_ATE_Load_E2P_Proc}, + {"ATERE2P", Set_ATE_Read_E2P_Proc}, +#ifdef LED_CONTROL_SUPPORT +#endif /* LED_CONTROL_SUUPORT */ + {"ATEAUTOALC", Set_ATE_AUTO_ALC_Proc}, + {"ATETEMPSENSOR", Set_ATE_TEMP_SENSOR_Proc}, + {"ATEIPG", Set_ATE_IPG_Proc}, + {"ATEPAYLOAD", Set_ATE_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 */ +#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 */ + + + + {"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 MESH_SUPPORT + {"MeshId", Set_MeshId_Proc}, + {"MeshHostName", Set_MeshHostName_Proc}, + {"MeshAutoLink", Set_MeshAutoLink_Proc}, + {"MeshAddLink", Set_MeshAddLink_Proc}, + {"MeshForward", Set_MeshForward_Proc}, + {"MeshDelLink", Set_MeshDelLink_Proc}, + {"MeshMaxTxRate", Set_MeshMaxTxRate_Proc}, + {"MeshMultiCastAgeOut", Set_MeshMultiCastAgeOut_Proc}, + {"MeshRouteAdd", Set_MeshRouteAdd_Proc}, + {"MeshRouteDelete", Set_MeshRouteDelete_Proc}, + {"MeshRouteUpdate", Set_MeshRouteUpdate_Proc}, + {"MeshAuthMode", Set_MeshAuthMode_Proc}, + {"MeshEncrypType", Set_MeshEncrypType_Proc}, + {"MeshDefaultkey", Set_MeshDefaultkey_Proc}, + {"MeshWEPKEY", Set_MeshWEPKEY_Proc}, + {"MeshWPAKEY", Set_MeshWPAKEY_Proc}, + {"MeshOnly", Set_MeshOnly_Proc}, + {"MeshPortal", Set_MeshPortal_Proc}, +#endif /* MESH_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 RT305x + {"HiPower", Set_HiPower_Proc}, +#if defined(RT3352) || defined(RT5350) +#ifdef RTMP_INTERNAL_TX_ALC + {"TSSIMaxRange", Set_TSSIMaxRange_Proc}, +#endif /* RTMP_INTERNAL_TX_ALC */ +#endif /* defined(RT3352) || defined(RT5350) */ +#endif /* RT305x */ + + +#ifdef RT5350 + {"HwAntDiv", Set_Hw_Antenna_Div_Proc}, +#endif /* RT5350 */ + + {"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_TdlsCapableProc}, + {"TdlsSetup", Set_TdlsSetupProc}, + {"TdlsTearDown", Set_TdlsTearDownProc}, + {"TdlsDiscoveryReq", Set_TdlsDiscoveryReqProc}, + {"TdlsTPKLifeTime", Set_TdlsTPKLifeTimeProc}, +#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 */ + +#ifdef WOW_SUPPORT +#endif /* WOW_SUPPORT */ + + {"VcoPeriod", Set_VcoPeriod_Proc}, + +#ifdef SINGLE_SKU + {"ModuleTxpower", Set_ModuleTxpower_Proc}, +#endif /* SINGLE_SKU */ + + + {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( + IN PRTMP_ADAPTER pAd, + IN 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.AuthMode = Ndis802_11AuthModeOpen; + pAd->StaCfg.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; +} + +#ifdef WMM_SUPPORT +/* + ========================================================================== + 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; +} +#endif /* WMM_SUPPORT */ + +/* + ========================================================================== + 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 */ + { + UCHAR bbpValue = 0; + BCN_TIME_CFG_STRUC csr; + +#ifdef MONITOR_FLAG_11N_SNIFFER_SUPPORT + if (strcmp(arg, "Monitor2") == 0) + pAd->StaCfg.BssMonitorFlag |= MONITOR_FLAG_11N_SNIFFER; + /* End of if */ +#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 (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) + 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 (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && + pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40 && + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + { + /* 40MHz ,control channel at lower */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &bbpValue); + bbpValue &= (~0x18); + bbpValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, bbpValue); + pAd->CommonCfg.BBPCurrentBW = BW_40; + /* RX : control channel at lower */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &bbpValue); + bbpValue &= (~0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, bbpValue); + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= 0xfffffffe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2; + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + DBGPRINT(RT_DEBUG_TRACE, ("BW_40 ,control_channel(%d), CentralChannel(%d) \n", + pAd->CommonCfg.Channel, + pAd->CommonCfg.CentralChannel)); + } + else if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && + pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40 && + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_BELOW) + { + /* 40MHz ,control channel at upper */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &bbpValue); + bbpValue &= (~0x18); + bbpValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, bbpValue); + pAd->CommonCfg.BBPCurrentBW = BW_40; + 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_R3, &bbpValue); + bbpValue |= (0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, bbpValue); + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2; + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + DBGPRINT(RT_DEBUG_TRACE, ("BW_40 ,control_channel(%d), CentralChannel(%d) \n", + pAd->CommonCfg.Channel, + pAd->CommonCfg.CentralChannel)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + /* 20MHz */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &bbpValue); + bbpValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, bbpValue); + pAd->CommonCfg.BBPCurrentBW = BW_20; + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, ("BW_20, Channel(%d)\n", pAd->CommonCfg.Channel)); + } + + + /* 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")); + } + + /* 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) +{ + if ((strcmp(arg, "WEPAUTO") == 0) || (strcmp(arg, "wepauto") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeAutoSwitch; + else if ((strcmp(arg, "OPEN") == 0) || (strcmp(arg, "open") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + else if ((strcmp(arg, "SHARED") == 0) || (strcmp(arg, "shared") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeShared; + else if ((strcmp(arg, "WPAPSK") == 0) || (strcmp(arg, "wpapsk") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK; + else if ((strcmp(arg, "WPANONE") == 0) || (strcmp(arg, "wpanone") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPANone; + else if ((strcmp(arg, "WPA2PSK") == 0) || (strcmp(arg, "wpa2psk") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK; +#ifdef WPA_SUPPLICANT_SUPPORT + else if ((strcmp(arg, "WPA") == 0) || (strcmp(arg, "wpa") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA; + else if ((strcmp(arg, "WPA2") == 0) || (strcmp(arg, "wpa2") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA2; +#endif /* WPA_SUPPLICANT_SUPPORT */ +#ifdef WAPI_SUPPORT + else if ((strcmp(arg, "WAICERT") == 0) || (strcmp(arg, "waicert") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWAICERT; + else if ((strcmp(arg, "WAIPSK") == 0) || (strcmp(arg, "waipsk") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWAIPSK; +#endif /* WAPI_SUPPORT */ + else + return FALSE; + + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_AuthMode_Proc::(AuthMode=%d)\n", pAd->StaCfg.AuthMode)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Encryption Type + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_EncrypType_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + if ((strcmp(arg, "NONE") == 0) || (strcmp(arg, "none") == 0)) + { + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; /* do nothing */ + + pAd->StaCfg.WepStatus = Ndis802_11WEPDisabled; + pAd->StaCfg.PairCipher = Ndis802_11WEPDisabled; + pAd->StaCfg.GroupCipher = Ndis802_11WEPDisabled; + } + else if ((strcmp(arg, "WEP") == 0) || (strcmp(arg, "wep") == 0)) + { + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; /* do nothing */ + + pAd->StaCfg.WepStatus = Ndis802_11WEPEnabled; + pAd->StaCfg.PairCipher = Ndis802_11WEPEnabled; + pAd->StaCfg.GroupCipher = Ndis802_11WEPEnabled; + } + else if ((strcmp(arg, "TKIP") == 0) || (strcmp(arg, "tkip") == 0)) + { + if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA) + return TRUE; /* do nothing */ + + pAd->StaCfg.WepStatus = Ndis802_11Encryption2Enabled; + pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; + pAd->StaCfg.GroupCipher = Ndis802_11Encryption2Enabled; + } + else if ((strcmp(arg, "AES") == 0) || (strcmp(arg, "aes") == 0)) + { + if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA) + return TRUE; /* do nothing */ + + pAd->StaCfg.WepStatus = Ndis802_11Encryption3Enabled; + pAd->StaCfg.PairCipher = Ndis802_11Encryption3Enabled; + pAd->StaCfg.GroupCipher = Ndis802_11Encryption3Enabled; + } +#ifdef WAPI_SUPPORT + else if ((strcmp(arg, "SMS4") == 0) || (strcmp(arg, "sms4") == 0)) + { + if ((pAd->StaCfg.AuthMode != Ndis802_11AuthModeWAICERT) && + (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWAIPSK)) + return TRUE; /* do nothing */ + + pAd->StaCfg.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.DesiredPhyMode); +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif /* DOT11_N_SUPPORT */ + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_EncrypType_Proc::(EncrypType=%d)\n", pAd->StaCfg.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.DefaultKeyId = (UCHAR) (KeyIdx - 1 ); + else + return FALSE; /*Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_DefaultKeyID_Proc::(DefaultKeyID=%d)\n", pAdapter->StaCfg.DefaultKeyId)); + + 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.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.AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + RTMP_ASIC_SHARED_KEY_TABLE(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.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.AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + RTMP_ASIC_SHARED_KEY_TABLE(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.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.AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + RTMP_ASIC_SHARED_KEY_TABLE(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.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.AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + RTMP_ASIC_SHARED_KEY_TABLE(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( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int status; + + if ((pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) && + (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) && + (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPANone) +#ifdef WAPI_SUPPORT + && (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWAICERT) + && (pAd->StaCfg.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 && + pAd->StaCfg.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; +#ifdef DOT11Z_TDLS_SUPPORT + pAdapter->StaCfg.DefaultListenCount = 1; +#endif // DOT11Z_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.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE; + else if ( simple_strtol(arg, 0, 10) == 1) + pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE; + else if ( simple_strtol(arg, 0, 10) == 2) + pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE_WITH_WEB_UI; + else + pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_Wpa_Support::(WpaSupplicantUP=%d)\n", pAd->StaCfg.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 Wsc_Uuid_Str[UUID_LEN_STR]; + 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)); + 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.AuthMode = Ndis802_11AuthModeWPA2PSK; + pAd->StaCfg.WepStatus = Ndis802_11Encryption3Enabled; + 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 */ + +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", GetPhyMode(pEntry->HTPhyMode.field.MODE)); + sprintf(extra + strlen(extra), "%-6s", GetBW(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; +} + + +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; + + if (pAd->StaCfg.PSPXlink) + Value = PSPXLINK; + else + Value = STANORMAL; + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, Value); + Value = 0; + 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( + IN PRTMP_ADAPTER pAd, + IN PNDIS_802_11_KEY pKey) +{ + ULONG KeyIdx; + MAC_TABLE_ENTRY *pEntry; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddKey ------>\n")); + + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + { + if (pKey->KeyIndex & 0x80000000) + { + if (pAd->StaCfg.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_11Encryption2Enabled) + { + 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_11Encryption2Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) + 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; + + /* Update pairwise key information to ASIC Shared Key Table */ + RTMP_ASIC_SHARED_KEY_TABLE(pAd, + BSS0, + 0, + &pAd->SharedKey[BSS0][0]); + + /* Update ASIC WCID attribute table and IVEIV table */ + RTMPSetWcidSecurityInfo(pAd, + BSS0, + 0, + pAd->SharedKey[BSS0][0].CipherAlg, + BSSID_WCID, + SHAREDKEYTABLE); + + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2) + { + /* set 802.1x port control */ + STA_PORT_SECURED(pAd); + } + } + else + { + /* Update GTK */ + pAd->StaCfg.DefaultKeyId = (pKey->KeyIndex & 0xFF); + NdisZeroMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], sizeof(CIPHER_KEY)); + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = LEN_TK; + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, pKey->KeyMaterial, LEN_TK); +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) + { + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, pKey->KeyMaterial + LEN_TK, LEN_TKIP_MIC); + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, pKey->KeyMaterial + LEN_TK + LEN_TKIP_MIC, LEN_TKIP_MIC); + } + else +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, pKey->KeyMaterial + LEN_TK, LEN_TKIP_MIC); + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, pKey->KeyMaterial + LEN_TK + LEN_TKIP_MIC, LEN_TKIP_MIC); + } + + /* Update Shared Key CipherAlg */ + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_NONE; + if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled) + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES; + + /* Update group key information to ASIC Shared Key Table */ + RTMP_ASIC_SHARED_KEY_TABLE(pAd, + BSS0, + pAd->StaCfg.DefaultKeyId, + &pAd->SharedKey[BSS0][pAd->StaCfg.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->Aid, + &pEntry->PairwiseKey); + + /* update WCID attribute table and IVEIV table for this entry */ + RTMPSetWcidSecurityInfo(pAd, + BSS0, + KeyIdx, + pEntry->PairwiseKey.CipherAlg, + pEntry->Aid, + PAIRWISEKEYTABLE); + } + } + else + { + /* Default key for tx (shared key) */ + pAd->StaCfg.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 */ + RTMP_ASIC_SHARED_KEY_TABLE(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); + +#ifdef P2P_SUPPORT + pAd->P2pCfg.bPeriodicListen = FALSE; +#endif /* P2P_SUPPORT */ + + 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 */ + +#ifdef WOW_SUPPORT +#endif /* WOW_SUPPORT */ + + + +INT RTMPSetInformation( + 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_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 Config, *pConfig = 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 ,kathy */ +#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; +#endif /* SNMP_SUPPORT */ + UCHAR ctmp; + +#ifdef MESH_SUPPORT + BOOLEAN RestartMeshIsRequired = FALSE; +#endif /* MESH_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 */ + + +#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; + UCHAR TmpPhy; + + 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); + TmpPhy = pAd->CommonCfg.PhyMode; + pAd->CommonCfg.PhyMode = 0xff; + /* Build all corresponding channel information */ + RTMPSetPhyMode(pAd, TmpPhy); +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif /* DOT11_N_SUPPORT */ + 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)) && + ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) && + (pAd->StaCfg.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 + { +/* pSsidString = (PSTRING)kmalloc(MAX_LEN_OF_SSID+1, MEM_ALLOC_FLAG); */ + 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: +/* ppassphrase= kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); */ + 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", + Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5])); + } + 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 + { + Status = copy_from_user(&PhyMode, wrq->u.data.pointer, wrq->u.data.length); + if (PhyMode <= MaxPhyMode) + { + pAd->CommonCfg.DesiredPhyMode = PhyMode; + RTMPSetPhyMode(pAd, PhyMode); +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif /* DOT11_N_SUPPORT */ + } + 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) + { + pAd->CommonCfg.PhyMode = StaConfig.AdhocMode; + RTMPSetPhyMode(pAd, pAd->CommonCfg.PhyMode); + 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)); + +#ifdef XLINK_SUPPORT + if (pAd->StaCfg.PSPXlink) + Value = PSPXLINK; + else +#endif /* XLINK_SUPPORT */ + Value = STANORMAL; + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, Value); + } + 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.WepStatus != WepStatus) + { + /* Config has changed */ + pAd->bConfigChanged = TRUE; + } + pAd->StaCfg.WepStatus = WepStatus; + pAd->StaCfg.PairCipher = WepStatus; + pAd->StaCfg.GroupCipher = WepStatus; + + if (pAd->StaCfg.BssType == BSS_ADHOC) + { + /* Build all corresponding channel information */ + RTMPSetPhyMode(pAd, pAd->CommonCfg.DesiredPhyMode); +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif /* DOT11_N_SUPPORT */ + } + } + 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 (pAd->StaCfg.AuthMode != AuthMode) + { + /* Config has changed */ + pAd->bConfigChanged = TRUE; + } + pAd->StaCfg.AuthMode = AuthMode; + } + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_AUTHENTICATION_MODE (=%d) \n",pAd->StaCfg.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, PHY_11B); + else if (NetType == Ndis802_11OFDM24) + RTMPSetPhyMode(pAd, PHY_11BG_MIXED); + else if (NetType == Ndis802_11OFDM5) + RTMPSetPhyMode(pAd, PHY_11A); + else + Status = -EINVAL; +#ifdef DOT11_N_SUPPORT + if (Status == NDIS_STATUS_SUCCESS) + SetCommonHT(pAd); +#endif /* DOT11_N_SUPPORT */ + 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: +/* pKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); */ + 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 ((pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) && + (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) && + (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPANone) ) + { + Status = -EOPNOTSUPP; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA, Failed!! [AuthMode != WPAPSK/WPA2PSK/WPANONE]\n")); + } + else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) || + (pAd->StaCfg.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 (pAd->StaCfg.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); +/* kfree(pKey); */ + break; + case OID_802_11_REMOVE_KEY: +/* pRemoveKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); */ + 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 (pAd->StaCfg.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); +/* kfree(pRemoveKey); */ + break; + /* New for WPA */ + case OID_802_11_ADD_KEY: +/* pKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); */ + 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); +/* kfree(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 (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + RTMPSetHT(pAd, pHTPhyMode); + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_HT_PHYMODE(MCS=%d,BW=%d,SGI=%d,STBC=%d)\n", + pAd->StaCfg.HTPhyMode.field.MCS, pAd->StaCfg.HTPhyMode.field.BW, pAd->StaCfg.HTPhyMode.field.ShortGI, + pAd->StaCfg.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; + +/* pBA = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); */ + 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); +/* kfree(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->Aid, 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->Aid, pBA->TID, TRUE); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("Set :: Not found pEntry \n")); + } + os_free_mem(NULL, pBA); +/* kfree(pBA); */ + } + } + break; +#endif /* DOT11_N_SUPPORT */ + + /* For WPA_SUPPLICANT to set static wep key */ + case OID_802_11_ADD_WEP: +/* pWepKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); */ + 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.DesireSharedKey[KeyIdx], sizeof(CIPHER_KEY)); + + /* set key material and key length */ + pAd->StaCfg.DesireSharedKey[KeyIdx].KeyLen = (UCHAR) pWepKey->KeyLength; + NdisMoveMemory(pAd->StaCfg.DesireSharedKey[KeyIdx].Key, &pWepKey->KeyMaterial, pWepKey->KeyLength); + pAd->StaCfg.DesireSharedKeyId = KeyIdx; + pAd->StaCfg.DesireSharedKey[KeyIdx].CipherAlg = CipherAlg; +#endif /* WPA_SUPPLICANT_SUPPORT */ + pAd->StaCfg.DefaultKeyId = (UCHAR) KeyIdx; + } + +#ifdef WPA_SUPPLICANT_SUPPORT + if ((pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) && + (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)) + { + Key = pWepKey->KeyMaterial; + + /* Set Group key material to Asic */ + RTMP_ASIC_SHARED_KEY_TABLE(pAd, + BSS0, + KeyIdx, + &pAd->SharedKey[BSS0][KeyIdx]); + + STA_PORT_SECURED(pAd); + } + else if (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED) +#endif /* WPA_SUPPLICANT_SUPPORT */ + { + Key = pAd->SharedKey[BSS0][KeyIdx].Key; + + /* Set key material and cipherAlg to Asic */ + RTMP_ASIC_SHARED_KEY_TABLE(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), %s\n", pWepKey->KeyIndex, pWepKey->KeyLength, (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED) ? "Port Secured":"Port NOT Secured")); + } + } + os_free_mem(NULL, pWepKey); +/* kfree(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.WpaSupplicantUP |= WPA_SUPPLICANT_ENABLE_WPS; + else + { + pAd->StaCfg.WpaSupplicantUP = wpa_supplicant_enable; + pAd->StaCfg.WpaSupplicantUP &= 0x7F; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_WPA_SUPPLICANT_SUPPORT (=0x%02X)\n", pAd->StaCfg.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;/* = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); */ + 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); +/* kfree(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.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + else + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + NdisAcquireSpinLock(&pAd->MacTabLock); + pAd->MacTab.Content[BSSID_WCID].PortSecured = pAd->StaCfg.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.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.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: +/* pPmkId = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); */ + 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) +/* kfree(pPmkId); */ + os_free_mem(NULL, pPmkId); + break; + + case RT_OID_WPS_PROBE_REQ_IE: + if (pAd->StaCfg.pWpsProbeReqIe) + { +/* kfree(pAd->StaCfg.pWpsProbeReqIe); */ + os_free_mem(NULL, pAd->StaCfg.pWpsProbeReqIe); + pAd->StaCfg.pWpsProbeReqIe = NULL; + } + pAd->StaCfg.WpsProbeReqIeLen = 0; +/* pAd->StaCfg.pWpsProbeReqIe = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); */ + os_alloc_mem(pAd, (UCHAR **)&(pAd->StaCfg.pWpsProbeReqIe), wrq->u.data.length); + if (pAd->StaCfg.pWpsProbeReqIe) + { + Status = copy_from_user(pAd->StaCfg.pWpsProbeReqIe, wrq->u.data.pointer, wrq->u.data.length); + + if (Status) + { + Status = -EINVAL; + if (pAd->StaCfg.pWpsProbeReqIe) + { +/* kfree(pAd->StaCfg.pWpsProbeReqIe); */ + os_free_mem(NULL, pAd->StaCfg.pWpsProbeReqIe); + pAd->StaCfg.pWpsProbeReqIe = NULL; + } + pAd->StaCfg.WpsProbeReqIeLen = 0; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_WPS_PROBE_REQ_IE, Failed (copy_from_user failed)!!\n")); + } + else + { + pAd->StaCfg.WpsProbeReqIeLen = wrq->u.data.length; + hex_dump("WpsProbeReqIe", pAd->StaCfg.pWpsProbeReqIe, pAd->StaCfg.WpsProbeReqIeLen); + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_WPS_PROBE_REQ_IE, WpsProbeReqIeLen = %d!!\n", + pAd->StaCfg.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 = kmalloc(msgLen, GFP_KERNEL)) == NULL) */ + 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; + } + } + +/* kfree(pUPnPMsg); */ + 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); + 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: + 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; + 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; */ + } +/* kfree(pKey); */ + 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; + +#endif /* SNMP_SUPPORT */ + + 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; + +#ifdef MESH_SUPPORT + case OID_802_11_MESH_SECURITY_INFO: + Status = RTMPIoctlSetMeshSecurityInfo(pAd, wrq); + if (Status == NDIS_STATUS_SUCCESS) + RestartMeshIsRequired = TRUE; + break; + + case OID_802_11_MESH_ID: + if (wrq->u.data.length >= MAX_MESH_ID_LEN) + { + Status = -EINVAL; + break; + } + + { + UCHAR MeshID[MAX_MESH_ID_LEN]; + + NdisZeroMemory(pAd->MeshTab.MeshId, MAX_MESH_ID_LEN); + + Status = copy_from_user(&MeshID,wrq->u.data.pointer, wrq->u.data.length); + NdisMoveMemory(&pAd->MeshTab.MeshId, MeshID, wrq->u.data.length); + pAd->MeshTab.MeshIdLen = (UCHAR)wrq->u.data.length; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_MESH_ID (=%s)\n", pAd->MeshTab.MeshId)); + RestartMeshIsRequired = TRUE; + } + break; + + case OID_802_11_MESH_AUTO_LINK: + if (wrq->u.data.length != 1) + { + Status = -EINVAL; + break; + } + + { + UCHAR Enable = TRUE; + + Status = copy_from_user(&Enable, wrq->u.data.pointer, wrq->u.data.length); + pAd->MeshTab.MeshAutoLink = (Enable > 0) ? TRUE : FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_MESH_AUTO_LINK (=%s)\n", + pAd->MeshTab.MeshAutoLink == TRUE ? "Enable" : "Disable")); + } + break; + + case OID_802_11_MESH_ADD_LINK: + if (wrq->u.data.length != MAC_ADDR_LEN) + { + Status = -EINVAL; + break; + } + + { + UCHAR MacAddr[MAC_ADDR_LEN]; + UINT LinkIdx; + + Status = copy_from_user(&MacAddr, wrq->u.data.pointer, MAC_ADDR_LEN); + LinkIdx = GetMeshLinkId(pAd, (PCHAR)MacAddr); + if (LinkIdx == BSS_NOT_FOUND) + { + LinkIdx = MeshLinkAlloc(pAd, MacAddr, MESH_LINK_STATIC); + if (LinkIdx == BSS_NOT_FOUND) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() All Mesh-Links been occupied.\n", __FUNCTION__)); + return FALSE; + } + } + + if (!VALID_MESH_LINK_ID(LinkIdx)) + break; + + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_ACTOPN, 0, NULL, LinkIdx); + DBGPRINT(RT_DEBUG_TRACE, ("%s::(LinkIdx = %d)\n", __FUNCTION__, LinkIdx)); + } + break; + + case OID_802_11_MESH_DEL_LINK: + if (wrq->u.data.length != MAC_ADDR_LEN) + { + Status = -EINVAL; + break; + } + + { + UCHAR MacAddr[MAC_ADDR_LEN]; + UINT LinkIdx; + + Status = copy_from_user(&MacAddr, wrq->u.data.pointer, MAC_ADDR_LEN); + LinkIdx = GetMeshLinkId(pAd, (PCHAR)MacAddr); + if (!VALID_MESH_LINK_ID(LinkIdx)) + break; + + pAd->MeshTab.MeshLink[LinkIdx].Entry.LinkType = MESH_LINK_DYNAMIC; + MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_CNCL, 0, NULL, LinkIdx); + DBGPRINT(RT_DEBUG_TRACE, ("%s::(LinkIdx = %d)\n", __FUNCTION__, LinkIdx)); + } + break; + + case OID_802_11_MESH_MAX_TX_RATE: + if (wrq->u.data.length != 1) + { + Status = -EINVAL; + break; + } + + { + UCHAR TxRate; + + Status = copy_from_user(&TxRate, wrq->u.data.pointer, wrq->u.data.length); + if (TxRate <= 12) + pAd->MeshTab.MeshMaxTxRate = TxRate; + else + pAd->MeshTab.MeshMaxTxRate = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_MESH_MAX_TX_RATE (=%ld)\n", + pAd->MeshTab.MeshMaxTxRate)); + } + break; + + case OID_802_11_MESH_CHANNEL: + if (wrq->u.data.length != 1) + { + Status = -EINVAL; + break; + } + { + UCHAR Channel; + + if (INFRA_ON(pAd) || ADHOC_ON(pAd)) + { + Status = -EINVAL; + break; + } + + Status = copy_from_user(&Channel, wrq->u.data.pointer, wrq->u.data.length); + if (pAd->MeshTab.UCGEnable == TRUE) + { + pAd->MeshTab.MeshChannel = Channel; + MlmeEnqueue(pAd, MESH_CTRL_STATE_MACHINE, MESH_CTRL_UCG_EVT, 0, NULL, 0); + } + else + { + pAd->MeshTab.MeshChannel = pAd->CommonCfg.Channel = Channel; +#ifdef DOT11_N_SUPPORT + N_ChannelCheck(pAd); + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && + pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + { + N_SetCenCh(pAd); + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + DBGPRINT(RT_DEBUG_TRACE, ("BW_40, control_channel(%d), CentralChannel(%d) \n", + pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, ("BW_20, Channel(%d)\n", pAd->CommonCfg.Channel)); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_MESH_CHANNEL (=%d)\n", (int)Channel)); + } + break; + + case OID_802_11_MESH_HOSTNAME: + if (wrq->u.data.length >= MAX_HOST_NAME_LEN) + { + Status = -EINVAL; + break; + } + + { + NdisZeroMemory(pAd->MeshTab.HostName, MAX_HOST_NAME_LEN); + Status = copy_from_user(pAd->MeshTab.HostName, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_HOSTNAME_ID (=%s)\n", pAd->MeshTab.HostName)); + } + break; + + case OID_802_11_MESH_ONLY_MODE: + if (wrq->u.data.length != 1) + { + Status = -EINVAL; + break; + } + { + UCHAR Enable; + + Status = copy_from_user(&Enable, wrq->u.data.pointer, wrq->u.data.length); + + pAd->MeshTab.MeshOnly = (Enable == 1 ? TRUE : FALSE); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_MESH_ONLY_MODE (=%s)\n", pAd->MeshTab.MeshOnly == TRUE ? "Enable" : "Disable")); + } + break; + + case OID_802_11_MESH_CHANNEL_BW: + if (wrq->u.data.length != 1) + { + Status = -EINVAL; + break; + } + { + UCHAR HtBw; + + Status = copy_from_user(&HtBw, wrq->u.data.pointer, wrq->u.data.length); + + if (INFRA_ON(pAd) || ADHOC_ON(pAd)) + { + Status = -EINVAL; + break; + } + +#ifdef DOT11_N_SUPPORT + if (HtBw == BW_40) + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; + else if (HtBw == BW_20) +#endif /* DOT11_N_SUPPORT */ + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + + if ((pAd->CommonCfg.PhyMode <= PHY_11G) + && (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)) + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + DBGPRINT(RT_DEBUG_TRACE, ("40MHz BW in not valid in Legacy mode\n")); + Status = -EINVAL; + break; + } +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif /* DOT11_N_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_MESH_CHANNEL_BW (=%d)\n", pAd->CommonCfg.RegTransmitSetting.field.BW)); + } + break; + + case OID_802_11_MESH_CHANNEL_OFFSET: + if (wrq->u.data.length != 1) + { + Status = -EINVAL; + break; + } + { + UCHAR ChOffset; + + if (INFRA_ON(pAd) || ADHOC_ON(pAd)) + { + Status = -EINVAL; + break; + } + + Status = copy_from_user(&ChOffset, wrq->u.data.pointer, wrq->u.data.length); + + if (pAd->CommonCfg.PhyMode <= PHY_11G) + { + DBGPRINT(RT_DEBUG_TRACE, ("Channel offset in not valid in Legacy mode\n")); + Status = -EINVAL; + break; + } + +#ifdef DOT11_N_SUPPORT + if (ChOffset == 0) + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; + else if ( ChOffset ==1 ) + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; + + SetCommonHT(pAd); +#endif /* DOT11_N_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_MESH_CHANNEL_OFFSET (=%d)\n", pAd->CommonCfg.RegTransmitSetting.field.EXTCHA)); + } + break; + + case OID_802_11_MESH_FORWARD: + if (wrq->u.data.length != 1) + { + Status = -EINVAL; + break; + } + + { + UCHAR Enable = TRUE; + + Status = copy_from_user(&Enable, wrq->u.data.pointer, wrq->u.data.length); + pAd->MeshTab.MeshCapability.field.Forwarding = (Enable > 0) ? TRUE : FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_MESH_FORWARD (=%s)\n", + pAd->MeshTab.MeshCapability.field.Forwarding == TRUE ? "Enable" : "Disable")); + } + break; +#endif /* MESH_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 */ + + + + default: + DBGPRINT(RT_DEBUG_TRACE, ("Set::unknown IOCTL's subcmd = 0x%08x\n", cmd)); + Status = -EOPNOTSUPP; + break; + } + +#ifdef MESH_SUPPORT + /* important parameter is changed, restart mesh */ + if (RestartMeshIsRequired) + { + MeshDown(pAd, TRUE); + MeshUp(pAd); + } +#endif /* MESH_SUPPORT */ + + 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 + /*for snmp, kathy */ + DefaultKeyIdxValue *pKeyIdxValue; + INT valueLen; + TX_RTY_CFG_STRUC tx_rty_cfg; + ULONG ShortRetryLimit, LongRetryLimit; + UCHAR tmp[64]; +#endif /*SNMP */ + + +#ifdef P2P_SUPPORT + PRT_P2P_UI_TABLE pUI_table; + PRT_P2P_TABLE pP2pTable; + PRT_P2P_CLIENT_ENTRY pPAdCli, pUICli; + PRT_P2P_CONFIG pP2PCtrl; /* = &pAd->P2pCfg; */ + UCHAR tmpP2P[24]; +#endif /* P2P_SUPPORT */ + + + 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.WpaSupplicantUP & 0x7F) == WPA_SUPPLICANT_ENABLE) + { + pAd->StaCfg.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 */ +/* pBuf = kmalloc(BssBufSize, MEM_ALLOC_FLAG); */ + 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 ((pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) && (pAd->StaCfg.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) + { +/* kfree(pBssidList); */ + os_free_mem(NULL, pBssidList); + return -E2BIG; + } + else + wrq->u.data.length = BssLen; + } + + Status = copy_to_user(wrq->u.data.pointer, pBssidList, BssLen); +/* kfree(pBssidList); */ + 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: +/* pLinkStatus = (RT_802_11_LINK_STATUS *) kmalloc(sizeof(RT_802_11_LINK_STATUS), MEM_ALLOC_FLAG); */ + 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); +/* kfree(pLinkStatus); */ + 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: +/* pConfiguration = (NDIS_802_11_CONFIGURATION *) kmalloc(sizeof(NDIS_802_11_CONFIGURATION), MEM_ALLOC_FLAG); */ + 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)); +/* kfree(pConfiguration); */ + 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 */ + +#if defined(RT2883) || defined(RT3883) + case RT_OID_802_11_STREAM_SNR: + { + long StreamSnr[3]; + StreamSnr[0] = pAd->StaCfg.BF_SNR[0]; + StreamSnr[1] = pAd->StaCfg.BF_SNR[1]; + StreamSnr[2] = pAd->StaCfg.BF_SNR[2]; + wrq->u.data.length = sizeof(StreamSnr); + Status = copy_to_user(wrq->u.data.pointer, &StreamSnr, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE,("Query::RT_OID_802_11_STR_SNR(0x=%ld, %ld)\n", StreamSnr[0], StreamSnr[1])); + } + break; + +#endif /* defined(RT2883) || defined(RT3883) */ + + 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: +/* 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); + + /* 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); +/* kfree(pStatistics); */ + os_free_mem(NULL, pStatistics); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_STATISTICS(kmalloc 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); + kfree(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: +/* pStaConfig = (RT_802_11_STA_CONFIG *) kmalloc(sizeof(RT_802_11_STA_CONFIG), MEM_ALLOC_FLAG); */ + 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); +/* kfree(pStaConfig); */ + os_free_mem(NULL, pStaConfig); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(kmalloc 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.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.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 (pAd->CommonCfg.PhyMode == PHY_11A) + ulInfo = Ndis802_11OFDM5; + else if ((pAd->CommonCfg.PhyMode == PHY_11BG_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11G)) + 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; + getRate(HTPhyMode, &RateValue); + 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; + getRate(HTPhyMode, &RateValue); + 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.WpaSupplicantUP, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WPA_SUPPLICANT_SUPPORT (=%d)\n", pAd->StaCfg.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); +/* 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_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")); + } + +/* kfree(pProfile); */ + 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); +/* 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; + } + + 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); + } +#ifdef DPA_S + NdisMoveMemory(pProfile->Profile[0].MacAddr, pAd->MlmeAux.Bssid, MAC_ADDR_LEN); +#endif /* DPA_S */ + 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")); + } + +/* kfree(pProfile); */ + 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: +/* pHTPhyMode = (OID_SET_HT_PHYMODE *) kmalloc(sizeof(OID_SET_HT_PHYMODE), MEM_ALLOC_FLAG); */ + 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, (" MlmeUpdateTxRates (.word = %x )\n", pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word)); +/* kfree(pHTPhyMode); */ + os_free_mem(NULL, pHTPhyMode); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(kmalloc 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: +/* pHTPhyMode = (OID_SET_HT_PHYMODE *) kmalloc(sizeof(OID_SET_HT_PHYMODE), MEM_ALLOC_FLAG); */ + os_alloc_mem(pAd, (UCHAR **)&pHTPhyMode, sizeof(OID_SET_HT_PHYMODE)); + if (pHTPhyMode) + { + pHTPhyMode->PhyMode = pAd->CommonCfg.PhyMode; + pHTPhyMode->HtMode = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.HTMODE; + pHTPhyMode->BW = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.BW; + pHTPhyMode->MCS= (UCHAR)pAd->StaCfg.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, (" MlmeUpdateTxRates (.word = %x )\n", pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word)); +/* kfree(pHTPhyMode); */ + os_free_mem(NULL, pHTPhyMode); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(kmalloc 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); + 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)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; + +#endif /*SNMP_SUPPORT */ + + 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 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; + } + +/* pChListBuf = (RT_CHANNEL_LIST_INFO *) kmalloc(sizeof(RT_CHANNEL_LIST_INFO), MEM_ALLOC_FLAG); */ + 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) +/* kfree(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 P2P_SUPPORT + case OID_802_11_P2P_MODE: + wrq->u.data.length = sizeof(char); + Status = copy_to_user(wrq->u.data.pointer, &pAd->P2pCfg.Rule, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_MODE (Len=%d, Rule=%s)\n", sizeof(char),pAd->P2pCfg.Rule)); + break; + + case OID_802_11_P2P_DEVICE_NAME: + wrq->u.data.length = pAd->P2pCfg.DeviceNameLen; + Status = copy_to_user(wrq->u.data.pointer, pAd->P2pCfg.DeviceName, pAd->P2pCfg.DeviceNameLen); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_DEVICE_NAME (Len=%d, DeviceName=%s)\n", pAd->P2pCfg.DeviceNameLen,pAd->P2pCfg.DeviceName)); + break; + + case OID_802_11_P2P_LISTEN_CHANNEL: + wrq->u.data.length = sizeof(char); + Status = copy_to_user(wrq->u.data.pointer, &pAd->P2pCfg.ListenChannel, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_LISTEN_CHANNEL (Len=%d, Listen_Ch=%d)\n", sizeof(char),pAd->P2pCfg.ListenChannel)); + break; + + case OID_802_11_P2P_OPERATION_CHANNEL: + wrq->u.data.length = sizeof(char); + Status = copy_to_user(wrq->u.data.pointer, &pAd->P2pCfg.GroupChannel, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_OPERATION_CHANNEL (Len=%d, Op_Ch=%d)\n", sizeof(char),pAd->P2pCfg.GroupOpChannel)); + break; + + + case OID_802_11_P2P_DEV_ADDR: + wrq->u.data.length = 6; + Status = copy_to_user(wrq->u.data.pointer, pAd->P2pCfg.Bssid, wrq->u.data.length); + /*DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_MAC_ADDR (Len=%d, Rule=%s)\n", sizeof(char),pAd->P2pCfg.GroupOpChannel)); */ + break; + + case OID_802_11_P2P_CTRL_STATUS: + wrq->u.data.length = 24; + pP2PCtrl = &pAd->P2pCfg; + NdisZeroMemory(tmpP2P, 24); + sprintf(tmpP2P, "%s",decodeCtrlState(pP2PCtrl->CtrlCurrentState)); + Status = copy_to_user(wrq->u.data.pointer, tmpP2P, 24); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_MODE (Len=%d, DeviceName=%s)\n", pAd->P2pCfg.DeviceNameLen,pAd->P2pCfg.DeviceName)); + break; + + case OID_802_11_P2P_DISC_STATUS: + wrq->u.data.length = 24; + pP2PCtrl = &pAd->P2pCfg; + NdisZeroMemory(tmpP2P, 24); + sprintf(tmpP2P, "%s",decodeDiscoveryState(pP2PCtrl->DiscCurrentState)); + Status = copy_to_user(wrq->u.data.pointer, tmpP2P, 24); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_MODE (Len=%d, DeviceName=%s)\n", pAd->P2pCfg.DeviceNameLen,pAd->P2pCfg.DeviceName)); + break; + + case OID_802_11_P2P_GOFORM_STATUS: + wrq->u.data.length = 24; + pP2PCtrl = &pAd->P2pCfg; + NdisZeroMemory(tmpP2P, 24); + sprintf(tmpP2P, "%s",decodeGroupFormationState(pP2PCtrl->GoFormCurrentState)); + Status = copy_to_user(wrq->u.data.pointer, tmpP2P, 24); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_MODE (Len=%d, DeviceName=%s)\n", pAd->P2pCfg.DeviceNameLen,pAd->P2pCfg.DeviceName)); + break; + + case OID_802_11_P2P_SCAN_LIST: + os_alloc_mem(NULL, (UCHAR **)&pUI_table, sizeof(RT_P2P_UI_TABLE)); + if (pUI_table) + { + pP2pTable = &pAd->P2pTable; + NdisZeroMemory(pUI_table, sizeof(RT_P2P_UI_TABLE)); + pUI_table->ClientNumber = pAd->P2pTable.ClientNumber; + for (i=0; i < pAd->P2pTable.ClientNumber; i++) + { + pPAdCli = &pP2pTable->Client[i]; + pUICli = &pUI_table->Client[i]; + NdisMoveMemory(pUICli, pPAdCli, sizeof(RT_P2P_CLIENT_ENTRY)); + } + printk("Query::OID_802_11_P2P_SCAN_LIST\n"); + Status = copy_to_user(wrq->u.data.pointer, pUI_table, sizeof(RT_P2P_UI_TABLE)); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_SCAN_LIST (Len=%d, Rule=%s)\n", sizeof(char),pAd->P2pCfg.GroupOpChannel)); + os_free_mem(NULL, pUI_table); + } + else + { + Status = -ENOMEM; + } + break; + + case OID_P2P_WSC_PIN_CODE: + wrq->u.data.length = sizeof(UINT); + WscPinCode = pAd->ApCfg.ApCliTab[0].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; +#endif /* P2P_SUPPORT */ + +#ifdef MESH_SUPPORT + case OID_802_11_MESH_DEVICENAME: + if (pAd->MeshTab.dev) + { + wrq->u.data.length = strlen(RtmpOsGetNetDevName(pAd->MeshTab.dev)) + 1; + Status = copy_to_user(wrq->u.data.pointer, RtmpOsGetNetDevName(pAd->MeshTab.dev), strlen(RtmpOsGetNetDevName(pAd->MeshTab.dev))); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_DEVICENAME (Len=%d, Name=%s)\n", wrq->u.data.length, RtmpOsGetNetDevName(pAd->MeshTab.dev))); + } + break; + + case OID_802_11_MESH_SECURITY_INFO: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_SECURITY_INFO \n")); + if (wrq->u.data.length != sizeof(MESH_SECURITY_INFO)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Len Diff %d/%d \n", wrq->u.data.length, sizeof(MESH_SECURITY_INFO))); + Status = -EINVAL; + } + else + RTMPIoctlQueryMeshSecurityInfo(pAd, wrq); + break; + + case OID_802_11_MESH_ID: + wrq->u.data.length = pAd->MeshTab.MeshIdLen; + Status = copy_to_user(wrq->u.data.pointer, &pAd->MeshTab.MeshId, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_ID (Len=%d, MeshID=%s)\n", pAd->MeshTab.MeshIdLen, + pAd->MeshTab.MeshId)); + break; + + case OID_802_11_MESH_AUTO_LINK: + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &pAd->MeshTab.MeshAutoLink, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_AUTO_LINK (=%d)\n", pAd->MeshTab.MeshAutoLink)); + break; + + case OID_802_11_MESH_LINK_STATUS: + { + MESH_LINK_INFO MeshLinkInfo; + UCHAR i; + + NdisZeroMemory(&MeshLinkInfo, sizeof(MESH_LINK_INFO)); + + for (i=0; iMeshTab.MeshLink[i].Entry; + + COPY_MAC_ADDR(MeshLinkInfo.Entry[i].PeerMacAddr, pEntry->PeerMacAddr); + MeshLinkInfo.Entry[i].LinkType = pEntry->LinkType; + MeshLinkInfo.Entry[i].Status = PeerLinkValidCheck(pAd, i); + MeshLinkInfo.Entry[i].Rssi = + RTMPMaxRssi(pAd, pAd->MacTab.Content[pEntry->MacTabMatchWCID].RssiSample.AvgRssi0, + pAd->MacTab.Content[pEntry->MacTabMatchWCID].RssiSample.AvgRssi1, + pAd->MacTab.Content[pEntry->MacTabMatchWCID].RssiSample.AvgRssi2); + MeshLinkInfo.Entry[i].CurTxRate = pAd->MacTab.Content[pEntry->MacTabMatchWCID].HTPhyMode; + } + + wrq->u.data.length = sizeof(MESH_LINK_INFO); + Status = copy_to_user(wrq->u.data.pointer, &MeshLinkInfo, wrq->u.data.length); + } + break; + + case OID_802_11_MESH_LIST: + { + PMESH_NEIGHBOR_INFO pMeshNeighborInfo;/* = kmalloc(sizeof(MESH_NEIGHBOR_INFO), GFP_ATOMIC); */ + UCHAR i, idx = 0; + + os_alloc_mem(pAd, (UCHAR **)&pMeshNeighborInfo, sizeof(MESH_NEIGHBOR_INFO)); + if (pMeshNeighborInfo == NULL) + break; + + NdisZeroMemory(pMeshNeighborInfo, sizeof(MESH_NEIGHBOR_INFO)); + for (i=0; iMeshTab.pMeshNeighborTab->NeighborMP[i]; + + if (pEntry->Valid) + { + strcpy((PSTRING) pMeshNeighborInfo->Entry[idx].HostName,(PSTRING) pEntry->HostName); + COPY_MAC_ADDR(pMeshNeighborInfo->Entry[idx].MacAddr, pEntry->PeerMac); + strcpy((PSTRING) pMeshNeighborInfo->Entry[idx].MeshId,(PSTRING) pEntry->MeshId); + pMeshNeighborInfo->Entry[idx].Channel = pEntry->Channel; + pMeshNeighborInfo->Entry[idx].Rssi = pEntry->RealRssi; + pMeshNeighborInfo->Entry[idx].Status = pEntry->State != LINK_AVAILABLE ? 0 : 1; + pMeshNeighborInfo->Entry[idx].MeshEncrypType = + MeshCheckPeerMpCipher(pEntry->CapabilityInfo, pEntry->RSNIE, pEntry->RSNIE_Len);; + idx++; + } + } + pMeshNeighborInfo->num = idx; + wrq->u.data.length = sizeof(MESH_NEIGHBOR_INFO); + Status = copy_to_user(wrq->u.data.pointer, pMeshNeighborInfo, wrq->u.data.length); + + if (pMeshNeighborInfo) +/* kfree(pMeshNeighborInfo); */ + os_free_mem(NULL, pMeshNeighborInfo); + } + break; + + case OID_802_11_MESH_ROUTE_LIST: + { + PRT_MESH_ROUTE_TABLE rt_table;/* = kmalloc(sizeof(RT_MESH_ROUTE_TABLE), GFP_ATOMIC); */ + UCHAR i; + + os_alloc_mem(pAd, (UCHAR **)&rt_table, sizeof(RT_MESH_ROUTE_TABLE)); + if (rt_table == NULL) + break; + + NdisZeroMemory(rt_table, sizeof(RT_MESH_ROUTE_TABLE)); + + for (i=0; iMeshTab.pMeshRouteTab->Content[i]; + + if (pEntry->Valid) + { + COPY_MAC_ADDR(rt_table->Entry[rt_table->Num].MeshDA, pEntry->MeshDA); + rt_table->Entry[rt_table->Num].Dsn = pEntry->Dsn; + COPY_MAC_ADDR(rt_table->Entry[rt_table->Num].NextHop, pEntry->NextHop); + rt_table->Entry[rt_table->Num].Metric = pEntry->PathMetric; + rt_table->Num++; + } + } + + wrq->u.data.length = sizeof(RT_MESH_ROUTE_TABLE); + Status = copy_to_user(wrq->u.data.pointer, rt_table, wrq->u.data.length); + + if (rt_table) +/* kfree(rt_table); */ + os_free_mem(NULL, rt_table); + + DBGPRINT(RT_DEBUG_OFF, ("Query::OID_802_11_MESH_ROUTE_LIST \n")); + } + break; + + case OID_802_11_MESH_MAX_TX_RATE: + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &pAd->MeshTab.MeshMaxTxRate, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_CHANNEL (=%d)\n", pAd->MeshTab.MeshChannel)); + break; + + case OID_802_11_MESH_CHANNEL: + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &pAd->MeshTab.MeshChannel, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_CHANNEL (=%d)\n", pAd->MeshTab.MeshChannel)); + break; + + case OID_802_11_MESH_HOSTNAME: + wrq->u.data.length = strlen((PSTRING) pAd->MeshTab.HostName) + 1; + Status = copy_to_user(wrq->u.data.pointer, &pAd->MeshTab.HostName, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_HOSTNAME (MeshHostName=%s)\n", pAd->MeshTab.HostName)); + break; + + case OID_802_11_MESH_ONLY_MODE: + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &pAd->MeshTab.MeshOnly, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_ONLY_MODE (=%s)\n", pAd->MeshTab.MeshOnly == TRUE ? "Enable" : "Disable")); + break; + case OID_802_11_MESH_CHANNEL_BW: + { + UCHAR Value = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.BW; + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &Value, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_ONLY_MODE (=%s)\n", + pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40 ? "BW40" : "BW20")); + } + break; + + case OID_802_11_MESH_CHANNEL_OFFSET: + { + UCHAR Value = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_BELOW ? 0 : 1; + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &Value, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MESH_ONLY_MODE (=%s)\n", + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_BELOW ? "BELOW" : "ABOVE")); + } + break; +#endif /* MESH_SUPPORT */ + +#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;/* = kmalloc(sizeof(RT_802_11_DLS_INFO), GFP_ATOMIC); */ + 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) +/* kfree(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 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 WAC_SUPPORT + case RT_OID_WAC_REQ: + if (wrq->u.data.length < sizeof(WAC_REQUEST)) + { + Status = -EINVAL; + } + else + { + WAC_IoctlReq(pAd, BSS0, wrq); + } + break; +#endif /* WAC_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 */ + 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 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; + ULONG macAddr = 0; + UCHAR temp[16]; + STRING temp2[16]; + UINT32 macValue = 0; + INT Status; + BOOLEAN bIsPrintAllMAC = 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); + 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 */ + /* 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; + } + + /* 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=%lx, MacValue=%x\n", macAddr, macValue)); + sprintf(msg+strlen(msg), "[0x%08lX]:%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*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 R17 tuning, 0: disable R17 tuning */ + if (macValue & 0x000000ff) + { + pAd->BbpTuning.bEnable = TRUE; + DBGPRINT(RT_DEBUG_TRACE,("turn on R17 tuning\n")); + } + else + { +/* UCHAR R66; */ + pAd->BbpTuning.bEnable = FALSE; + + RTMP_CHIP_RX_SENSITIVITY_TUNING(pAd); + } + goto LabelOK; + } + + DBGPRINT(RT_DEBUG_TRACE, ("MacAddr=%02lx, MacValue=0x%x\n", macAddr, macValue)); + + RTMP_IO_WRITE32(pAd, macAddr, macValue); + sprintf(msg+strlen(msg), "[0x%08lX]:%08X ", macAddr, macValue); + } + } + } + else + bIsPrintAllMAC = TRUE; +next: + if (bIsPrintAllMAC) + { + UINT32 *pBufMac = NULL, *pBuf; + /* Note: AddrEnd must >= AddrStart */ + UINT32 AddrStart = 0x1000, AddrEnd = 0x1800; + UINT32 IdAddr; + + /* *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); + 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 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; + + + maxRFIdx = pAd->chipCap.MaxNumOfRfId; + + +/* mpool = (CHAR *) kmalloc(sizeof(CHAR)*(2048+256+12), MEM_ALLOC_FLAG); */ + 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), "%03d = %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__)); + } + } + +/* kfree(mpool); */ + os_free_mem(NULL, mpool); + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlRF\n\n")); +} +#endif /* RTMP_RF_RW_SUPPORT */ +#endif /* DBG */ + + +VOID RTMPIoctlBbp( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN CHAR *extra, + IN UINT32 size) +{ + PSTRING this_char; + PSTRING value = NULL; + UCHAR regBBP = 0; +/* CHAR arg[255]={0}; */ + UINT32 bbpId; + UINT32 bbpValue; + BOOLEAN bIsPrintAllBBP = FALSE; + + 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)); + } +} + + + + +#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; + +#ifdef MESH_SUPPORT + if (pIoctlShow->InfType == INT_MESH) + { + pObj->ioctl_if_type = INT_MESH; + pObj->ioctl_if = 0; + } + else +#endif /* MESH_SUPPORT */ + { + 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 (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && + 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__ ); +#ifdef MESH_SUPPORT + sprintf(extra+strlen(extra), "Support MESH \n"); +#endif /* MESH_SUPPORT */ + 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) + { + 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) + { + 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 MESH_SUPPORT + case SHOW_MESH_INFO: + { + Set_MeshInfo_Display_Proc(pAd, NULL); + wrq->u.data.length = 0; /* 1: size of '\0' */ + } + break; + + case SHOW_NEIGHINFO_INFO: + { + Set_NeighborInfo_Display_Proc(pAd, NULL); + wrq->u.data.length = 0; /* 1: size of '\0' */ + } + break; + + case SHOW_MESH_ROUTE_INFO: + { + Set_MeshRouteInfo_Display_Proc(pAd, NULL); + wrq->u.data.length = 0; /* 1: size of '\0' */ + } + break; + + case SHOW_MESH_ENTRY_INFO: + { + Set_MeshEntryInfo_Display_Proc(pAd, NULL); + wrq->u.data.length = 0; /* 1: size of '\0' */ + } + break; + + case SHOW_MULPATH_INFO: + { + Set_MultipathInfo_Display_Proc(pAd, NULL); + wrq->u.data.length = 0; /* 1: size of '\0' */ + } + break; + + case SHOW_MCAST_AGEOUT_INFO: + { + Set_MultiCastAgeOut_Display_Proc(pAd, NULL); + wrq->u.data.length = 0; /* 1: size of '\0' */ + } + break; + + case SHOW_MESH_PKTSIG_INFO: + { + Set_PktSig_Display_Proc(pAd, NULL); + wrq->u.data.length = 0; /* 1: size of '\0' */ + } + break; + + case SHOW_MESH_PROXY_INFO: + { + Set_MeshProxyInfo_Display_Proc(pAd, NULL); + wrq->u.data.length = 0; /* 1: size of '\0' */ + } + break; +#endif /* MESH_SUPPORT */ + +#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 */ + +#ifdef DOT11Z_TDLS_SUPPORT + case SHOW_TDLS_ENTRY_INFO: + { + Set_TdlsEntryInfo_Display_Proc(pAd, NULL); + wrq->u.data.length = 0; /* 1: size of '\0' */ + } + break; +#endif /* DOT11Z_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; + + 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; + +#ifdef MESH_SUPPORT + if (Data == INT_MESH) + ch = pAd->MeshTab.MeshChannel; + else +#endif /* MESH_SUPPORT */ + 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.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( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + /* + 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 MESH_SUPPORT + if (pAd->MeshTab.MeshOnly == TRUE) + return NDIS_STATUS_SUCCESS; +#endif /* MESH_SUPPORT */ + +#ifdef WPA_SUPPLICANT_SUPPORT + if ((pAd->StaCfg.WpaSupplicantUP & 0x7F) == WPA_SUPPLICANT_ENABLE) + { + pAd->StaCfg.WpaSupplicantScanCount++; + } +#endif /* WPA_SUPPLICANT_SUPPORT */ + + pAd->StaCfg.bSkipAutoScanConn = TRUE; + do{ + + if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) && + ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) && + (pAd->StaCfg.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 PBSS_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; + PBSS_ENTRY pBssEntry; + UINT32 IdBss; + + + pIoctlScan->BssNr = 0; + +#ifdef MESH_SUPPORT + if(pIoctlScan->priv_flags == INT_MESH) + { + DBGPRINT(RT_DEBUG_TRACE, ("Mesh do not support rt_ioctl_giwscan \n")); + return NDIS_STATUS_FAILURE; + } + + if (pAd->MeshTab.MeshOnly == TRUE) + return NDIS_STATUS_SUCCESS; +#endif /* MESH_SUPPORT */ + +#ifdef WPA_SUPPLICANT_SUPPORT + if ((pAd->StaCfg.WpaSupplicantUP & 0x7F) == WPA_SUPPLICANT_ENABLE) + { + pAd->StaCfg.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->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. */ +/* pSsidString = kmalloc(MAX_LEN_OF_SSID+1, MEM_ALLOC_FLAG); */ + 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( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + RT_CMD_STA_IOCTL_SECURITY *pIoctlSec = (RT_CMD_STA_IOCTL_SECURITY *)pData; + + + if ((pIoctlSec->length == 0) && + (pIoctlSec->flags & RT_CMD_STA_IOCTL_SECURITY_DISABLED)) + { + pAd->StaCfg.PairCipher = Ndis802_11WEPDisabled; + pAd->StaCfg.GroupCipher = Ndis802_11WEPDisabled; + pAd->StaCfg.WepStatus = Ndis802_11WEPDisabled; + pAd->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + goto done; + } + else if (pIoctlSec->flags & RT_CMD_STA_IOCTL_SECURITY_RESTRICTED || + pIoctlSec->flags & RT_CMD_STA_IOCTL_SECURITY_OPEN) + { + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + pAd->StaCfg.PairCipher = Ndis802_11WEPEnabled; + pAd->StaCfg.GroupCipher = Ndis802_11WEPEnabled; + pAd->StaCfg.WepStatus = Ndis802_11WEPEnabled; + if (pIoctlSec->flags & RT_CMD_STA_IOCTL_SECURITY_RESTRICTED) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeShared; + else + pAd->StaCfg.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, pAd->StaCfg.DefaultKeyId)); + + /*Using default key */ + keyIdx = pAd->StaCfg.DefaultKeyId; + } + else + pAd->StaCfg.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.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",pAd->StaCfg.AuthMode)); + DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::DefaultKeyId=%x, KeyLen = %d\n",pAd->StaCfg.DefaultKeyId , pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen)); + DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::WepStatus=%x\n",pAd->StaCfg.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( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + RT_CMD_STA_IOCTL_SECURITY *pIoctlSec = (RT_CMD_STA_IOCTL_SECURITY *)pData; + int kid; + + + kid = pIoctlSec->KeyIdx; /*erq->flags & IW_ENCODE_INDEX; */ + DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_giwencode %d\n", kid)); + + if (pAd->StaCfg.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 (pAd->StaCfg.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 (pAd->StaCfg.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][pAd->StaCfg.DefaultKeyId].KeyLen; + memcpy(pIoctlSec->pData, pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, pIoctlSec->length); + /* copy default key ID */ + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeShared) + pIoctlSec->flags |= RT_CMD_STA_IOCTL_SECURITY_RESTRICTED; /* XXX */ + else + pIoctlSec->flags |= RT_CMD_STA_IOCTL_SECURITY_OPEN; /* XXX */ + pIoctlSec->KeyIdx = pAd->StaCfg.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; + + + switch (pIoctlWpa->flags) + { + case RT_CMD_STA_IOCTL_WPA_VERSION: + if (pIoctlWpa->value == RT_CMD_STA_IOCTL_WPA_VERSION1) + { + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK; + if (pAd->StaCfg.BssType == BSS_ADHOC) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPANone; + } + else if (pIoctlWpa->value == RT_CMD_STA_IOCTL_WPA_VERSION2) + pAd->StaCfg.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) + { + pAd->StaCfg.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) + { + pAd->StaCfg.WepStatus = Ndis802_11WEPEnabled; + pAd->StaCfg.PairCipher = Ndis802_11WEPEnabled; +#ifdef WPA_SUPPLICANT_SUPPORT + pAd->StaCfg.IEEE8021X = FALSE; +#endif /* WPA_SUPPLICANT_SUPPORT */ + } + else if (pIoctlWpa->value == RT_CMD_STA_IOCTL_WPA_PAIRWISE_TKIP) + { + pAd->StaCfg.WepStatus = Ndis802_11Encryption2Enabled; + pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; + } + else if (pIoctlWpa->value == RT_CMD_STA_IOCTL_WPA_PAIRWISE_CCMP) + { + pAd->StaCfg.WepStatus = Ndis802_11Encryption3Enabled; + pAd->StaCfg.PairCipher = Ndis802_11Encryption3Enabled; + } + 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_11Encryption2Enabled; + } + else if (pIoctlWpa->value == RT_CMD_STA_IOCTL_WPA_GROUP_CCMP) + { + pAd->StaCfg.GroupCipher = Ndis802_11Encryption3Enabled; + } + 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.WpaSupplicantUP &= 0x7F; +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + if (pIoctlWpa->value == RT_CMD_STA_IOCTL_WPA_KEY_MGMT_1X) + { + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) + { + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA; +#ifdef WPA_SUPPLICANT_SUPPORT + pAd->StaCfg.IEEE8021X = FALSE; +#endif /* WPA_SUPPLICANT_SUPPORT */ + } + else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) + { + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA2; +#ifdef WPA_SUPPLICANT_SUPPORT + pAd->StaCfg.IEEE8021X = FALSE; +#endif /* WPA_SUPPLICANT_SUPPORT */ + } +#ifdef WPA_SUPPLICANT_SUPPORT + else + /* WEP 1x */ + pAd->StaCfg.IEEE8021X = TRUE; +#endif /* WPA_SUPPLICANT_SUPPORT */ + } +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT +#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ + else if (pIoctlWpa->value == 0) + { + pAd->StaCfg.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) + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + else + { + pAd->StaCfg.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: + pAd->StaCfg.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; +} + + 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( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + RT_CMD_STA_IOCTL_SECURITY_ADV *pIoctlWpa = (RT_CMD_STA_IOCTL_SECURITY_ADV *)pData; + + + switch (pIoctlWpa->flags) { + case RT_CMD_STA_IOCTL_WPA_AUTH_DROP_UNENCRYPTED: + pIoctlWpa->value = (pAd->StaCfg.WepStatus == Ndis802_11WEPDisabled) ? 0 : 1; + break; + + case RT_CMD_STA_IOCTL_WPA_AUTH_80211_AUTH_ALG: + pIoctlWpa->value = (pAd->StaCfg.AuthMode == Ndis802_11AuthModeShared) ? 0 : 1; + break; + + case RT_CMD_STA_IOCTL_WPA_AUTH_WPA_ENABLED: + pIoctlWpa->value = (pAd->StaCfg.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; + + /* Update group key information to ASIC Shared Key Table */ + RTMP_ASIC_SHARED_KEY_TABLE(pAd, + BSS0, + keyIdx, + &pAd->SharedKey[BSS0][keyIdx]); + + /* Update ASIC WCID attribute table and IVEIV table */ + if (!bGTK) + RTMPSetWcidSecurityInfo(pAd, + BSS0, + keyIdx, + pAd->SharedKey[BSS0][keyIdx].CipherAlg, + BSSID_WCID, + SHAREDKEYTABLE); +} + + +/* +======================================================================== +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( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + RT_CMD_STA_IOCTL_SECURITY *pIoctlSec = (RT_CMD_STA_IOCTL_SECURITY *)pData; + int keyIdx; + + + 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) + { + pAd->StaCfg.DefaultKeyId = keyIdx; + DBGPRINT(RT_DEBUG_TRACE, ("%s::DefaultKeyId = %d\n", __FUNCTION__, pAd->StaCfg.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 */ + RTMP_ASIC_SHARED_KEY_TABLE(pAd, + BSS0, + keyIdx, + &pAd->SharedKey[BSS0][keyIdx]); + + /* Assign pairwise key info */ + RTMPSetWcidSecurityInfo(pAd, + BSS0, + keyIdx, + pAd->SharedKey[BSS0][keyIdx].CipherAlg, + BSSID_WCID, + SHAREDKEYTABLE); + + 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 (pAd->StaCfg.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 (pAd->StaCfg.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 (pAd->StaCfg.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 (pAd->StaCfg.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( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + RT_CMD_STA_IOCTL_SECURITY *pIoctlSec = (RT_CMD_STA_IOCTL_SECURITY *)pData; + int idx; + + + idx = pIoctlSec->KeyIdx; + if (idx) + { + if (idx < 1 || idx > 4) + { + pIoctlSec->Status = RTMP_IO_EINVAL; + return NDIS_STATUS_FAILURE; + } + idx--; + + if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || + (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)) + { + if (idx != pAd->StaCfg.DefaultKeyId) + { + pIoctlSec->Status = 0; + pIoctlSec->length = 0; + return NDIS_STATUS_FAILURE; + } + } + } + else + idx = pAd->StaCfg.DefaultKeyId; + + pIoctlSec->KeyIdx = idx + 1; + + pIoctlSec->length = 0; + switch(pAd->StaCfg.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_11Encryption2Enabled: + case Ndis802_11Encryption3Enabled: + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) + 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.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) + { + DBGPRINT(RT_DEBUG_TRACE ,("===> rt_ioctl_siwgenie\n")); + pAd->StaCfg.bRSN_IE_FromWpaSupplicant = FALSE; + if ((length > 0) && + (pData == NULL)) + { + return NDIS_STATUS_FAILURE; + } + else if (length) + { + if (pAd->StaCfg.pWpaAssocIe) + { + os_free_mem(NULL, pAd->StaCfg.pWpaAssocIe); + pAd->StaCfg.pWpaAssocIe = NULL; + } +/* pAd->StaCfg.pWpaAssocIe = kmalloc(wrqu->data.length, MEM_ALLOC_FLAG); */ + os_alloc_mem(NULL, (UCHAR **)&pAd->StaCfg.pWpaAssocIe, length); + if (pAd->StaCfg.pWpaAssocIe) + { + pAd->StaCfg.WpaAssocIeLen = length; + NdisMoveMemory(pAd->StaCfg.pWpaAssocIe, pData, pAd->StaCfg.WpaAssocIeLen); + pAd->StaCfg.bRSN_IE_FromWpaSupplicant = TRUE; + } + else + pAd->StaCfg.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( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + RT_CMD_STA_IOCTL_RSN_IE *IoctlRsnIe = (RT_CMD_STA_IOCTL_RSN_IE *)pData; + + + if ((pAd->StaCfg.RSNIE_Len == 0) || + (pAd->StaCfg.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.WpaSupplicantUP & 0x7F) == WPA_SUPPLICANT_ENABLE && + (pAd->StaCfg.WpaAssocIeLen > 0)) + { + if (IoctlRsnIe->length < pAd->StaCfg.WpaAssocIeLen) + return NDIS_STATUS_FAILURE; + + IoctlRsnIe->length = pAd->StaCfg.WpaAssocIeLen; + memcpy(IoctlRsnIe->pRsnIe, pAd->StaCfg.pWpaAssocIe, pAd->StaCfg.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 ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) || + (pAd->StaCfg.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( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + RT_CMD_RATE_SET *pCmdRate = (RT_CMD_RATE_SET *)pData; + UINT32 rate = pCmdRate->Rate; + UINT32 fixed = pCmdRate->Fixed; + + + /* rate = -1 => auto rate + rate = X, fixed = 1 => (fixed rate X) + */ + if (rate == -1) + { + /*Auto Rate */ + pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; + pAd->StaCfg.bAutoTxRateSwitch = TRUE; + if ((pAd->CommonCfg.PhyMode <= PHY_11G) || + (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) + { + pAd->StaCfg.bAutoTxRateSwitch = FALSE; + if ((pAd->CommonCfg.PhyMode <= PHY_11G) || + (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM)) + RTMPSetDesiredRates(pAd, rate); + else + { + pAd->StaCfg.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",pAd->StaCfg.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( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + int rate_index = 0, rate_count = 0; + HTTRANSMIT_SETTING ht_setting; + + + rate_count = RT_RateSize/sizeof(__s32); + + if ((pAd->StaCfg.bAutoTxRateSwitch == FALSE) && + (INFRA_ON(pAd)) && + ((pAd->CommonCfg.PhyMode <= PHY_11G) || (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM))) + ht_setting.word = pAd->StaCfg.HTPhyMode.word; + else + ht_setting.word = pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word; + +#ifdef DOT11_N_SUPPORT + if (ht_setting.field.MODE >= MODE_HTMIX) + { +/* rate_index = 12 + ((UCHAR)ht_setting.field.BW *16) + ((UCHAR)ht_setting.field.ShortGI *32) + ((UCHAR)ht_setting.field.MCS); */ + rate_index = 12 + ((UCHAR)ht_setting.field.BW *24) + ((UCHAR)ht_setting.field.ShortGI *48) + ((UCHAR)ht_setting.field.MCS); + } + else +#endif /* DOT11_N_SUPPORT */ + if (ht_setting.field.MODE == MODE_OFDM) + rate_index = (UCHAR)(ht_setting.field.MCS) + 4; + else if (ht_setting.field.MODE == MODE_CCK) + rate_index = (UCHAR)(ht_setting.field.MCS); + + if (rate_index < 0) + rate_index = 0; + + if (rate_index >= rate_count) + rate_index = rate_count-1; + + *(ULONG *)pData = ralinkrate[rate_index] * 500000; + + 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; +#ifdef MESH_SUPPORT + if (Data == INT_MESH) + { + pObj->ioctl_if_type = INT_MESH; + pObj->ioctl_if = 0; + } + else +#endif /* MESH_SUPPORT */ +#ifdef P2P_SUPPORT + if (Data == INT_P2P) + { + pObj->ioctl_if_type = INT_P2P; + pObj->ioctl_if = 0; + } + else +#endif /* P2P_SUPPORT */ + { + 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[4] = {"CCK", "OFDM", "MM", "GF"}; + int i; + + for (i=1; iMacTab.Content[i]); + if (IS_ENTRY_CLIENT(pEntry) && pEntry->Sst==SST_ASSOC) + { + UINT32 lastRxRate = pEntry->LastRxRate; + + 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": " "); + +#if defined(RT2883) || defined(RT3883) + sprintf(extra+strlen(extra), "BF SNR = %d.%02d, %d.%02d, %d.%02d FO:%02X\n", + pEntry->BF_SNR[0]/4, (pEntry->BF_SNR[0] % 4)*25, + pEntry->BF_SNR[1]/4, (pEntry->BF_SNR[1] % 4)*25, + pEntry->BF_SNR[2]/4, (pEntry->BF_SNR[2] % 4)*25, + pEntry->freqOffset & 0xFF); +#endif // defined(RT2883) || defined(RT3883) // + 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.WpaSupplicantUP); +#endif /* WPA_SUPPLICANT_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); +#ifdef DPA_S + sprintf(extra+strlen(extra), "MAC = %02X:%02X:%02X:%02X:%02X:%02X\n", + pAd->MlmeAux.Bssid[0], + pAd->MlmeAux.Bssid[1], + pAd->MlmeAux.Bssid[2], + pAd->MlmeAux.Bssid[3], + pAd->MlmeAux.Bssid[4], + pAd->MlmeAux.Bssid[5]); +#else + 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]); +#endif /* DPA_S */ + 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 */ + + 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; + +#ifdef MESH_SUPPORT + if (priv_flags == INT_MESH) + { + pObj->ioctl_if_type = INT_MESH; + pObj->ioctl_if = 0; + } else +#endif /* MESH_SUPPORT */ +#ifdef P2P_SUPPORT + if (priv_flags == INT_P2P) + { + pObj->ioctl_if_type = INT_P2P; + pObj->ioctl_if = 0; + } else +#endif /* MESH_SUPPORT */ + { /* 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; +} + +/* End of sta_cfg.c */ + diff --git a/mt7620/src/sta/sta_iwsc.c b/mt7620/src/sta/sta_iwsc.c new file mode 100644 index 0000000..0cc6d28 --- /dev/null +++ b/mt7620/src/sta/sta_iwsc.c @@ -0,0 +1,1933 @@ +/* + *************************************************************************** + * 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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN IN PRTMP_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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pOutBuf, + OUT PUSHORT pIeLen) +{ +// UCHAR Data[512]; // change array to pointer + 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; + USHORT 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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN 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, BSS0, OPMODE_STA, FALSE); + } + + if (pEntry) + { +#ifdef ADHOC_WPA2PSK_SUPPORT + //Adhoc support WPA2PSK by Eddy + if ((pAd->StaCfg.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.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, BSS0, OPMODE_STA, FALSE); + } + + if (pEntry) + { +#ifdef ADHOC_WPA2PSK_SUPPORT + //Adhoc support WPA2PSK by Eddy + if ((pAd->StaCfg.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.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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN PMAC_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( + IN PRTMP_ADAPTER pAd, + IN 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( + IN PRTMP_ADAPTER pAd, + IN PUCHAR 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, 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", + pEntry->Addr[0], + pEntry->Addr[1], + pEntry->Addr[2], + pEntry->Addr[3], + pEntry->Addr[4], + pEntry->Addr[5])); + } + } + else if (pIWscInfo->bIWscEntryTimerRunning) + { + pEntry = MacTableLookup(pAd, pPeerAddr); + if (pEntry == NULL) + { + pEntry = MacTableInsertEntry(pAd, pPeerAddr, 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", + pEntry->Addr[0], + pEntry->Addr[1], + pEntry->Addr[2], + pEntry->Addr[3], + pEntry->Addr[4], + pEntry->Addr[5])); + + 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( + IN PRTMP_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( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pVIE, + IN INT VIELen, + OUT PUSHORT 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( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pOutBuf, + OUT PUSHORT 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( + IN PRTMP_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( + IN PRTMP_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/mt7620/src/sta/sync.c b/mt7620/src/sta/sync.c new file mode 100644 index 0000000..c574b73 --- /dev/null +++ b/mt7620/src/sta/sync.c @@ -0,0 +1,3270 @@ +/* + *************************************************************************** + * 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 MESH_SUPPORT +#include "mesh_sanity.h" +#endif /* MESH_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); +#ifdef P2P_SUPPORT + StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction); +#endif /* P2P_SUPPORT */ + + /* 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) +#ifdef MESH_SUPPORT + || MESH_ON(pAd) +#endif /* MESH_SUPPORT */ + ) + { + UCHAR BBPValue = 0; + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + BBPValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + 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); + RTMPSendWirelessEvent(pAd, IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG, NULL, BSS0, 0); + } +} + + +VOID MlmeForceJoinReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR BBPValue = 0; + 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 = pBss->BssType; + pAd->MlmeAux.Channel = pBss->Channel; + pAd->MlmeAux.CentralChannel = pBss->CentralChannel; + */ + pAd->MlmeAux.BssType = pAd->StaCfg.ConnectinfoBssType; + pAd->MlmeAux.Channel = pAd->StaCfg.ConnectinfoChannel; + + + /* Let BBP register at 20MHz to do scan */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + pAd->CommonCfg.BBPCurrentBW = BW_20; + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); + + /* switch channel and waiting for beacon timer */ + AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE); + AsicLockChannel(pAd, pAd->MlmeAux.Channel); + + + 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, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + pAd->MlmeAux.Bssid); + } + else + MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + 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.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) && + (pAd->StaCfg.WpsProbeReqIeLen != 0)) + { + ULONG WpsTmpLen = 0; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &WpsTmpLen, + pAd->StaCfg.WpsProbeReqIeLen, pAd->StaCfg.pWpsProbeReqIe, + END_OF_ARGS); + + FrameLen += WpsTmpLen; + } +#endif /* WPA_SUPPLICANT_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, pAd->StaCfg.ConnectinfoBssid[0], pAd->StaCfg.ConnectinfoBssid[1], pAd->StaCfg.ConnectinfoBssid[2], + pAd->StaCfg.ConnectinfoBssid[3], pAd->StaCfg.ConnectinfoBssid[4], pAd->StaCfg.ConnectinfoBssid[5])); + + 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, BBPValue = 0; + 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)) + { + + /* + 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); + + /* + 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); + } + + 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 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + 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); + 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, BBPValue = 0; + 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) + { + AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02, FALSE); + AsicCheckCommanOk(pAd, PowerWakeCID); + 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)) + { + UINT32 Data = 0, macStatus; + UINT32 MTxCycle; + + /* + 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); + + /* + 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); + } + + 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; + } +#ifdef P2P_SUPPORT + else if (pAd->P2pCfg.CtrlCurrentState == P2P_CTRL_DISCOVERY) + { + pAd->MlmeAux.Channel = 1; + } +#endif /* P2P_SUPPORT */ + 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); + } + } + } + + //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; + } + + /* Let BBP register at 20MHz to do scan */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); + + //Enable MAC Tx/Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Data); + Data |= 0x0C; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Data); + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + /* Before scan, reset trigger event table. */ + TriEventInit(pAd); +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef WAC_SUPPORT + if ((pAd->StaCfg.EasyConfigInfo.bEnableWAC) && + (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))) + { + pAd->StaCfg.EasyConfigInfo.CurrentStatus = OFC_PROCEED_FIRST_PHASE; + } +#endif /* WAC_SUPPORT */ + + ScanNextChannel(pAd, OPMODE_STA); + } + 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) +{ + UCHAR BBPValue = 0; + 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; +#ifdef P2P_SUPPORT + PAPCLI_STRUCT pApCliEntry = NULL; +#endif /* P2P_SUPPORT */ + + 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 */ + +#ifdef P2P_SUPPORT + pApCliEntry = &pAd->ApCfg.ApCliTab[BSS0]; + + if (!P2P_GO_ON(pAd) && (pApCliEntry->Valid == FALSE)) +#endif /* P2P_SUPPORT */ + { + bChangeInitBW = TRUE; + } + +#ifdef P2P_SUPPORT + if ((P2P_GO_ON(pAd) || (pApCliEntry->Valid == TRUE)) && (pAd->CommonCfg.Channel != pAd->MlmeAux.Channel)) + { + bChangeInitBW = TRUE; + } +#endif /* P2P_SUPPORT */ + + if (bChangeInitBW == TRUE) + { + /* Let BBP register at 20MHz to do scan */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + pAd->CommonCfg.BBPCurrentBW = BW_20; + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); + + /* 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, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + pAd->MlmeAux.Bssid); + else + MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + 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 /* WscBuf[256], */ 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->StaCfg.WscControl, 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 WAC_SUPPORT + if (pAd->StaCfg.EasyConfigInfo.bDoAutoWps && + pAd->StaCfg.EasyConfigInfo.bEnableWAC && + pAd->StaCfg.EasyConfigInfo.bWACAP) + { + PUCHAR pWAC_IE = NULL; + UCHAR WAC_IELen = 0; + UCHAR tempPIN[9] = {0}; + PWSC_CTRL pWscControl = &pAd->StaCfg.WscControl; + ULONG TmpWACLen = 0; + + pWscControl->WscEnrolleePinCode = WscRandomGeneratePinCode(pAd, BSS0); + os_alloc_mem(NULL, &pWAC_IE, 128); + if (pWAC_IE) + { + sprintf((PSTRING) tempPIN, "%08u", pWscControl->WscEnrolleePinCode); + WAC_GenUicastProbeReqAttr(TRUE, tempPIN, pWAC_IE, &WAC_IELen); + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpWACLen, + WAC_IELen, pWAC_IE, + END_OF_ARGS); + + FrameLen += TmpWACLen; + os_free_mem(NULL, pWAC_IE); + } + } + +#ifdef WAC_QOS_PRIORITY +#define WAC_AP 0x04 + + pAd->MlmeAux.bForcePriority = FALSE; + if ((pAd->StaCfg.EasyConfigInfo.bWACAP & WAC_AP) && (pBss->bForcePriority)) + { + pAd->MlmeAux.bForcePriority = TRUE; + } +#endif /* WAC_QOS_PRIORITY */ +#endif /* WAC_SUPPORT */ + +#ifdef WPA_SUPPLICANT_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && + (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) && + (pAd->StaCfg.WpsProbeReqIeLen != 0)) + { + ULONG WpsTmpLen = 0; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &WpsTmpLen, + pAd->StaCfg.WpsProbeReqIeLen, pAd->StaCfg.pWpsProbeReqIe, + END_OF_ARGS); + + FrameLen += WpsTmpLen; + } +#endif /* WPA_SUPPLICANT_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; + + /* New for WPA security suites */ + UCHAR *VarIE = NULL; + 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)) + { + /* 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 = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) || + (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || + (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled); + 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 ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->StaCfg.bAdhocN == TRUE)) + { + RTMPUpdateHTIE(&pAd->CommonCfg.DesiredHtPhy, &pAd->StaCfg.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")); + } + 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); +} + +/* + ========================================================================== + Description: + peer sends beacon back when scanning + ========================================================================== + */ +VOID PeerBeaconAtScanAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; + UCHAR /* Ssid[MAX_LEN_OF_SSID], */ BssType, Channel = 0, NewChannel, + SsidLen=0, DtimCount, DtimPeriod, BcastFlag, MessageToMe; + UCHAR *Ssid = NULL; + CF_PARM CfParm; + USHORT BeaconPeriod, AtimWin, CapabilityInfo; + PFRAME_802_11 pFrame; + LARGE_INTEGER TimeStamp; + UCHAR Erp; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen, ExtRateLen; + USHORT LenVIE; + UCHAR CkipFlag; + UCHAR AironetCellPowerLimit; + EDCA_PARM EdcaParm; + QBSS_LOAD_PARM QbssLoad; + QOS_CAPABILITY_PARM QosCapability; + ULONG RalinkIe; + UCHAR *VarIE = NULL; + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + 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 AddHtInfoLen; + UCHAR NewExtChannelOffset = 0xff; + +#ifdef MESH_SUPPORT + UCHAR HostName[MAX_HOST_NAME_LEN] = {0}; + UCHAR HostNameLen = 0; + UCHAR MeshId[MAX_MESH_ID_LEN] = {0}; + UCHAR MeshIdLen = 0; + MESH_CONFIGURAION_IE MeshConfig = {0}; +#endif /* MESH_SUPPORT */ + EXT_CAP_INFO_ELEMENT ExtCapInfo; + +#ifdef P2P_SUPPORT + if (P2P_GO_ON(pAd)) + return; +#endif /* P2P_SUPPORT */ + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&Ssid, MAX_LEN_OF_SSID); + if (Ssid == NULL) + goto LabelErr; + os_alloc_mem(NULL, (UCHAR **)&VarIE, MAX_VIE_LEN); + if (VarIE == 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(Ssid, MAX_LEN_OF_SSID); + pFrame = (PFRAME_802_11) Elem->Msg; + /* Init Variable IE structure */ + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; +#ifdef DOT11_N_SUPPORT + RTMPZeroMemory(pHtCapability, sizeof(HT_CAPABILITY_IE)); + RTMPZeroMemory(pAddHtInfo, sizeof(ADD_HT_INFO_IE)); +#endif /* DOT11_N_SUPPORT */ + + NdisZeroMemory(&QbssLoad, sizeof(QBSS_LOAD_PARM)); /* woody */ + if (PeerBeaconAndProbeRspSanity(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, +#endif /* CONFIG_STA_SUPPORT */ + pHtCapability, + &ExtCapInfo, + &AddHtInfoLen, + pAddHtInfo, + &NewExtChannelOffset, + &LenVIE, + pVIE)) + { + ULONG Idx = 0; + CHAR Rssi = 0; + + Idx = BssTableSearch(&pAd->ScanTab, Bssid, 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 MESH_SUPPORT + MeshPeerBeaconAndProbeSanity(pAd, Elem->Msg, Elem->MsgLen, HostName, &HostNameLen, MeshId, &MeshIdLen, &MeshConfig); + if(MESH_ON(pAd) && (MeshIdLen != 0)) + { + ULONG LinkIdx; + + InsertNeighborMP(pAd, Rssi, Bssid, Channel, (UINT8)pAddHtInfo->AddHtInfo.RecomWidth, + (UINT8)pAddHtInfo->AddHtInfo.ExtChanOffset, HostName, MeshId, MeshIdLen, CapabilityInfo, (PUCHAR)pVIE, LenVIE, &MeshConfig); + + LinkIdx = GetMeshLinkId(pAd, (PCHAR)Addr2); + if(VALID_MESH_LINK_ID(LinkIdx)) + { + ULONG Now; + NdisGetSystemUpTime(&Now); + pAd->MeshTab.MeshLink[LinkIdx].Entry.LastBeaconTime = Now; + } + } +#endif /* MESH_SUPPORT */ +#ifdef P2P_SUPPORT + MlmeEnqueue(pAd, P2P_DISC_STATE_MACHINE, P2P_DISC_PEER_PROB_RSP, Elem->MsgLen, Elem->Msg, Channel); +#endif /* P2P_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) + HtCapabilityLen = SIZE_HT_CAP_IE; +#endif /* DOT11_N_SUPPORT */ + + Idx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, (PCHAR)Ssid, SsidLen, BssType, BeaconPeriod, + &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, pHtCapability, + pAddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag, + &EdcaParm, &QosCapability, &QbssLoad, 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) + && ((Channel > 0) && (Channel <= 14))) + { + int chListIdx; + + /* + First we find the channel list idx by the channel number + */ + for (chListIdx = 0; chListIdx < pAd->ChannelListNum; chListIdx++) + { + if (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, Bssid, pHtCapability, HtCapabilityLen, RegClass, Channel); + } + } + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + if (Idx != BSS_NOT_FOUND) + { + PBSS_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, Addr2, 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 + 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 (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); + return; +} + +/* + ========================================================================== + Description: + When waiting joining the (I)BSS, beacon received from external + ========================================================================== + */ +VOID PeerBeaconAtJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; + UCHAR /* Ssid[MAX_LEN_OF_SSID], */ SsidLen=0, BssType, Channel, MessageToMe, + DtimCount, DtimPeriod, BcastFlag, NewChannel; + UCHAR *Ssid = NULL; + LARGE_INTEGER TimeStamp; + USHORT BeaconPeriod, AtimWin, CapabilityInfo; + CF_PARM Cf; + BOOLEAN TimerCancelled; + UCHAR Erp; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen, ExtRateLen; + UCHAR CkipFlag; + USHORT LenVIE; + UCHAR AironetCellPowerLimit; + EDCA_PARM EdcaParm; + QBSS_LOAD_PARM QbssLoad; + QOS_CAPABILITY_PARM QosCapability; + USHORT Status; + UCHAR *VarIE = NULL; + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + ULONG RalinkIe; + ULONG Idx = 0; + CHAR Rssi = 0; + 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 AddHtInfoLen; + UCHAR NewExtChannelOffset = 0xff; +#ifdef DOT11_N_SUPPORT + UCHAR CentralChannel; + BOOLEAN bAllowNrate = FALSE; +#endif /* DOT11_N_SUPPORT */ + EXT_CAP_INFO_ELEMENT ExtCapInfo; + + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&Ssid, MAX_LEN_OF_SSID); + if (Ssid == NULL) + goto LabelErr; + os_alloc_mem(NULL, (UCHAR **)&VarIE, MAX_VIE_LEN); + if (VarIE == 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; + + /* Init Variable IE structure */ + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + RTMPZeroMemory(pHtCapability, sizeof(HT_CAPABILITY_IE)); + RTMPZeroMemory(pAddHtInfo, sizeof(ADD_HT_INFO_IE)); + RTMPZeroMemory(&QosCapability, sizeof(QOS_CAPABILITY_PARM)); + RTMPZeroMemory(&EdcaParm, sizeof(EDCA_PARM)); + + EdcaParm.bValid = FALSE; + if (PeerBeaconAndProbeRspSanity(pAd, + Elem->Msg, + Elem->MsgLen, + Elem->Channel, + Addr2, + Bssid, + (PCHAR)Ssid, + &SsidLen, + &BssType, + &BeaconPeriod, + &Channel, + &NewChannel, + &TimeStamp, + &Cf, + &AtimWin, + &CapabilityInfo, + &Erp, + &DtimCount, + &DtimPeriod, + &BcastFlag, + &MessageToMe, + SupRate, + &SupRateLen, + ExtRate, + &ExtRateLen, + &CkipFlag, + &AironetCellPowerLimit, + &EdcaParm, + &QbssLoad, + &QosCapability, + &RalinkIe, + &HtCapabilityLen, + &PreNHtCapabilityLen, + pHtCapability, + &ExtCapInfo, + &AddHtInfoLen, + pAddHtInfo, + &NewExtChannelOffset, + &LenVIE, + pVIE)) + { + /* Disqualify 11b only adhoc when we are in 11g only adhoc mode */ + if ((BssType == BSS_ADHOC) && (pAd->CommonCfg.PhyMode == PHY_11G) && ((SupRateLen+ExtRateLen)< 12)) + goto LabelOK; + +#ifdef P2P_SUPPORT +/* if ((pAd->P2pCfg.P2PDiscoProvState == P2P_DISC_SCAN) || (pAd->P2pCfg.P2PDiscoProvState == P2P_DISC_SEARCH)) */ + if (P2P_INF_ON(pAd)) + { + P2pPeerBeaconAtJoinAction(pAd, Elem, Bssid); + } +#endif /* P2P_SUPPORT */ + /* + 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, Bssid)) + { + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - receive desired BEACON at JoinWaitBeacon... Channel = %d\n", Channel)); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); + +#ifdef P2P_SUPPORT + if (IS_P2P_ENROLLEE(pAd)) + { + int p2pIdx; + DBGPRINT(RT_DEBUG_ERROR, ("Recv desired Beacon, update SSID[%d][%s]\n", SsidLen, Ssid)); + pAd->MlmeAux.SsidLen = SsidLen; + NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, pAd->MlmeAux.SsidLen); + + p2pIdx = P2pGroupTabSearch(pAd, Addr2); + if (p2pIdx < MAX_P2P_GROUP_SIZE) + { + pAd->P2pTable.Client[p2pIdx].SsidLen = SsidLen; + NdisMoveMemory(pAd->P2pTable.Client[p2pIdx].Ssid, Ssid, pAd->P2pTable.Client[p2pIdx].SsidLen); + } + } +#endif /* P2P_SUPPORT */ + /* 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, Ssid, SsidLen); + pAd->MlmeAux.SsidLen = SsidLen; + } + else + { + Idx = BssSsidTableSearch(&pAd->ScanTab, Bssid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, 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, Bssid, (CHAR *) Ssid, SsidLen, BssType, BeaconPeriod, + &Cf, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, pHtCapability, + pAddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag, + &EdcaParm, &QosCapability, &QbssLoad, 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); + 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, Addr2, MAC_ADDR_LEN); + } + } + else + { +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP & WPA_SUPPLICANT_ENABLE_WPS) ; + else +#endif /* WPA_SUPPLICANT_SUPPORT */ +#ifdef WSC_STA_SUPPORT + if ((pAd->StaCfg.WscControl.WscState != WSC_STATE_OFF) +#ifdef WAC_SUPPORT + || (pAd->StaCfg.EasyConfigInfo.bDoAutoWps) +#endif /* WAC_SUPPORT */ + ) + ; + 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 ((((pAd->StaCfg.WepStatus != Ndis802_11WEPDisabled) << 4) ^ + CapabilityInfo) & + 0x0010) + { + MLME_SCAN_REQ_STRUCT ScanReq; + DBGPRINT(RT_DEBUG_TRACE, ("%s:AP privacy %d is differenct from STA privacy%d\n", __FUNCTION__, (CapabilityInfo & 0x0010) >> 4 ,pAd->StaCfg.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); + goto LabelOK; + } + } + + /* + Multiple SSID case, used correct CapabilityInfo + */ + CapabilityInfo = pAd->ScanTab.BssEntry[Idx].CapabilityInfo; + } + } + /*NdisMoveMemory(pAd->MlmeAux.Bssid, Bssid, MAC_ADDR_LEN);*/ + pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; + pAd->MlmeAux.BssType = BssType; + pAd->MlmeAux.BeaconPeriod = 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 = Channel; + pAd->MlmeAux.AtimWin = AtimWin; + pAd->MlmeAux.CfpPeriod = Cf.CfpPeriod; + pAd->MlmeAux.CfpMaxDuration = Cf.CfpMaxDuration; + pAd->MlmeAux.APRalinkIe = RalinkIe; + + /* + Copy AP's supported rate to MlmeAux for creating assoication request + Also filter out not supported rate + */ + pAd->MlmeAux.SupRateLen = SupRateLen; + NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen); + RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen); + pAd->MlmeAux.ExtRateLen = ExtRateLen; + NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen); + RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen); + + NdisZeroMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, 16); + + + /* Get the ext capability info element */ + NdisMoveMemory(&pAd->MlmeAux.ExtCapInfo, &ExtCapInfo,sizeof(ExtCapInfo)); + +#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 (((pAd->StaCfg.WepStatus != Ndis802_11WEPEnabled) && (pAd->StaCfg.WepStatus != Ndis802_11Encryption2Enabled)) + || (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 = NewExtChannelOffset; + pAd->MlmeAux.HtCapabilityLen = HtCapabilityLen; + + RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); + /* filter out un-supported ht rates */ + if (((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) && + (pAd->StaCfg.DesiredHtPhyInfo.bHtEnable) && + ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && bAllowNrate)) + { + RTMPMoveMemory(&pAd->MlmeAux.AddHtInfo, pAddHtInfo, SIZE_ADD_HT_INFO_IE); + + /* StaActive.SupportedHtPhy.MCSSet stores Peer AP's 11n Rx capability */ + NdisMoveMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, pHtCapability->MCSSet, 16); + pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset; + pAd->MlmeAux.HtCapabilityLen = SIZE_HT_CAP_IE; + pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE; + if (PreNHtCapabilityLen > 0) + pAd->StaActive.SupportedPhyInfo.bPreNHt = TRUE; + RTMPCheckHt(pAd, BSSID_WCID, pHtCapability, pAddHtInfo); + /* Copy AP Parameter to StaActive. This is also in LinkUp. */ + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction! (MpduDensity=%d, MaxRAmpduFactor=%d, BW=%d)\n", + pAd->StaActive.SupportedHtPhy.MpduDensity, pAd->StaActive.SupportedHtPhy.MaxRAmpduFactor, pHtCapability->HtCapInfo.ChannelWidth)); + + if (AddHtInfoLen > 0) + { + CentralChannel = pAddHtInfo->ControlChan; + /* Check again the Bandwidth capability of this AP. */ + if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40)) + { + CentralChannel = pAddHtInfo->ControlChan - 2; + } + else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40)) + { + CentralChannel = pAddHtInfo->ControlChan + 2; + } + + /* Check Error . */ + if (pAd->MlmeAux.CentralChannel != CentralChannel) + DBGPRINT(RT_DEBUG_ERROR, ("PeerBeaconAtJoinAction HT===>Beacon Central Channel = %d, Control Channel = %d. Mlmeaux CentralChannel = %d\n", CentralChannel, pAddHtInfo->ControlChan, pAd->MlmeAux.CentralChannel)); + + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction HT===>Central Channel = %d, Control Channel = %d, .\n", CentralChannel, pAddHtInfo->ControlChan)); + + } + + } + else +#endif /* DOT11_N_SUPPORT */ + { + /* To prevent error, let legacy AP must have same CentralChannel and Channel. */ + if ((HtCapabilityLen == 0) && (PreNHtCapabilityLen == 0)) + pAd->MlmeAux.CentralChannel = pAd->MlmeAux.Channel; + + pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; + 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); + } + + RTMPUpdateMlmeRate(pAd); + + /* copy QOS related information */ + if ((pAd->CommonCfg.bWmmCapable) +#ifdef DOT11_N_SUPPORT + || (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) +#endif /* DOT11_N_SUPPORT */ + ) + { + NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, &EdcaParm, sizeof(EDCA_PARM)); + NdisMoveMemory(&pAd->MlmeAux.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM)); + NdisMoveMemory(&pAd->MlmeAux.APQosCapability, &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, ("SYNC - after JOIN, SupRateLen=%d, ExtRateLen=%d\n", + pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen)); + + if (AironetCellPowerLimit != 0xFF) + { + /* We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power */ + ChangeToCellPowerLimit(pAd, 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; + + /* + Ad-hoc call this function in LinkUp + */ + 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); +#ifdef P2P_SUPPORT + if (BwFallBack == 1) + { + DBGPRINT(RT_DEBUG_TRACE, ("P2P STA connection to 40MHz GO, but Infra extra and P2P Group extra is different!!!\n")); + pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = BW_20; + pAd->MlmeAux.CentralChannel = pAd->MlmeAux.Channel; + pAd->MlmeAux.bBwFallBack = TRUE; + } + else + { + pAd->MlmeAux.bBwFallBack = FALSE; + } + pAd->MlmeAux.ConCurrentCentralChannel = pAd->CommonCfg.CentralChannel; +#endif /* P2P_SUPPORT */ + } + + 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 + 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 (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); + return; +} + +/* + ========================================================================== + Description: + receive BEACON from peer + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerBeacon( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; + CHAR *Ssid = NULL; + CF_PARM CfParm; + UCHAR SsidLen=0, MessageToMe=0, BssType, Channel, NewChannel, index=0; + UCHAR DtimCount=0, DtimPeriod=0, BcastFlag=0; + USHORT CapabilityInfo, AtimWin, BeaconPeriod; + LARGE_INTEGER TimeStamp; + USHORT TbttNumToNextWakeUp; + UCHAR Erp; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen, ExtRateLen; + UCHAR CkipFlag; + USHORT LenVIE; + UCHAR AironetCellPowerLimit; + EDCA_PARM *pEdcaParm = NULL; + QBSS_LOAD_PARM QbssLoad; + QOS_CAPABILITY_PARM QosCapability; + ULONG RalinkIe; + UCHAR *VarIE = NULL; /* Total VIE length = MAX_VIE_LEN - -5 */ + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + HT_CAPABILITY_IE *pHtCapability = NULL; + ADD_HT_INFO_IE *pAddHtInfo = NULL; /* AP might use this additional ht info IE */ + UCHAR HtCapabilityLen, PreNHtCapabilityLen; + UCHAR AddHtInfoLen; + UCHAR NewExtChannelOffset = 0xff; + EXT_CAP_INFO_ELEMENT ExtCapInfo; + +#ifdef MESH_SUPPORT + UCHAR HostName[MAX_HOST_NAME_LEN] = {0}; + UCHAR HostNameLen = 0; + UCHAR MeshId[MAX_MESH_ID_LEN] = {0}; + UCHAR MeshIdLen = 0; + MESH_CONFIGURAION_IE MeshConfig = {0}; +#endif /* MESH_SUPPORT */ + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + return; + } +#endif /* RALINK_ATE */ + + if (!(INFRA_ON(pAd) || ADHOC_ON(pAd) +#ifdef MESH_SUPPORT + || MESH_ON(pAd) +#endif /* MESH_SUPPORT */ +#ifdef P2P_SUPPORT + || P2P_GO_ON(pAd) || P2P_CLI_ON(pAd) +#endif /* P2P_SUPPORT */ + )) + return; + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&Ssid, MAX_LEN_OF_SSID); + if (Ssid == NULL) + goto LabelErr; + os_alloc_mem(NULL, (UCHAR **)&pEdcaParm, sizeof(EDCA_PARM)); + if (pEdcaParm == NULL) + goto LabelErr; + os_alloc_mem(NULL, (UCHAR **)&VarIE, MAX_VIE_LEN); + if (VarIE == 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; + + /* Init Variable IE structure */ + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + RTMPZeroMemory(pHtCapability, sizeof(HT_CAPABILITY_IE)); + RTMPZeroMemory(pAddHtInfo, sizeof(ADD_HT_INFO_IE)); + RTMPZeroMemory(&ExtCapInfo, sizeof(ExtCapInfo)); + + if (PeerBeaconAndProbeRspSanity(pAd, + Elem->Msg, + Elem->MsgLen, + Elem->Channel, + Addr2, + Bssid, + Ssid, + &SsidLen, + &BssType, + &BeaconPeriod, + &Channel, + &NewChannel, + &TimeStamp, + &CfParm, + &AtimWin, + &CapabilityInfo, + &Erp, + &DtimCount, + &DtimPeriod, + &BcastFlag, + &MessageToMe, + SupRate, + &SupRateLen, + ExtRate, + &ExtRateLen, + &CkipFlag, + &AironetCellPowerLimit, + pEdcaParm, + &QbssLoad, + &QosCapability, + &RalinkIe, + &HtCapabilityLen, +#ifdef CONFIG_STA_SUPPORT + &PreNHtCapabilityLen, +#endif /* CONFIG_STA_SUPPORT */ + pHtCapability, + &ExtCapInfo, + &AddHtInfoLen, + pAddHtInfo, + &NewExtChannelOffset, + &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(Bssid, pAd->CommonCfg.Bssid)? TRUE : FALSE; + is_my_ssid = SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)? TRUE:FALSE; + +#ifdef MESH_SUPPORT + MeshPeerBeaconAndProbeSanity(pAd, Elem->Msg, Elem->MsgLen, HostName, &HostNameLen, MeshId, &MeshIdLen, &MeshConfig); + if(MESH_ON(pAd) && (MeshIdLen != 0)) + { + ULONG LinkIdx; + + InsertNeighborMP(pAd, RealRssi, Bssid, Channel, (UINT8)pAddHtInfo->AddHtInfo.RecomWidth, + (UINT8)pAddHtInfo->AddHtInfo.ExtChanOffset, HostName, MeshId, MeshIdLen, CapabilityInfo, (PUCHAR)pVIE, LenVIE, &MeshConfig); + + LinkIdx = GetMeshLinkId(pAd, (PCHAR)Addr2); + if(VALID_MESH_LINK_ID(LinkIdx)) + { + ULONG Now; + NdisGetSystemUpTime(&Now); + pAd->MeshTab.MeshLink[LinkIdx].Entry.LastBeaconTime = Now; + } + } +#endif /* MESH_SUPPORT */ + + /* 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 (AddHtInfoLen != 0) + Channel = pAddHtInfo->ControlChan; + + if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) + HtCapabilityLen = SIZE_HT_CAP_IE; +#endif /* DOT11_N_SUPPORT */ + + /* + Housekeeping "SsidBssTab" table for later-on ROAMing usage. + */ + Bssidx = BssTableSearchWithSSID(&pAd->MlmeAux.SsidBssTab, Bssid, Ssid, SsidLen, Channel); + if (Bssidx == BSS_NOT_FOUND) + { + /* discover new AP of this network, create BSS entry */ + Bssidx = BssTableSetEntry(pAd, &pAd->MlmeAux.SsidBssTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, + &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, + pHtCapability, pAddHtInfo, HtCapabilityLen,AddHtInfoLen,NewExtChannelOffset, Channel, + RealRssi, TimeStamp, CkipFlag, pEdcaParm, &QosCapability, + &QbssLoad, LenVIE, pVIE); + if (Bssidx == BSS_NOT_FOUND) + ; + else + { + PBSS_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, Addr2, MAC_ADDR_LEN); + + + } + } + + /* + Update ScanTab + */ + Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); + if (Bssidx == BSS_NOT_FOUND) + { + /* discover new AP of this network, create BSS entry */ + Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, + &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, + pHtCapability, pAddHtInfo, HtCapabilityLen,AddHtInfoLen,NewExtChannelOffset, Channel, + RealRssi, TimeStamp, CkipFlag, pEdcaParm, &QosCapability, + &QbssLoad, 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, 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 ((pAd->StaCfg.WepStatus != pAd->ScanTab.BssEntry[Bssidx].WepStatus) || + (pAd->StaCfg.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 (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", + Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5])); + AsicDisableSync(pAd); + COPY_MAC_ADDR(pAd->CommonCfg.Bssid, 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 (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 = DtimCount; + pAd->StaCfg.DtimPeriod = DtimPeriod; + pAd->StaCfg.LastBeaconRxTime = Now; + + + NdisZeroMemory(&RxWI, RXWISize); + RxWI.RSSI0 = Elem->Rssi0; + RxWI.RSSI1 = Elem->Rssi1; + RxWI.RSSI2 = Elem->Rssi2; + RxWI.PHYMODE = 0; /* Prevent SNR calculate error. */ + + if (INFRA_ON(pAd)) { + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID]; + if (pEntry) + Update_Rssi_Sample(pAd, + &pEntry->RssiSample, + &RxWI); + } + + Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, &RxWI); + + 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); + 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 == 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, ("PeerBeacon - STA receive channel switch announcement IE (New Channel =%d)\n", 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.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 ((((pAd->StaCfg.WepStatus != Ndis802_11WEPDisabled) << 4) ^ CapabilityInfo) & 0x0010) + { + /* + 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__, (CapabilityInfo & 0x0010) >> 4 , pAd->StaCfg.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 (AironetCellPowerLimit != 0xFF) + { + /* + We get the Cisco (ccx) "TxPower Limit" required + Changed to appropriate TxPower Limit for Ciso Compatible Extensions + */ + ChangeToCellPowerLimit(pAd, 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(CapabilityInfo))) + { + UCHAR MaxSupportedRateIn500Kbps = 0; + UCHAR idx; + MAC_TABLE_ENTRY *pEntry; +#ifdef WSC_STA_SUPPORT + PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl; +#endif /* WSC_STA_SUPPORT */ + + /* supported rates array may not be sorted. sort it and find the maximum rate */ + for (idx=0; idxLastBeaconRxTime + ADHOC_ENTRY_BEACON_LOST_TIME))) + { + if (pEntry == NULL) + /* Another adhoc joining, add to our MAC table. */ + pEntry = MacTableInsertEntry(pAd, Addr2, BSS0, OPMODE_STA, FALSE); + + if (pEntry == NULL) + goto LabelOK; + +#ifdef IWSC_SUPPORT + hex_dump("Another adhoc joining - Addr2", Addr2, 6); + hex_dump("Another adhoc joining - WscPeerMAC", pAd->StaCfg.WscControl.WscPeerMAC, 6); + if ((NdisEqualMemory(Addr2, pAd->StaCfg.WscControl.WscPeerMAC, MAC_ADDR_LEN)) && + (pAd->StaCfg.IWscInfo.bSendEapolStart == FALSE) && + (pWpsCtrl->bWscTrigger == TRUE)) + { + pAd->StaCfg.IWscInfo.bSendEapolStart = TRUE; + } +#endif /* IWSC_SUPPORT */ + + if (StaAddMacTableEntry(pAd, + pEntry, + MaxSupportedRateIn500Kbps, + pHtCapability, + HtCapabilityLen, + pAddHtInfo, + AddHtInfoLen, + CapabilityInfo) == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("ADHOC - Add Entry failed.\n")); + goto LabelOK; + } +#ifdef IWSC_SUPPORT + else + pEntry->bUpdateInfoFromPeerBeacon = TRUE; +#endif /* IWSC_SUPPORT */ + + if (ADHOC_ON(pAd) && pEntry) + { + RTMPSetSupportMCS(pAd, + OPMODE_STA, + pEntry, + SupRate, + SupRateLen, + ExtRate, + ExtRateLen, + pHtCapability, + HtCapabilityLen); + } + + pEntry->LastBeaconRxTime = 0; + +#ifdef ADHOC_WPA2PSK_SUPPORT + /* Adhoc support WPA2PSK by Eddy */ + if ((pAd->StaCfg.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 (Addr2[i] > pAd->CurrentAddress[i]) + { + bHigherMAC = TRUE; + break; + } + else if (Addr2[i] < pAd->CurrentAddress[i]) + break; + } + hex_dump("PeerBeacon:: Addr2", 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 = pAd->StaCfg.DefaultKeyId; + RTMP_SET_WCID_SEC_INFO(pAd, BSS0, idx, + pAd->SharedKey[BSS0][idx].CipherAlg, + pEntry->Aid, + SHAREDKEYTABLE); + } + } + + if (pEntry && IS_ENTRY_CLIENT(pEntry)) + { + pEntry->LastBeaconRxTime = Now; +#ifdef IWSC_SUPPORT + if (pEntry->bUpdateInfoFromPeerBeacon == FALSE) + { + if (StaAddMacTableEntry(pAd, + pEntry, + MaxSupportedRateIn500Kbps, + pHtCapability, + HtCapabilityLen, + pAddHtInfo, + AddHtInfoLen, + CapabilityInfo) == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("ADHOC 2 - Add Entry failed.\n")); + return; + } + + if (ADHOC_ON(pAd) && pEntry) + { + RTMPSetSupportMCS(pAd, + OPMODE_STA, + pEntry, + SupRate, + SupRateLen, + ExtRate, + ExtRateLen, + pHtCapability, + 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(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(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 ((AddHtInfoLen != 0) && + ((pAddHtInfo->AddHtInfo2.OperaionMode != pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode) || + (pAddHtInfo->AddHtInfo2.NonGfPresent != pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent))) + { + pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent = pAddHtInfo->AddHtInfo2.NonGfPresent; + pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode = pAddHtInfo->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(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) && + (pEdcaParm->bValid == TRUE) && + (pEdcaParm->EdcaUpdateCount != pAd->CommonCfg.APEdcaParm.EdcaUpdateCount)) + { + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP change EDCA parameters(from %d to %d)\n", + pAd->CommonCfg.APEdcaParm.EdcaUpdateCount, + pEdcaParm->EdcaUpdateCount)); + AsicSetEdcaParm(pAd, pEdcaParm); + } + + /* copy QOS related information */ + NdisMoveMemory(&pAd->CommonCfg.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM)); + NdisMoveMemory(&pAd->CommonCfg.APQosCapability, &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 ((AddHtInfoLen != 0) && INFRA_ON(pAd)) + { + BOOLEAN bChangeBW = FALSE; +#ifdef P2P_SUPPORT + PAPCLI_STRUCT pApCliEntry = NULL; + + pApCliEntry = &pAd->ApCfg.ApCliTab[BSS0]; +#endif /* P2P_SUPPORT */ + + /* + 1) HT Information + 2) Secondary Channel Offset Element + + 40 -> 20 case + */ + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + if (((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_NONE) && (pAddHtInfo->AddHtInfo.RecomWidth == 0)) + ||(NewExtChannelOffset==0x0) + ) + { + pAd->StaActive.SupportedHtPhy.ChannelWidth = BW_20; + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.BW = 0; + +#ifdef P2P_SUPPORT + if (!P2P_GO_ON(pAd) && (pApCliEntry->Valid == FALSE)) +#endif /* P2P_SUPPORT */ + { + 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) ||(NewExtChannelOffset!=0x0)) && + (pAd->CommonCfg.DesiredHtPhy.ChannelWidth != BW_20) + ) + { + if ((pAddHtInfo->AddHtInfo.ExtChanOffset != EXTCHA_NONE) && (pAddHtInfo->AddHtInfo.RecomWidth == 1) + && (HtCapabilityLen>0) && (pHtCapability->HtCapInfo.ChannelWidth == 1)) + { +#ifdef P2P_SUPPORT + if (!P2P_GO_ON(pAd) && (pApCliEntry->Valid == FALSE)) +#endif /* P2P_SUPPORT */ + { + if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW)) + { + pAd->CommonCfg.CentralChannel = pAddHtInfo->ControlChan - 2; + bChangeBW = TRUE; + } + else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE)) + { + pAd->CommonCfg.CentralChannel = pAddHtInfo->ControlChan + 2; + bChangeBW = TRUE; + } + + if (bChangeBW) + { + pAd->CommonCfg.Channel = pAddHtInfo->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, pAddHtInfo->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 (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; +#ifdef DOT11Z_TDLS_SUPPORT + RTMPSendNullFrame(pAd, + pAd->CommonCfg.TxRate, + TRUE, + pAd->CommonCfg.bAPSDForcePowerSave ? PWR_SAVE : pAd->StaCfg.Psm); +#endif /* DOT11Z_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 (BcastFlag && (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]) +#ifdef DOT11Z_TDLS_SUPPORT + || (pAd->StaCfg.FlgPsmCanNotSleep == TRUE)|| + (RtmpPktPmBitCheck(pAd) == FALSE) +#endif /* DOT11Z_TDLS_SUPPORT */ + ) + { + /* + WMM Spec v1.0 3.6.2.4, + The WMM STA shall remain awake until it receives a + QoS Data or Null frame addressed to it, with the + EOSP subfield in QoS Control field set to 1. + + So we can not sleep here or we will suffer a case: + + PS Management Frame --> + Trigger frame --> + Beacon (TIM=0) (Beacon is closer to Trig frame) --> + Station goes to sleep --> + AP delivery queued UAPSD packets --> + Station can NOT receive the reply + + Maybe we need a timeout timer to avoid that we do + NOT receive the EOSP frame. + + We can not use More Data to check if SP is ended + due to MaxSPLength. + */ + } + else + { + USHORT NextDtim = DtimCount; + + + if (NextDtim == 0) + NextDtim = 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->ThisTbttNumToNextWakeUp = TbttNumToNextWakeUp; + AsicSleepThenAutoWakeup(pAd, pAd->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 (Ssid != NULL) + os_free_mem(NULL, Ssid); + if (pEdcaParm != NULL) + os_free_mem(NULL, pEdcaParm); + if (VarIE != NULL) + os_free_mem(NULL, VarIE); + if (pHtCapability != NULL) + os_free_mem(NULL, pHtCapability); + if (pAddHtInfo != NULL) + os_free_mem(NULL, pAddHtInfo); + return; +} + +/* + ========================================================================== + Description: + Receive PROBE REQ from remote peer when operating in IBSS mode + ========================================================================== + */ +VOID PeerProbeReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + CHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SsidLen; +#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; + +#ifdef P2P_SUPPORT + /* P2P device and Listen State could response Probe Req. */ +/* if ((pAd->P2pCfg.DiscCurrentState == P2P_DISC_LISTEN) && !(P2P_CLI_ON(pAd)))*/ + if(P2P_INF_ON(pAd)) + MlmeEnqueue(pAd, P2P_DISC_STATE_MACHINE, P2P_DISC_PEER_PROB_REQ, Elem->MsgLen, Elem->Msg, Elem->Channel); +#endif /* P2P_SUPPORT */ + + if (! ADHOC_ON(pAd)) + return; + + if (PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen, NULL)) + { + if ((SsidLen == 0) || SSID_EQUAL(Ssid, 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, Addr2, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + pAd->CommonCfg.Bssid); + + Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) || + (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || + (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled); + 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 ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) +#ifdef ADHOC_WPA2PSK_SUPPORT + || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) +#endif /* ADHOC_WPA2PSK_SUPPORT */ + ) + { + ULONG tmp; + UCHAR RSNIe = IE_WPA; + +#ifdef ADHOC_WPA2PSK_SUPPORT + RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, BSS0); + if (pAd->StaCfg.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 (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + { + 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); +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +VOID InvalidStateWhenScan( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; +#ifdef P2P_SUPPORT + UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType; +#endif /* P2P_SUPPORT */ + + 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)); + +#ifdef P2P_SUPPORT + if (MlmeScanReqSanity(pAd, + Elem->Msg, + Elem->MsgLen, + &BssType, + (PCHAR)Ssid, + &SsidLen, + &ScanType)) + { + /* reset Device Discovery State Machine. */ + MlmeEnqueue(pAd, P2P_CTRL_STATE_MACHINE, P2P_CTRL_DISC_CANL_EVT, 0, NULL, 0); + P2PSetNextScanTimer(pAd, 10); + return; + } +#endif /* P2P_SUPPORT */ + 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( + IN PRTMP_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, 0, (PUCHAR)&pAd->PsPollFrame, sizeof(PSPOLL_FRAME)); + +} + + +/* + ========================================================================== + Description: + ========================================================================== + */ +VOID EnqueueProbeRequest( + IN PRTMP_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, +#ifdef P2P_SUPPORT + pAd->CurrentAddress, +#endif /* P2P_SUPPORT */ + 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 PrimaryChannel, + IN UCHAR CentralChannel, + IN UCHAR ChannelWidth, + IN UCHAR SecondaryChannelOffset) +{ + UCHAR Value = 0; + UINT32 Data = 0; + + + DBGPRINT(RT_DEBUG_TRACE, ("%s: PrimaryChannel[%d] \n",__FUNCTION__,PrimaryChannel)); + DBGPRINT(RT_DEBUG_TRACE, ("%s: CentralChannel[%d] \n",__FUNCTION__,CentralChannel)); + DBGPRINT(RT_DEBUG_TRACE, ("%s: ChannelWidth[%d] \n",__FUNCTION__,ChannelWidth)); + DBGPRINT(RT_DEBUG_TRACE, ("%s: SecondaryChannelOffset[%d] \n",__FUNCTION__,SecondaryChannelOffset)); + +#ifdef DOT11_N_SUPPORT + /*Change to AP channel */ + if (ChannelWidth == BW_40) + { + if(SecondaryChannelOffset == EXTCHA_ABOVE) + { + /* Must using 40MHz. */ + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, CentralChannel, FALSE); + AsicLockChannel(pAd, CentralChannel); + + 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); + + /* 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); +#ifdef RTMP_MAC_PCI + pAd->StaCfg.BBPR3 = Value; +#endif /* RTMP_MAC_PCI */ + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data &= 0xfffffffe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + 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_TRACE, ("!!!40MHz Lower !!! Control Channel at Below. Central = %d \n", pAd->CommonCfg.CentralChannel )); + } + else if (SecondaryChannelOffset == EXTCHA_BELOW) + { + /* Must using 40MHz. */ + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, CentralChannel, FALSE); + AsicLockChannel(pAd, CentralChannel); + + 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); + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data |= 0x1; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + 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, 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_TRACE, ("!!! 40MHz Upper !!! Control Channel at UpperCentral = %d \n", CentralChannel)); + } + } + else +#endif /* DOT11_N_SUPPORT */ + { + pAd->CommonCfg.BBPCurrentBW = BW_20; + AsicSwitchChannel(pAd, PrimaryChannel, FALSE); + AsicLockChannel(pAd, PrimaryChannel); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); + Value &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data &= 0xfffffffe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + 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_TRACE, ("!!! 20MHz !!! \n" )); + } + + RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW); + + AsicBBPReadWithRxChain(pAd, BBP_R66, &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); + + return; +} + diff --git a/mt7620/src/sta/tdls.c b/mt7620/src/sta/tdls.c new file mode 100644 index 0000000..0c02db7 --- /dev/null +++ b/mt7620/src/sta/tdls.c @@ -0,0 +1,3309 @@ +/**************************************************************************** + * 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 "dot11z_tdls.h" + +UCHAR TDLS_LLC_SNAP_WITH_CATEGORY[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x89, 0x0d, PROTO_NAME_TDLS, CATEGORY_TDLS}; +UCHAR TDLS_ETHERTYPE[] = {0x89, 0x0d}; + +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 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); + + 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; + } +} + +VOID +TDLS_Table_Destory( + IN PRTMP_ADAPTER pAd) +{ + UCHAR idx; + BOOLEAN TimerCancelled; + PRT_802_11_TDLS pTDLS = NULL; + +#ifdef UAPSD_SUPPORT + TDLS_UAPSDP_Release(pAd); +#endif /* UAPSD_SUPPORT */ + + NdisFreeSpinLock(&pAd->StaCfg.TdlsInfo.TDLSEntryLock); + + 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); + } +} + +UCHAR TDLS_GetRegulatoryClass( + IN PRTMP_ADAPTER pAd, + IN UCHAR ChannelWidth, + IN UCHAR TargetChannel) +{ + int i=0; + UCHAR regclass = 0; + + do + { + if (reg_class[i].spacing == ChannelWidth) + { + int j=0; + + do + { + if (reg_class[i].channelset[j] == TargetChannel) + { + 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; +} + +static 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; +} + + +static 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( + IN PRTMP_ADAPTER pAd, + IN PHEADER_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_ERROR, ("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_ERROR, ("TDLS <=== TDLS_AutoSetupByRcvFrame\n")); +} +#endif // TDLS_AUTOLINK_SUPPORT // + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +INT Set_TdlsCapableProc( + 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; + + 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_TdlsSetupProc( + 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_TdlsSetupProc() 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_TdlsTearDownProc( + 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_TdlsTearDownProc() 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_TdlsDiscoveryReqProc( + 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; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +INT Set_TdlsTPKLifeTimeProc( + 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; + + 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 +========================================================================== +*/ +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_WARN, ("TDLS - Receive Peer HT Capable STA from %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 ((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.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (pHtCapability->MCSSet[j]&bitmask)) + { + pEntry->MaxHTPhyMode.field.MCS = ii; + break; + } + + if (ii==0) + break; + } + + if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) + { + if (pAd->StaCfg.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.HTPhyMode.field.MCS) + { + /* STA supports fixed MCS */ + pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.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.bAutoTxRateSwitch == TRUE) + { + PUCHAR pTable; + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex); + pEntry->bAutoTxRateSwitch = TRUE; + } + else + { + pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + + RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.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; + 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)) + return FALSE; + + + 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; + } + + 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 */ + { + 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 + { + 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, + 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[], + OUT UCHAR *pLinkIdentLen, + OUT TDLS_LINK_IDENT_ELEMENT *pLinkIdent) +{ + ULONG RemainLen = MsgLen; + CHAR *Ptr =(CHAR *)Msg; + //PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + PEID_STRUCT pEid; + ULONG Length = 0; + + // 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; + *pLinkIdentLen = 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_WARN, ("PeerTdlsSetupReqSanity --> Invaild packet length - (action header) \n")); + 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_WARN, ("PeerTdlsSetupReqSanity --> Invaild packet length - (dialog token) \n")); + 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_WARN, ("PeerTdlsSetupReqSanity --> Invaild packet length - (capability) \n")); + 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(pLinkIdent, &pEid->Octet[0], sizeof(TDLS_LINK_IDENT_ELEMENT)); + *pLinkIdentLen = TDLS_ELM_LEN_LINK_IDENTIFIER; + NdisMoveMemory(pSA, pLinkIdent->InitiatorAddr, 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; + } + 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 (*pLinkIdentLen == 0) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsSetupReqSanity --> Invaild packet - (link identifier) \n")); + return FALSE; + } + else + { + if (!MAC_ADDR_EQUAL(pLinkIdent->BSSID, pAd->CommonCfg.Bssid)) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsSetupReqSanity --> It's not my BSSID\n")); + return FALSE; + } + else if (!MAC_ADDR_EQUAL(pLinkIdent->ResponderAddr, pAd->CurrentAddress)) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsSetupReqSanity --> It's not my MAC address\n")); + return FALSE; + } + } + + // Process in succeed + return TRUE; + +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +BOOLEAN PeerTdlsSetupRspSanity( + 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 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[], + OUT UCHAR *pLinkIdentLen, + OUT TDLS_LINK_IDENT_ELEMENT *pLinkIdent) +{ + ULONG RemainLen = MsgLen; + CHAR *Ptr =(CHAR *)Msg; + //PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + PEID_STRUCT pEid; + ULONG Length = 0; + + // 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; + *pLinkIdentLen = 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_WARN, ("PeerTdlsSetupRspSanity --> Invaild packet length - (action header) \n")); + 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_WARN, ("PeerTdlsSetupRspSanity --> Invaild packet length - (status code) \n")); + 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_WARN, ("PeerTdlsSetupRspSanity --> Invaild packet length - (dialog token) \n")); + 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(pLinkIdent, &pEid->Octet[0], sizeof(TDLS_LINK_IDENT_ELEMENT)); + *pLinkIdentLen = TDLS_ELM_LEN_LINK_IDENTIFIER; + NdisMoveMemory(pSA, pLinkIdent->ResponderAddr, 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; + } + 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 (*pLinkIdentLen == 0) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsSetupRspSanity --> Invaild packet - (link identifier) \n")); + return FALSE; + } + else + { + if (!MAC_ADDR_EQUAL(pLinkIdent->BSSID, pAd->CommonCfg.Bssid)) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsSetupRspSanity --> It's not my BSSID\n")); + return FALSE; + } + else if (!MAC_ADDR_EQUAL(pLinkIdent->InitiatorAddr, pAd->CurrentAddress)) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsSetupRspSanity --> It's not my MAC address\n")); + 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[], + OUT UCHAR *pLinkIdentLen, + OUT TDLS_LINK_IDENT_ELEMENT *pLinkIdent, + OUT UCHAR *pAddHtInfoLen, + OUT ADD_HT_INFO_IE *pAddHtInfo) +{ + ULONG RemainLen = MsgLen; + CHAR *Ptr =(CHAR *)Msg; + //PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + PEID_STRUCT pEid; + ULONG Length = 0; + + // Init output parameters + *pCapabilityInfo = 0; + *pStatusCode = MLME_REQUEST_DECLINED; + //pEdcaParm = 0; // default: no IE_EDCA_PARAMETER found + *pRsnLen = 0; + *pFTLen = 0; + *pTILen = 0; + *pLinkIdentLen = 0; + *pAddHtInfoLen = 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_WARN, ("PeerTdlsSetupConfSanity --> Invaild packet length - (action header) \n")); + 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_WARN, ("PeerTdlsSetupConfSanity --> Invaild packet length - (status code) \n")); + 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_WARN, ("PeerTdlsSetupConfSanity --> Invaild packet length - (dialog token) \n")); + 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) + NdisMoveMemory(pAddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE)); + *pAddHtInfoLen = SIZE_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(pLinkIdent, &pEid->Octet[0], sizeof(TDLS_LINK_IDENT_ELEMENT)); + *pLinkIdentLen = TDLS_ELM_LEN_LINK_IDENTIFIER; + NdisMoveMemory(pSA, pLinkIdent->InitiatorAddr, 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 (*pLinkIdentLen == 0) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsSetupConfSanity --> Invaild packet - (link identifier) \n")); + return FALSE; + } + else + { + if (!MAC_ADDR_EQUAL(pLinkIdent->BSSID, pAd->CommonCfg.Bssid)) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsSetupConfSanity --> It's not my BSSID\n")); + return FALSE; + } + else if (!MAC_ADDR_EQUAL(pLinkIdent->ResponderAddr, pAd->CurrentAddress)) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsSetupConfSanity --> It's not my MAC address\n")); + 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[], + OUT UCHAR *pLinkIdentLen, + OUT TDLS_LINK_IDENT_ELEMENT *pLinkIdent) +{ + ULONG RemainLen = MsgLen; + CHAR *Ptr =(CHAR *)Msg; + PEID_STRUCT pEid; + ULONG Length = 0; + + // 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_WARN, ("PeerTdlsTearDownSanity --> Invaild packet length - (cation header) \n")); + 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_WARN, ("PeerTdlsTearDownSanity --> Invaild packet length - (reason code) \n")); + 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(pLinkIdent, &pEid->Octet[0], sizeof(TDLS_LINK_IDENT_ELEMENT)); + *pLinkIdentLen = TDLS_ELM_LEN_LINK_IDENTIFIER; + NdisMoveMemory(pSA, pLinkIdent->ResponderAddr, 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 (*pLinkIdentLen == 0) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsTearDownSanity --> Invaild packet - (link identifier) \n")); + return FALSE; + } + else + { + if (!MAC_ADDR_EQUAL(pLinkIdent->BSSID, pAd->CommonCfg.Bssid)) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsTearDownSanity --> It's not my BSSID\n")); + return FALSE; + } + + // Check if my MAC address and then find out SA + if (!MAC_ADDR_EQUAL(pAd->CurrentAddress, pLinkIdent->InitiatorAddr)) + { + if (!MAC_ADDR_EQUAL(pAd->CurrentAddress, pLinkIdent->ResponderAddr)) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsTearDownSanity --> It's not my Address\n")); + return FALSE; + } + else + { + *pIsInitator = TRUE; // peer are Initator. + NdisMoveMemory(pSA, pLinkIdent->InitiatorAddr, MAC_ADDR_LEN); + } + } + else + { + *pIsInitator = FALSE; // peer are not Initator. + NdisMoveMemory(pSA, pLinkIdent->ResponderAddr, 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_WARN, ("PeerTdlsDiscovReqSanity --> Invaild packet length - (action header) \n")); + 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_WARN, ("PeerTdlsDiscovReqSanity --> Invaild packet length - (dialog token) \n")); + 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_WARN, ("PeerTdlsDiscovReqSanity --> Invaild packet length - (link identifier) \n")); + return FALSE; + } + if (!MAC_ADDR_EQUAL(Ptr+2, pAd->CommonCfg.Bssid)) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsDiscovReqSanity --> It's not my BSSID\n")); + return FALSE; + } + else if (!MAC_ADDR_EQUAL(Ptr+14, pAd->CurrentAddress)) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsDiscovReqSanity --> It's not my MAC address\n")); + 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[], + OUT UCHAR *pLinkIdentLen, + OUT TDLS_LINK_IDENT_ELEMENT *pLinkIdent) +{ + ULONG RemainLen = MsgLen; + CHAR *Ptr =(CHAR *)Msg; + //PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + PEID_STRUCT pEid; + ULONG Length = 0; + + // Init output parameters + *pSupRateLen = 0; + *pExtRateLen = 0; + *pCapabilityInfo = 0; + *pHtCapLen = 0; + *pTdlsExtCapLen = 0; + *pRsnLen = 0; + *pFTLen = 0; + *pTILen = 0; + *pLinkIdentLen = 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_WARN, ("PeerTdlsDiscovRspSanity --> Invaild packet length - (action header) \n")); + 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_WARN, ("PeerTdlsDiscovRspSanity --> Invaild packet length - (dialog token) \n")); + 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(pLinkIdent, &pEid->Octet[0], sizeof(TDLS_LINK_IDENT_ELEMENT)); + *pLinkIdentLen = TDLS_ELM_LEN_LINK_IDENTIFIER; + NdisMoveMemory(pSA, pLinkIdent->ResponderAddr, 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 (*pLinkIdentLen == 0) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsDiscovRspSanity --> Invaild packet - (link identifier) \n")); + return FALSE; + } + else + { + if (!MAC_ADDR_EQUAL(pLinkIdent->BSSID, pAd->CommonCfg.Bssid)) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsDiscovRspSanity --> It's not my BSSID\n")); + return FALSE; + } + else if (!MAC_ADDR_EQUAL(pLinkIdent->InitiatorAddr, pAd->CurrentAddress)) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsDiscovRspSanity --> It's not my MAC address\n")); + return FALSE; + } + } + + return TRUE; +} + +/* +========================================================================== + 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_WARN, ("PeerTdlsBasicSanity --> " + "Invaild packet length - (action header) \n")); + 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_WARN, ("PeerTdlsBasicSanity --> " + "Invaild packet length - (dialog token) \n")); + 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_WARN, ("PeerTdlsBasicSanity --> " + "Invaild packet length - (link identifier) \n")); + return 0; + } + + if (!MAC_ADDR_EQUAL(Ptr+2, pAd->CommonCfg.Bssid)) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsBasicSanity --> " + "It's not my BSSID\n")); + return 0; + } + + if (bInitiator) + { + if (!MAC_ADDR_EQUAL(Ptr+14, pAd->CurrentAddress)) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsBasicSanity --> " + "It's not my MAC address\n")); + 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_WARN, ("PeerTdlsBasicSanity --> " + "It's not my MAC address\n")); + 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); +} + +/* +========================================================================== + 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, ("====> TDLS_SendNullFrame\n")); + + /* WPA 802.1x secured port control */ + if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef WPA_SUPPLICANT_SUPPORT + || (pAd->StaCfg.IEEE8021X == TRUE) +#endif +#ifdef WAPI_SUPPORT + || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWAICERT) + || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWAIPSK) +#endif /* WAPI_SUPPORT */ + ) && + (pAd->StaCfg.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 = BTYPE_DATA; + pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC; + 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, ("<==== TDLS_SendNullFrame\n")); +} + +/* +========================================================================== + 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.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", + pEntry->Addr[0],pEntry->Addr[1],pEntry->Addr[2],pEntry->Addr[3], + pEntry->Addr[4],pEntry->Addr[5], 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", GetPhyMode(pEntry->HTPhyMode.field.MODE))); + DBGPRINT(RT_DEBUG_OFF, ("%-6s", GetBW(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; +} + +VOID TDLS_InitChannelRelatedValue( + IN PRTMP_ADAPTER pAd, + IN HT_CAPABILITY_IE *pHtCapability) +{ + UCHAR Value = 0; + UINT32 Data = 0; + +#ifdef RTMP_MAC_PCI + /* In power save , We will force use 1R. */ + /* So after link up, check Rx antenna # again. */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); + if(pAd->Antenna.field.RxPath == 3) + { + Value |= (0x10); + } + else if(pAd->Antenna.field.RxPath == 2) + { + Value |= (0x8); + } + else if(pAd->Antenna.field.RxPath == 1) + { + Value |= (0x0); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); + pAd->StaCfg.BBPR3 = Value; +#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) && + (pHtCapability->HtCapInfo.ChannelWidth == BW_40)) + { + /* Must using 40MHz. */ + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + + 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); + + /* 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); +#ifdef RTMP_MAC_PCI + pAd->StaCfg.BBPR3 = Value; +#endif /* RTMP_MAC_PCI */ + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data &= 0xfffffffe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + 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_TRACE, ("!!!40MHz Lower !!! Control Channel at Below. Central = %d \n", pAd->CommonCfg.CentralChannel )); + } + else if ((pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) && + (pHtCapability->HtCapInfo.ChannelWidth == BW_40)) + { + /* Must using 40MHz. */ + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + + 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); + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data |= 0x1; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + 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, 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_TRACE, ("!!! 40MHz Upper !!! Control Channel at UpperCentral = %d \n", pAd->CommonCfg.CentralChannel )); + } + else +#endif /* DOT11_N_SUPPORT */ + { + pAd->CommonCfg.BBPCurrentBW = BW_20; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); + Value &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data &= 0xfffffffe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + 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_TRACE, ("!!! 20MHz !!! \n" )); + } + + RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW); +} +#endif /* DOT11Z_TDLS_SUPPORT */ + diff --git a/mt7620/src/sta/tdls_chswitch_mng.c b/mt7620/src/sta/tdls_chswitch_mng.c new file mode 100644 index 0000000..a727339 --- /dev/null +++ b/mt7620/src/sta/tdls_chswitch_mng.c @@ -0,0 +1,1241 @@ +/**************************************************************************** + * 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 +========================================================================== +*/ +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, + OUT UCHAR *pLinkIdentLen, + OUT TDLS_LINK_IDENT_ELEMENT *pLinkIdent) +{ + 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, ("PeerTdlsChannelSwitchReqSanity --> Invaild packet length - (ation header) \n")); + 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, ("PeerTdlsChannelSwitchReqSanity --> Invaild packet length - (target channel) \n")); + 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_WARN, ("PeerTdlsChannelSwitchReqSanity --> Invaild packet length - (regulatory class) \n")); + return FALSE; + } + + *pRegulatoryClass = *Ptr; + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsChannelSwitchReqSanity - Regulatory class = %d \n", *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_WARN, ("PeerTdlsChannelSwitchReqSanity - wrong IE_SECONDARY_CH_OFFSET. \n")); + } + break; + + case IE_TDLS_LINK_IDENTIFIER: + if (pEid->Len == TDLS_ELM_LEN_LINK_IDENTIFIER) + { + NdisMoveMemory(pLinkIdent, &pEid->Octet[0], sizeof(TDLS_LINK_IDENT_ELEMENT)); + *pLinkIdentLen = TDLS_ELM_LEN_LINK_IDENTIFIER; + } + else + { + rv = FALSE; + DBGPRINT(RT_DEBUG_WARN, ("PeerTdlsChannelSwitchReqSanity - wrong IE_TDLS_LINK_IDENTIFIER. \n")); + } + break; + + case IE_TDLS_CHANNEL_SWITCH_TIMING: + if (pEid->Len == 4) + { + TDLS_CH_SWITCH_TIMING_ELEMENT ChSwitchTiming; + + NdisMoveMemory(&ChSwitchTiming, &pEid->Octet[0], sizeof(TDLS_CH_SWITCH_TIMING_ELEMENT)); + *pChSwitchTime = ChSwitchTiming.ChSwitchTime; + *pChSwitchTimeOut = ChSwitchTiming.ChSwitchTimeOut; + } + else + { + rv = FALSE; + DBGPRINT(RT_DEBUG_WARN, ("PeerTdlsChannelSwitchReqSanity - wrong IE_TDLS_CHANNEL_SWITCH_TIMING. \n")); + } + break; + + default: + // Unknown IE, we have to pass it as variable IEs + DBGPRINT(RT_DEBUG_WARN, ("PeerTdlsChannelSwitchReqSanity - unrecognized EID = %d\n", 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, + OUT UCHAR *pLinkIdentLen, + OUT TDLS_LINK_IDENT_ELEMENT *pLinkIdent) +{ + ULONG RemainLen = MsgLen; + CHAR *Ptr =(CHAR *)Msg; + PEID_STRUCT pEid; + ULONG Length = 0; + PHEADER_802_11 pHeader; + + // 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_WARN, ("PeerTdlsChannelSwitchRspSanity --> Invaild packet length - (ation header) \n")); + 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_WARN, ("PeerTdlsChannelSwitchRspSanity --> Invaild packet length - (status code) \n")); + 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) + { + NdisMoveMemory(pLinkIdent, &pEid->Octet[0], sizeof(TDLS_LINK_IDENT_ELEMENT)); + *pLinkIdentLen = TDLS_ELM_LEN_LINK_IDENTIFIER; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("PeerTdlsChannelSwitchRspSanity - wrong IE_TDLS_LINK_IDENTIFIER. \n")); + } + break; + + case IE_TDLS_CHANNEL_SWITCH_TIMING: + if (pEid->Len == 4) + { + TDLS_CH_SWITCH_TIMING_ELEMENT ChSwitchTiming; + + NdisMoveMemory(&ChSwitchTiming, &pEid->Octet[0], sizeof(TDLS_CH_SWITCH_TIMING_ELEMENT)); + *pChSwitchTime = ChSwitchTiming.ChSwitchTime; + *pChSwitchTimeOut = ChSwitchTiming.ChSwitchTimeOut; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("PeerTdlsChannelSwitchRspSanity - wrong IE_TDLS_CHANNEL_SWITCH_TIMING. \n")); + } + break; + default: + // Unknown IE, we have to pass it as variable IEs + DBGPRINT(RT_DEBUG_WARN, ("PeerTdlsChannelSwitchRspSanity - unrecognized EID = %d\n", pEid->Eid)); + break; + } + + Length = Length + 2 + pEid->Len; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + return TRUE; +} + +/* +========================================================================== + 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) +{ + 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); + pAd->StaCfg.TdlsCurrentChannelBW = 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); + pAd->StaCfg.TdlsCurrentChannelBW = EXTCHA_BELOW; + } + } + else + { + do + { + UCHAR ExtCh; + UCHAR Dir = pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; + ExtCh = TDLS_GetExtCh(TargetChannel, Dir); + if (TDLS_IsValidChannel(pAd, ExtCh)) + { + TDLS_InsertSecondaryChOffsetIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, Dir); + pAd->StaCfg.TdlsCurrentChannelBW = Dir; + break; + } + + 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); + pAd->StaCfg.TdlsCurrentChannelBW = Dir; + break; + } + } while(FALSE); + } + } + else + { + pAd->StaCfg.TdlsCurrentChannelBW = EXTCHA_NONE; + } + + /* fill link identifier */ + LinkId = TDLS_SearchLinkId(pAd, pPeerAddr); + if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY) + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_ChannelSwitchReqAction() can not find the LinkId!\n")); + return NDIS_STATUS_FAILURE; + } + 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 PMLME_TDLS_CH_SWITCH_STRUCT pChSwitchReq) +{ + 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; + UINT16 SwitchTime = pAd->StaCfg.TdlsInfo.TdlsSwitchTime; //micro seconds + UINT16 SwitchTimeout = pAd->StaCfg.TdlsInfo.TdlsSwitchTimeout; // micro seconds + INT LinkId = 0xff; + PRT_802_11_TDLS pTDLS = NULL; + + DBGPRINT(RT_DEBUG_WARN, ("====> TDLS_ChannelSwitchReqAction\n")); + + MAKE_802_3_HEADER(Header802_3, pChSwitchReq->PeerMacAddr, 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, pChSwitchReq->PeerMacAddr,SwitchTime, + SwitchTimeout, pChSwitchReq->TargetChannel, pChSwitchReq->TargetChannelBW); + + pEntry = MacTableLookup(pAd, pChSwitchReq->PeerMacAddr); + + if (pEntry && IS_ENTRY_TDLS(pEntry)) + { + pTDLS->ChannelSwitchCurrentState = TDLS_CHANNEL_SWITCH_WAIT_RSP; + if (pChSwitchReq->TargetChannel != pAd->CommonCfg.Channel) + RTMPToWirelessSta(pAd, pEntry, Header802_3, LENGTH_802_3, pOutBuffer, (UINT)FrameLen, FALSE, RTMP_TDLS_SPECIFIC_EDCA); + else + RTMPToWirelessSta(pAd, pEntry, Header802_3, LENGTH_802_3, pOutBuffer, (UINT)FrameLen, FALSE, RTMP_TDLS_SPECIFIC_HCCA); + pAd->StaCfg.TdlsCurrentChannel = pChSwitchReq->TargetChannel; + pAd->StaCfg.TdlsCurrentChannelBW = pChSwitchReq->TargetChannelBW; + } + 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_WARN, ("<==== TDLS_ChannelSwitchReqAction\n")); + + 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_WARN, ("TDLS ===> TDLS_ChannelSwitchRspAction\n")); + + 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 - TDLS_ChannelSwitchRspAction() allocate memory failed \n")); + return NStatus; + } + + MakeOutgoingFrame(pOutBuffer, &TempLen, + 1, &RemoteFrameType, + END_OF_ARGS); + + FrameLen = FrameLen + TempLen; + + TDLS_BuildChannelSwitchResponse(pAd, pOutBuffer, &FrameLen, pTDLS, ChSwitchTime, ChSwitchTimeOut, StatusCode); + + RTMPToWirelessSta(pAd, &pAd->MacTab.Content[pTDLS->MacTabMatchWCID], Header802_3, + LENGTH_802_3, pOutBuffer, (UINT)FrameLen, FALSE, FrameType); + + hex_dump("TDLS send channel switch response pack", pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_WARN, ("TDLS <=== TDLS_ChannelSwitchRspAction\n")); + + return NStatus; +} + + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID +TDLS_MlmeChannelSwitchAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PMLME_TDLS_CH_SWITCH_STRUCT pChSwReq = NULL; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + INT LinkId = 0xff; + + DBGPRINT(RT_DEBUG_WARN,("TDLS ===> TDLS_MlmeChannelSwitchAction() \n")); + + pChSwReq = (PMLME_TDLS_CH_SWITCH_STRUCT)Elem->Msg; + + if (pAd->StaActive.ExtCapInfo.TDLSChSwitchProhibited == TRUE) + { + DBGPRINT(RT_DEBUG_OFF,("%s(%d): AP Prohibite TDLS Channel Switch !!!\n", __FUNCTION__, __LINE__)); + 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,("TDLS - TDLS_MlmeChannelSwitchAction() can not find the LinkId!\n")); + return; + } + + pAd->StaCfg.TdlsForcePowerSaveWithAP = TRUE; + + if (pAd->StaCfg.bTdlsNoticeAPPowerSave == FALSE) + { + pAd->StaCfg.TdlsSendNullFrameCount = 0; + pAd->StaCfg.bTdlsNoticeAPPowerSave = TRUE; + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, TRUE); + } + else + { + pAd->StaCfg.TdlsSendNullFrameCount++; + if (pAd->StaCfg.TdlsSendNullFrameCount >= 200) + pAd->StaCfg.bTdlsNoticeAPPowerSave = FALSE; + } + + DBGPRINT(RT_DEBUG_ERROR, ("103. %ld !!!\n", (jiffies * 1000) / OS_HZ)); + + /* Build TDLS channel switch Request Frame */ + NStatus = TDLS_ChannelSwitchReqAction(pAd, pChSwReq); + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_MlmeChannelSwitchAction() Build Channel Switch Request Fail !!!\n")); + } + else + { + pAd->StaCfg.TdlsChannelSwitchPairCount++; + DBGPRINT(RT_DEBUG_WARN,("TDLS <=== TDLS_MlmeChannelSwitchAction() \n")); + } + } + else + { + DBGPRINT(RT_DEBUG_WARN,("TDLS <=== TDLS_MlmeChannelSwitchAction() TDLS only support infra mode !!!\n")); + } + + 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_WARN,("TDLS ===> TDLS_MlmeChannelSwitchRspAction() \n")); + + 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_OFF,("TDLS - TDLS_MlmeChannelSwitchRspAction() can not find the LinkId!\n")); + 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, 0, (RTMP_TDLS_SPECIFIC_CS_RSP_NOACK + RTMP_TDLS_SPECIFIC_HCCA)); + + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_MlmeChannelSwitchRspAction() Build Channel Switch Response Fail !!!\n")); + } + else + { + RTMPusecDelay(300); + NdisGetSystemUpTime(&pAd->StaCfg.TdlsGoBackStartTime); + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH); + if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_ABOVE); + else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_BELOW); + else + TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_NONE); + TDLS_EnablePktChannel(pAd, TDLS_FIFO_ALL); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH); + + DBGPRINT(RT_DEBUG_WARN,("TDLS <=== TDLS_MlmeChannelSwitchRspAction() \n")); + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_MlmeChannelSwitchRspAction() TDLS only support infra mode !!!\n")); + } + + 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; + //BOOLEAN TimerCancelled; + UCHAR TargetChannel; + UCHAR RegulatoryClass; + UCHAR NewExtChannelOffset = 0xff; + UCHAR LinkIdentLen; + USHORT PeerChSwitchTime; + USHORT PeerChSwitchTimeOut; + TDLS_LINK_IDENT_ELEMENT LinkIdent; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + USHORT StatusCode = MLME_SUCCESS; + UINT16 SwitchTime = pAd->StaCfg.TdlsInfo.TdlsSwitchTime; //micro seconds + UINT16 SwitchTimeout = pAd->StaCfg.TdlsInfo.TdlsSwitchTimeout; // micro seconds + + DBGPRINT(RT_DEBUG_WARN,("TDLS ===> TDLS_PeerChannelSwitchReqAction() \n")); + + // 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(%d): AP Prohibite TDLS Channel Switch !!!\n", __FUNCTION__, __LINE__)); + return; + } + + tdls_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, + &LinkIdentLen, + &LinkIdent)) + { + DBGPRINT(RT_DEBUG_ERROR,("%s(%d): from %02x:%02x:%02x:%02x:%02x:%02x Sanity Check Fail !!!\n", + __FUNCTION__,__LINE__, PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5])); + return; + } + + DBGPRINT(RT_DEBUG_WARN,("%s(%d): from %02x:%02x:%02x:%02x:%02x:%02x !!!\n", + __FUNCTION__,__LINE__, PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5])); + + 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(%d): can not find from %02x:%02x:%02x:%02x:%02x:%02x on TDLS entry !!!\n", + __FUNCTION__,__LINE__, PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5])); + return; + } + + if (pAd->StaCfg.bChannelSwitchInitiator == FALSE) + { + pAd->StaCfg.TdlsForcePowerSaveWithAP = TRUE; + + if (pAd->StaCfg.bTdlsNoticeAPPowerSave == FALSE) + { + pAd->StaCfg.TdlsSendNullFrameCount = 0; + pAd->StaCfg.bTdlsNoticeAPPowerSave = TRUE; + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, TRUE); + } + else + { + pAd->StaCfg.TdlsSendNullFrameCount++; + if (pAd->StaCfg.TdlsSendNullFrameCount >= 200) + pAd->StaCfg.bTdlsNoticeAPPowerSave = FALSE; + } + } + + + + // Point to the current Link ID + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId]; + + if (SwitchTime >= PeerChSwitchTime) + PeerChSwitchTime = SwitchTime; + + if (SwitchTimeout >= PeerChSwitchTimeOut) + PeerChSwitchTimeOut = SwitchTimeout; + + if (RtmpPktPmBitCheck(pAd)) + { + RTMP_SET_PSM_BIT(pAd, PWR_ACTIVE); + TDLS_SendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, 0); + } + + { + UINT32 macCfg, TxCount; + UINT32 MTxCycle; + + RTMP_IO_READ32(pAd, TX_REPORT_CNT, &macCfg); + + if (TargetChannel != pAd->CommonCfg.Channel) + NStatus = TDLS_ChannelSwitchRspAction(pAd, pTDLS, PeerChSwitchTime, PeerChSwitchTimeOut, StatusCode, RTMP_TDLS_SPECIFIC_CS_RSP_WAIT_ACK); + else + NStatus = TDLS_ChannelSwitchRspAction(pAd, pTDLS, PeerChSwitchTime, PeerChSwitchTimeOut, StatusCode, (RTMP_TDLS_SPECIFIC_CS_RSP_WAIT_ACK + RTMP_TDLS_SPECIFIC_HCCA)); + + + for (MTxCycle = 0; MTxCycle < 500; MTxCycle++) + { + RTMP_IO_READ32(pAd, TX_REPORT_CNT, &macCfg); + TxCount = macCfg & 0x0000ffff; + if (TxCount > 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("MTxCycle = %d, %ld !!!\n", MTxCycle, (jiffies * 1000) / OS_HZ)); + break; + } + else + RTMPusecDelay(50); + } + + if (MTxCycle >= 500) + { + NStatus = NDIS_STATUS_FAILURE; + DBGPRINT(RT_DEBUG_OFF,("TDLS Transmit Channel Switch Response Fail !!!\n")); + } + } + + if (NStatus == NDIS_STATUS_SUCCESS) + { + + { + if (TargetChannel != pAd->CommonCfg.Channel) + { + BOOLEAN TimerCancelled; + //ULONG Now, temp1, temp2, temp3; + + pAd->StaCfg.TdlsCurrentChannel = TargetChannel; + + if (NewExtChannelOffset != 0) + pAd->StaCfg.TdlsCurrentChannelBW = NewExtChannelOffset; + else + pAd->StaCfg.TdlsCurrentChannelBW = EXTCHA_NONE; + + pTDLS->ChSwitchTime = PeerChSwitchTime; + pAd->StaCfg.TdlsGlobalSwitchTime = PeerChSwitchTime; + pTDLS->ChSwitchTimeout = PeerChSwitchTimeOut; + pAd->StaCfg.TdlsGlobalSwitchTimeOut = PeerChSwitchTimeOut; + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH); + //Cancel the timer since the received packet to me. +#ifdef TDLS_HWTIMER_SUPPORT + TDLS_SetChannelSwitchTimer(pAd, (PeerChSwitchTimeOut / 1000)); +#else + RTMPCancelTimer(&pTDLS->ChannelSwitchTimeoutTimer, &TimerCancelled); + NdisGetSystemUpTime(&pTDLS->ChannelSwitchTimerStartTime); + RTMPSetTimer(&pTDLS->ChannelSwitchTimeoutTimer, (PeerChSwitchTimeOut / 1000)); +#endif // TDLS_HWTIMER_SUPPORT // + RTMPCancelTimer(&pAd->StaCfg.TdlsDisableChannelSwitchTimer, &TimerCancelled); + pAd->StaCfg.bTdlsCurrentDoingChannelSwitchWaitSuccess = TRUE; + pAd->StaCfg.bDoingPeriodChannelSwitch = TRUE; + + if (RTDebugLevel < RT_DEBUG_ERROR) + RTMPusecDelay(300); + else + DBGPRINT(RT_DEBUG_ERROR, ("1041. %ld !!!\n", (jiffies * 1000) / OS_HZ)); + TDLS_InitChannelRelatedValue(pAd, pAd->StaCfg.TdlsCurrentChannel, pAd->StaCfg.TdlsCurrentChannelBW); + } + else + { + pTDLS->bDoingPeriodChannelSwitch = FALSE; + pAd->StaCfg.bDoingPeriodChannelSwitch = FALSE; + pAd->StaCfg.TdlsForcePowerSaveWithAP = FALSE; + pAd->StaCfg.bTdlsNoticeAPPowerSave = FALSE; + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH); + RTMPusecDelay(300); + + if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_ABOVE); + else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_BELOW); + else + TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_NONE); + TDLS_EnablePktChannel(pAd, TDLS_FIFO_ALL); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH); + + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, FALSE); + } + } + } + + DBGPRINT(RT_DEBUG_WARN,("TDLS <=== TDLS_PeerChannelSwitchReqAction() \n")); + + 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 IsInitator; + BOOLEAN TimerCancelled; + //UCHAR RegulatoryClass; + //UCHAR NewExtChannelOffset = 0xff; + UCHAR LinkIdentLen; + USHORT PeerChSwitchTime; + USHORT PeerChSwitchTimeOut; + TDLS_LINK_IDENT_ELEMENT LinkIdent; + //NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + USHORT StatusCode = MLME_SUCCESS; + + DBGPRINT(RT_DEBUG_WARN,("TDLS ===> TDLS_PeerChannelSwitchRspAction() \n")); + + // Not TDLS Capable, ignore it + if (!IS_TDLS_SUPPORT(pAd)) + return; + + if (!INFRA_ON(pAd)) + return; + + hex_dump("TDLS peer channel switch response receive pack", Elem->Msg, Elem->MsgLen); + + if (!PeerTdlsChannelSwitchRspSanity(pAd, + Elem->Msg, + Elem->MsgLen, + PeerAddr, + &StatusCode, + &PeerChSwitchTime, + &PeerChSwitchTimeOut, + &LinkIdentLen, + &LinkIdent)) + { + DBGPRINT(RT_DEBUG_ERROR,("%s(%d): from %02x:%02x:%02x:%02x:%02x:%02x Sanity Check Fail !!!\n", + __FUNCTION__,__LINE__, PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5])); + 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(%d): can not find from %02x:%02x:%02x:%02x:%02x:%02x on TDLS entry !!!\n", + __FUNCTION__,__LINE__, PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5])); + 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_OFF,("%s(%d): received a failed StatusCode = %d on Unsolicited response !!!\n", + __FUNCTION__, __LINE__, StatusCode)); + return; + } + + if (StatusCode == MLME_REQUEST_DECLINED) + { + if ((pAd->StaCfg.TdlsChannelSwitchRetryCount > 0) && + (pTDLS->bDoingPeriodChannelSwitch) && + (pAd->StaCfg.bDoingPeriodChannelSwitch)) + { + pAd->StaCfg.TdlsChannelSwitchRetryCount--; + + DBGPRINT(RT_DEBUG_OFF,("%s(%d): received a failed StatusCode = %d re-try again !!!\n", + __FUNCTION__, __LINE__, StatusCode)); + } + else + { + pTDLS->bDoingPeriodChannelSwitch = FALSE; + pAd->StaCfg.bDoingPeriodChannelSwitch = FALSE; + pAd->StaCfg.bTdlsNoticeAPPowerSave = FALSE; + pAd->StaCfg.TdlsForcePowerSaveWithAP = FALSE; + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, FALSE); + } + + DBGPRINT(RT_DEBUG_OFF,("TDLS - TDLS_PeerChannelSwitchRspAction() received a failed StatusCode = %d !!!\n", StatusCode )); + return; + } + + DBGPRINT(RT_DEBUG_WARN,("%s(%d): from %02x:%02x:%02x:%02x:%02x:%02x !!!\n", + __FUNCTION__,__LINE__, PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5])); + + + + if (StatusCode == MLME_SUCCESS) + { + if (pTDLS->ChannelSwitchCurrentState == TDLS_CHANNEL_SWITCH_NONE) + { + if (pAd->StaCfg.bChannelSwitchInitiator == FALSE) + { + RTMPCancelTimer(&pAd->StaCfg.TdlsResponderGoBackBaseChTimer, &TimerCancelled); + DBGPRINT(RT_DEBUG_WARN,("%s(%d): i am responder!!!\n", __FUNCTION__,__LINE__)); + } + else + { + RTMPCancelTimer(&pAd->StaCfg.TdlsPeriodGoBackBaseChTimer, &TimerCancelled); + DBGPRINT(RT_DEBUG_WARN,("%s(%d): i am Initiator !!!\n", __FUNCTION__,__LINE__)); + } + + if (pAd->StaCfg.TdlsCurrentOperateChannel != pAd->CommonCfg.Channel) + { + DBGPRINT(RT_DEBUG_ERROR, ("106. %ld !!!\n", (jiffies * 1000) / OS_HZ)); + + RTMPusecDelay(300); + NdisGetSystemUpTime(&pAd->StaCfg.TdlsGoBackStartTime); + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH); + if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_ABOVE); + else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_BELOW); + else + TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_NONE); + TDLS_EnablePktChannel(pAd, TDLS_FIFO_ALL); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH); + } + } + else + { + if (pAd->StaCfg.TdlsCurrentChannel != pAd->CommonCfg.Channel) + { + if (pAd->StaCfg.bChannelSwitchInitiator) + { + UINT16 SwitchTime = pAd->StaCfg.TdlsInfo.TdlsSwitchTime; //micro seconds + UINT16 SwitchTimeout = pAd->StaCfg.TdlsInfo.TdlsSwitchTimeout; // micro seconds + + pAd->StaCfg.TdlsChannelSwitchPairCount--; + pAd->StaCfg.TdlsChannelSwitchRetryCount = 10; + //pAd->StaCfg.bDoingPeriodChannelSwitch = TRUE; + + if (SwitchTime >= PeerChSwitchTime) + PeerChSwitchTime = SwitchTime; + + if (SwitchTimeout >= PeerChSwitchTimeOut) + PeerChSwitchTimeOut = SwitchTimeout; + + pTDLS->ChSwitchTime = PeerChSwitchTime; + pAd->StaCfg.TdlsGlobalSwitchTime = PeerChSwitchTime; + pTDLS->ChSwitchTimeout = PeerChSwitchTimeOut; + pAd->StaCfg.TdlsGlobalSwitchTimeOut = PeerChSwitchTimeOut; + pTDLS->ChannelSwitchCurrentState = TDLS_CHANNEL_SWITCH_NONE; + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH); + //Cancel the timer since the received packet to me. +#ifdef TDLS_HWTIMER_SUPPORT + TDLS_SetChannelSwitchTimer(pAd, ((PeerChSwitchTime + pAd->StaCfg.TdlsOffChannelDelay) / 1000)); +#else + RTMPCancelTimer(&pTDLS->ChannelSwitchTimer, &TimerCancelled); + pTDLS->bEnableChSwitchTime = TRUE; + NdisGetSystemUpTime(&pTDLS->ChannelSwitchTimerStartTime); + RTMPSetTimer(&pTDLS->ChannelSwitchTimer, ((PeerChSwitchTime + pAd->StaCfg.TdlsOffChannelDelay) / 1000)); +#endif // TDLS_HWTIMER_SUPPORT // + + if (RTDebugLevel < RT_DEBUG_ERROR) + RTMPusecDelay(300); + else + DBGPRINT(RT_DEBUG_ERROR, ("104. %ld !!!\n", (jiffies * 1000) / OS_HZ)); + TDLS_InitChannelRelatedValue(pAd, pAd->StaCfg.TdlsCurrentChannel, pAd->StaCfg.TdlsCurrentChannelBW); + } + } + else + { + pTDLS->bDoingPeriodChannelSwitch = FALSE; + pAd->StaCfg.bDoingPeriodChannelSwitch = FALSE; + pAd->StaCfg.TdlsForcePowerSaveWithAP = FALSE; + pAd->StaCfg.bTdlsNoticeAPPowerSave = FALSE; + + if (pAd->StaCfg.bChannelSwitchInitiator == FALSE) + { + DBGPRINT(RT_DEBUG_OFF,("%s(%d): i am channel switch responder!!!\n", __FUNCTION__,__LINE__)); + } + else + { + RTMPCancelTimer(&pAd->StaCfg.TdlsDisableChannelSwitchTimer, &TimerCancelled); + pAd->StaCfg.bChannelSwitchInitiator = FALSE; + DBGPRINT(RT_DEBUG_OFF,("%s(%d): i am channel switch Initiator !!!\n", __FUNCTION__,__LINE__)); + } + + if (pAd->StaCfg.TdlsCurrentOperateChannel != pAd->CommonCfg.Channel) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH); + if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_ABOVE); + else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_BELOW); + else + TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_NONE); + TDLS_EnablePktChannel(pAd, TDLS_FIFO_ALL); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH); + } + + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, FALSE); + } + } + } + + + + + DBGPRINT(RT_DEBUG_WARN,("TDLS <=== TDLS_PeerChannelSwitchRspAction() \n")); + + return; +} + +/* +========================================================================== + Description: + + IRQL = PASSIVE_LEVEL +========================================================================== +*/ +VOID TDLS_ChannelSwitchTimeAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd; + PRT_802_11_TDLS pTDLS = (PRT_802_11_TDLS)FunctionContext; + + + DBGPRINT(RT_DEBUG_WARN, ("TDLS_ChannelSwitchTimeAction - channel switch procedure for (%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])); + + pAd = pTDLS->pAd; + + { + UINT32 macCfg, TxCount; + UINT32 MTxCycle; + UINT16 MaxWaitingTime; + + DBGPRINT(RT_DEBUG_ERROR, ("105. %ld !!!\n", (jiffies * 1000) / OS_HZ)); + + { + ULONG Now, temp1; + + NdisGetSystemUpTime(&Now); + temp1 = (((Now - pTDLS->ChannelSwitchTimerStartTime) * 1000) / OS_HZ); + + if (temp1 < (pTDLS->ChSwitchTime / 1000)) + { + DBGPRINT(RT_DEBUG_OFF, ("Timer = %ld < 11 !!!\n", temp1)); + } + } + RTMP_IO_READ32(pAd, TX_REPORT_CNT, &macCfg); + TDLS_SendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, RTMP_TDLS_SPECIFIC_NULL_FRAME); + TDLS_EnablePktChannel(pAd, TDLS_FIFO_HCCA); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH); + + MaxWaitingTime = ((pTDLS->ChSwitchTimeout - pTDLS->ChSwitchTime) / 1000); + for (MTxCycle = 0; MTxCycle < ((MaxWaitingTime + 1) * 20); MTxCycle++) + { + RTMP_IO_READ32(pAd, TX_REPORT_CNT, &macCfg); + TxCount = macCfg & 0x0000ffff; + if (TxCount > 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("MTxCycle = %d, %ld !!!\n", MTxCycle, (jiffies * 1000) / OS_HZ)); + break; + } + else + RTMPusecDelay(50); + } + + if (MTxCycle == ((MaxWaitingTime + 1) * 20)) + { + DBGPRINT(RT_DEBUG_OFF, ("24. %ld @@@!!!\n", (jiffies * 1000) / OS_HZ)); + + RTMPusecDelay(300); + NdisGetSystemUpTime(&pAd->StaCfg.TdlsGoBackStartTime); + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH); + if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_ABOVE); + else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_BELOW); + else + TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_NONE); + TDLS_EnablePktChannel(pAd, TDLS_FIFO_ALL); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH); + + 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; + BOOLEAN TimerCancelled; + + DBGPRINT(RT_DEBUG_WARN, ("TDLS - Failed to wait for channel switch, terminate the channel switch 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])); + + { + ULONG Now, temp1; + + NdisGetSystemUpTime(&Now); + temp1 = (((Now - pTDLS->ChannelSwitchTimerStartTime) * 1000) / OS_HZ); + + if (temp1 < (pTDLS->ChSwitchTimeout / 1000)) + { + RTMPSetTimer(&pTDLS->ChannelSwitchTimeoutTimer, ((pTDLS->ChSwitchTimeout / 1000) - temp1)); + return; + } + + if (temp1 < (pTDLS->ChSwitchTimeout / 1000)) + { + DBGPRINT(RT_DEBUG_OFF, ("Timer = %ld < 11 !!!\n", temp1)); + } + } + + RTMPCancelTimer(&pAd->StaCfg.TdlsResponderGoBackBaseChTimer, &TimerCancelled); + pAd->StaCfg.bTdlsCurrentDoingChannelSwitchWaitSuccess = FALSE; + pAd->StaCfg.bDoingPeriodChannelSwitch = FALSE; + + RTMPusecDelay(300); + NdisGetSystemUpTime(&pAd->StaCfg.TdlsGoBackStartTime); + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH); + if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_ABOVE); + else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_BELOW); + else + TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_NONE); + TDLS_EnablePktChannel(pAd, TDLS_FIFO_ALL); + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH); +} +#endif /* DOT11Z_TDLS_SUPPORT */ + diff --git a/mt7620/src/sta/tdls_ctrl.c b/mt7620/src/sta/tdls_ctrl.c new file mode 100644 index 0000000..b09719f --- /dev/null +++ b/mt7620/src/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/mt7620/src/sta/tdls_link_mng.c b/mt7620/src/sta/tdls_link_mng.c new file mode 100644 index 0000000..385a303 --- /dev/null +++ b/mt7620/src/sta/tdls_link_mng.c @@ -0,0 +1,3394 @@ +/**************************************************************************** + * 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; + + 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); + + for (i = 0; i < MAX_NUMBER_OF_DLS_ENTRY; i++) + { + pAd->StaCfg.TdlsInfo.TDLSEntry[i].pAd = pAd; + + RTMPInitTimer(pAd, &pAd->StaCfg.TdlsInfo.TDLSEntry[i].Timer, GET_TIMER_FUNCTION(TDLS_TimeoutAction), + &pAd->StaCfg.TdlsInfo.TDLSEntry[i], 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.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.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); + + // ==>> 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.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.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); + } +} + +/* +========================================================================== + 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.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); +} + +/* +========================================================================== + 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.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, + 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, ("TDLS ===> TDLS_DiscoveryReqAction\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, + 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, ("TDLS <=== TDLS_DiscoveryReqAction\n")); + + 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_ERROR, ("TDLS ===> TDLS_DiscoveryRspAction\n")); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("ACT - TDLS_DiscoveryRspAction() allocate memory failed \n")); + 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.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.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_ERROR, ("TDLS <=== TDLS_DiscoveryRspAction\n")); + + 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, ("====> TDLS_SetupRequestAction\n")); + + 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 - TDLS_SetupRequestAction() allocate memory failed \n")); + 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, ("<==== TDLS_SetupRequestAction\n")); + + 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, ("====> TDLS_SetupResponseAction\n")); + + 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 - TDLS_SetupResponseAction() allocate memory failed \n")); + 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, ("<==== TDLS_SetupResponseAction\n")); + + 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, ("====> TDLS_SetupConfirmAction\n")); + + 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 - TDLS_SetupConfirmAction() allocate memory failed \n")); + 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, ("<==== TDLS_SetupConfirmAction\n")); + + 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, ("====> TDLS_LinkTearDown\n")); + + /* 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, ("<==== TDLS_LinkTearDown\n")); +} + +/* +========================================================================== + 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_ERROR, ("TDLS ===> TDLS_TearDownPeerLink\n")); + + // 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, ("Peer MAC - not found !!!\n")); + } + + DBGPRINT(RT_DEBUG_ERROR, ("TDLS <=== TDLS_TearDownPeerLink\n")); +} + +/* +========================================================================== + 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, ("====> TDLS_TearDownAction\n")); + + 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 - TDLS_TearDownAction() allocate memory failed \n")); + 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, ("<==== TDLS_TearDownAction\n")); + + 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_ERROR,("===> TDLS_MlmeDiscoveryReqAction() \n")); + + NdisMoveMemory(PeerMacAddr, Elem->Msg, MAC_ADDR_LEN); + + if (INFRA_ON(pAd)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Send Discovery Request to Peer ::%02x:%02x:%02x:%02x:%02x:%02x !!!\n", + PeerMacAddr[0], PeerMacAddr[1], PeerMacAddr[2], + PeerMacAddr[3], PeerMacAddr[4], PeerMacAddr[5])); + + /* 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,("TDLS - TDLS_MlmeDiscoveryReqAction() Build Discovery Setup Request Fail !!!\n")); + } + else + { +#ifdef TDLS_AUTOLINK_SUPPORT + pTdlsPeer = TDLS_FindDiscoveryEntry(pTdlsDiscoveryEnList, PeerMacAddr); +#endif // TDLS_AUTOLINK_SUPPORT // + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_MlmeDiscoveryReqAction() Build Discovery Setup Request Fail, Because STA is not connect to AP!!!\n")); + } + + DBGPRINT(RT_DEBUG_ERROR,("<=== TDLS_MlmeDiscoveryReqAction() \n")); + + return; +} + +/* +========================================================================== + 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_ERROR,("TDLS - TDLS_PeerDiscoveryReqAction() \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, ("PeerTdlsDiscovReqSanity --> Invaild packet length - (action header) \n")); + 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_WARN, ("PeerTdlsDiscovReqSanity --> Invaild packet length - (dialog token) \n")); + 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_WARN, ("PeerTdlsDiscovReqSanity --> Invaild packet length - (link identifier) \n")); + return; + } + if (!MAC_ADDR_EQUAL(Ptr+2, pAd->CommonCfg.Bssid)) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsDiscovReqSanity --> It's not my BSSID\n")); + return; + } + else if (!MAC_ADDR_EQUAL(Ptr+14, pAd->CurrentAddress)) + { + DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsDiscovReqSanity --> It's not my MAC address\n")); + 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,("TDLS - TDLS_PeerDiscoveryReqAction() Build Discovery Response Fail !!!\n")); + } + + 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, LinkIdentLen; + UCHAR RsnIe[64], FTIe[128], TIIe[7]; + HT_CAPABILITY_IE HtCap; + EXT_CAP_INFO_ELEMENT ExtCap; + TDLS_LINK_IDENT_ELEMENT LinkIdent; + PFRAME_802_11 pFrame = (PFRAME_802_11)Elem->Msg; + + DBGPRINT(RT_DEBUG_ERROR,("TDLS ===> TDLS_DiscoveryRspPublicAction() \n")); + + 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, + &LinkIdentLen, + &LinkIdent)) + { + 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_ERROR,("TDLS <=== TDLS_DiscoveryRspPublicAction() \n")); + + 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_ERROR,("TDLS ===> TDLS_MlmeSetupReqAction() \n")); + + pInfo = (MLME_TDLS_REQ_STRUCT *)Elem->Msg; + + pTDLS = pInfo->pTDLS; + + if (pAd->StaActive.ExtCapInfo.TDLSProhibited == TRUE) + { + DBGPRINT(RT_DEBUG_OFF,("TDLS - TDLS_MlmeSetupReqAction() AP Prohibited TDLS !!!\n")); + return; + } + + /* Build TDLS Setup Request Frame */ + NStatus = TDLS_SetupRequestAction(pAd, pTDLS); + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_MlmeSetupReqAction() Build Setup Request Fail !!!\n")); + } + + DBGPRINT(RT_DEBUG_ERROR,("TDLS <=== TDLS_MlmeSetupReqAction() \n")); + + 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, LinkIdentLen; + UCHAR RsnIe[64], FTIe[128], TIIe[7]; + UCHAR QosCapability; + HT_CAPABILITY_IE HtCap; + EXT_CAP_INFO_ELEMENT ExtCap; + BOOLEAN bDiscard = FALSE; + BOOLEAN bWmmCapable; + TDLS_LINK_IDENT_ELEMENT LinkIdent; + + DBGPRINT(RT_DEBUG_ERROR, ("TDLS ===> TDLS_PeerSetupReqAction\n")); + + // Not TDLS Capable, ignore it + if (!IS_TDLS_SUPPORT(pAd)) + return; + + // Not BSS mode, ignore it + if (!INFRA_ON(pAd)) + return; + + if (pAd->StaActive.ExtCapInfo.TDLSProhibited == TRUE) + { + DBGPRINT(RT_DEBUG_OFF,("TDLS - TDLS_PeerSetupReqAction() AP Prohibited TDLS !!!\n")); + return; + } + + // 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)); + NdisZeroMemory(&LinkIdent, sizeof(LinkIdent)); + + + hex_dump("TDLS setup request receive pack", Elem->Msg, Elem->MsgLen); + + if (!PeerTdlsSetupReqSanity( + pAd, + Elem->Msg, + Elem->MsgLen, + &Token, + PeerAddr, + &CapabilityInfo, + &SupRateLen, + &SupRate[0], + &ExtRateLen, + &ExtRate[0], + &bWmmCapable, + &QosCapability, + &HtCapLen, + &HtCap, + &ExtCapLen, + &ExtCap, + &RsnLen, + RsnIe, + &FTLen, + FTIe, + &TILen, + TIIe, + &LinkIdentLen, + &LinkIdent)) + { + StatusCode = MLME_REQUEST_DECLINED; + } + + DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupReqAction() received a request from %02x:%02x:%02x:%02x:%02x:%02x\n", + PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5])); + + if ((pAd->StaCfg.WepStatus != Ndis802_11WEPDisabled) && (RsnLen == 0)) + { + StatusCode = MLME_INVALID_SECURITY_POLICY; + } + +#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; + //pTDLS = pTmpTDLS; + DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupReqAction() find the same entry \n")); + } + 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,("TDLS - PeerTdlsSetupReqAction() find the same entry and discard it\n")); + } + } + 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)) + return; + + 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) + return; + + if (idx >= 0) + { + pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[idx]; + if (pTDLS->Token == Token) + { + DBGPRINT(RT_DEBUG_WARN, ("TDLS - PeerTdlsSetupReqAction() receive the same token TDLS request !!!\n")); + return; + } + } + + /* 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_ERROR,("TDLS - PeerTdlsSetupReqAction() create a new entry \n")); + + break; + } + } + } + + + if (idx < 0) + { + // Table full !!!!! + StatusCode = MLME_REQUEST_DECLINED; + DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupReqAction() TDLSEntry table full(only can support %d TDLS session) \n", + MAX_NUM_OF_TDLS_ENTRY)); + } + else if (pTDLS) + { + // + // Process TPK Handshake Message 1 here! + // + if (pAd->StaCfg.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, pTDLS, RsnIe, RsnLen, FTIe, FTLen, TIIe, TILen); + if (Result != MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_TPKMsg1Process() Failed, reason=%d \n", Result)); + if (Result == MLME_REQUEST_DECLINED) // if mic error , ignore + { + return; + } + 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; + } + } + +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; + + } + + DBGPRINT(RT_DEBUG_ERROR, ("TDLS <=== TDLS_PeerSetupReqAction\n")); + + 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, LinkIdentLen; + 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; + TDLS_LINK_IDENT_ELEMENT LinkIdent; + PFRAME_802_11 pFrame = (PFRAME_802_11)Elem->Msg; + + DBGPRINT(RT_DEBUG_ERROR, ("TDLS ===> TDLS_PeerSetupRspAction\n")); + + // 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 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)); + NdisZeroMemory(&LinkIdent, sizeof(LinkIdent)); + + if (!PeerTdlsSetupRspSanity( + pAd, + Elem->Msg, + Elem->MsgLen, + &Token, + PeerAddr, + &CapabilityInfo, + &SupRateLen, + SupRate, + &ExtRateLen, + ExtRate, + &bWmmCapable, + &QosCapability, + &HtCapLen, + &HtCap, + &ExtCapLen, + &ExtCap, + &StatusCode, + &RsnLen, + RsnIe, + &FTLen, + FTIe, + &TILen, + TIIe, + &LinkIdentLen, + &LinkIdent)) + { + LocalStatusCode = MLME_REQUEST_DECLINED; + } + + + DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupRspAction() received a response from %02x:%02x:%02x:%02x:%02x:%02x with StatusCode=%d\n", + PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5], 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,("TDLS - TDLS_PeerSetupRspAction() can not find the LinkId!\n")); + 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; + + DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupRspAction() received a failed StatusCode, terminate the setup procedure \n")); + + return; + } + 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,("TDLS - PeerTdlsSetupRspAction() Not in TDLS_MODE_WAIT_RESPONSE STATE\n")); + StatusCode = MLME_REQUEST_DECLINED; + break; + } + + // Is the same Dialog Token? + if (pTDLS->Token != Token) + { + DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupRspAction() Not match with Dialig Token my token = %d, peer token = %d\n", + pTDLS->Token, Token)); + + StatusCode = MLME_REQUEST_DECLINED; + break; + } + + // Process TPK Handshake Message 2 here! + if (pAd->StaCfg.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,("TDLS - TDLS_TPKMsg2Process() Failed, reason=%d \n", Result)); + if (Result == MLME_REQUEST_DECLINED) // if mic error , ignore + { + return; + } + 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.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, BSS0 + MIN_NET_DEVICE_FOR_TDLS, OPMODE_STA, TRUE); + + if (pMacEntry) + { + pTDLS->MacTabMatchWCID = pMacEntry->Aid; + pMacEntry->AuthMode = pAd->StaCfg.AuthMode; + pMacEntry->WepStatus = pAd->StaCfg.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_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, + &CapabilityInfo, + SupRateLen, + SupRate, + HtCapLen, + &HtCap); + + RTMPSetSupportMCS(pAd, + OPMODE_STA, + pMacEntry, + SupRate, + SupRateLen, + ExtRate, + ExtRateLen, + &HtCap, + HtCapLen); + + // + // Install Peer Key if RSNA Enabled + // + if (pAd->StaCfg.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,("TDLS - PeerTdlsSetupRspAction() MacTableInsertEntry failed\n")); + } + } + else + StatusCode = MLME_REQUEST_DECLINED; + +send_out: + + if (StatusCode == MLME_SUCCESS) + { + TDLS_SetupConfirmAction(pAd, pTDLS, RsnLen, RsnIe, FTLen, FTIe, TILen, TIIe, StatusCode); + + pTDLS->ChSwitchTime = pAd->StaCfg.TdlsInfo.TdlsSwitchTime; + pTDLS->ChSwitchTimeout = pAd->StaCfg.TdlsInfo.TdlsSwitchTimeout; + pTDLS->Status = TDLS_MODE_CONNECTED; + + 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, ("TDLS - PeerTdlsSetupRspAction() receive the same token TDLS response !!!\n")); + return; + } + + pTDLS->Status = TDLS_MODE_NONE; + pTDLS->Valid = FALSE; + } + + //pAd->StaCfg.TdlsCurrentOperateChannel = pAd->CommonCfg.Channel; + + DBGPRINT(RT_DEBUG_ERROR, ("TDLS <=== TDLS_PeerSetupRspAction\n")); + + 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, LinkIdentLen; + UCHAR RsnIe[64], FTIe[128], TIIe[7]; + PMAC_TABLE_ENTRY pMacEntry = NULL; + TDLS_LINK_IDENT_ELEMENT LinkIdent; + ADD_HT_INFO_IE AddHtInfo; + UCHAR AddHtInfoLen; + PFRAME_802_11 pFrame = (PFRAME_802_11)Elem->Msg; + + DBGPRINT(RT_DEBUG_ERROR, ("TDLS ===> TDLS_PeerSetupConfAction\n")); + + // 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, + &LinkIdentLen, + &LinkIdent, + &AddHtInfoLen, + &AddHtInfo)) + { + 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; + + 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.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.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, BSS0 + MIN_NET_DEVICE_FOR_TDLS, OPMODE_STA, TRUE); + + if (pMacEntry) + { + pTDLS->MacTabMatchWCID = pMacEntry->Aid; + pMacEntry->AuthMode = pAd->StaCfg.AuthMode; + pMacEntry->WepStatus = pAd->StaCfg.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, + &pTDLS->HtCapability, + pTDLS->HtCapabilityLen); + + // + // Install Peer Key if RSNA Enabled + // + if (pAd->StaCfg.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 = pAd->StaCfg.TdlsInfo.TdlsSwitchTime; + pTDLS->ChSwitchTimeout = pAd->StaCfg.TdlsInfo.TdlsSwitchTimeout; + + 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; + //pAd->StaCfg.TdlsCurrentOperateChannel = pAd->CommonCfg.Channel; + DBGPRINT(RT_DEBUG_ERROR, ("TDLS <=== TDLS_PeerSetupConfAction\n")); + + 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; + //UINT i; + BOOLEAN TimerCancelled; + UCHAR FTLen, LinkIdentLen; + UCHAR FTIe[128]; + TDLS_LINK_IDENT_ELEMENT LinkIdent; + 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)); + NdisZeroMemory(&LinkIdent, sizeof(LinkIdent)); + + if (!PeerTdlsTearDownSanity(pAd, + Elem->Msg, + Elem->MsgLen, + SA, + &IsInitator, + &ReasonCode, + &FTLen, + FTIe, + &LinkIdentLen, + &LinkIdent)) + { + 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_TimeoutAction( + 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; + } +} + +/* +========================================================================== + 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/mt7620/src/sta/tdls_tlv.c b/mt7620/src/sta/tdls_tlv.c new file mode 100644 index 0000000..8b6177d --- /dev/null +++ b/mt7620/src/sta/tdls_tlv.c @@ -0,0 +1,1101 @@ +/**************************************************************************** + * 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) + { + ULONG TempLen; + UCHAR SupportChIe = IE_SUPP_CHANNELS; + UCHAR FirstChannel = 1; + UCHAR NumOfCh = 11; + UCHAR Length = 2; + + if ((pAd->CommonCfg.PhyMode == PHY_11BG_MIXED) || + (pAd->CommonCfg.PhyMode == PHY_11B) || + (pAd->CommonCfg.PhyMode == PHY_11G) || + (pAd->CommonCfg.PhyMode == PHY_11BGN_MIXED)) + { + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &SupportChIe, + 1, &Length, + 1, &FirstChannel, + 1, &NumOfCh, + END_OF_ARGS); + *pFrameLen = *pFrameLen + TempLen; + } + else if ((pAd->CommonCfg.PhyMode == PHY_11A) || + (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED)) + { + ULONG TempLen1; + + FirstChannel = 36; + NumOfCh = 8; + Length = 4; + MakeOutgoingFrame(pFrameBuf, &TempLen1, + 1, &SupportChIe, + 1, &Length, + 1, &FirstChannel, + 1, &NumOfCh, + END_OF_ARGS); + *pFrameLen = *pFrameLen + TempLen1; + + FirstChannel = 149; + NumOfCh = 4; + MakeOutgoingFrame((pFrameBuf + TempLen1), &TempLen, + 1, &FirstChannel, + 1, &NumOfCh, + END_OF_ARGS); + *pFrameLen = *pFrameLen + TempLen; + } + else if ((pAd->CommonCfg.PhyMode == PHY_11BG_MIXED) || + (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) || + (pAd->CommonCfg.PhyMode == PHY_11BGN_MIXED) || + (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED)) + { + ULONG TempLen1, TempLen2; + Length = 6; + + MakeOutgoingFrame(pFrameBuf, &TempLen1, + 1, &SupportChIe, + 1, &Length, + 1, &FirstChannel, + 1, &NumOfCh, + END_OF_ARGS); + *pFrameLen = *pFrameLen + TempLen1; + + FirstChannel = 36; + NumOfCh = 8; + MakeOutgoingFrame((pFrameBuf + TempLen1), &TempLen2, + 1, &FirstChannel, + 1, &NumOfCh, + END_OF_ARGS); + *pFrameLen = *pFrameLen + TempLen2; + + FirstChannel = 149; + NumOfCh = 4; + MakeOutgoingFrame((pFrameBuf + TempLen1 + TempLen2), &TempLen, + 1, &FirstChannel, + 1, &NumOfCh, + END_OF_ARGS); + *pFrameLen = *pFrameLen + TempLen; + } + } + + 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 ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) || (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 (((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) || (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 ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) || (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 (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + { + 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) && + (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && + (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/mt7620/src/sta/tdls_uapsd.c b/mt7620/src/sta/tdls_uapsd.c new file mode 100644 index 0000000..f20edc2 --- /dev/null +++ b/mt7620/src/sta/tdls_uapsd.c @@ -0,0 +1,1862 @@ +/**************************************************************************** + * 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_CmdUtilHexGet( + IN CHAR **ppArgv); +/* 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; + + + if (PsmOld == PsmNew) + return; /* no inform needs */ + + /* sanity check */ + /* WPA 802.1x secured port control */ + if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef WPA_SUPPLICANT_SUPPORT + || (pAd->StaCfg.IEEE8021X == TRUE) +#endif +#ifdef WAPI_SUPPORT + || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWAICERT) + || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWAIPSK) +#endif /* WAPI_SUPPORT */ + ) && + (pAd->StaCfg.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: + **ppArgv - input parameters + +Return Value: + decimal number + +Note: + Only for one hex byte. +======================================================================== +*/ +static UINT32 TDLS_UAPSD_CmdUtilHexGet( + 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 */ + + AtoH(Buf, &Value, 1); + return (UINT32)Value; +} /* End of TDLS_UAPSD_CmdUtilHexGet */ + + +/* +======================================================================== +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/mt7620/src/sta/wpa.c b/mt7620/src/sta/wpa.c new file mode 100644 index 0000000..854a99a --- /dev/null +++ b/mt7620/src/sta/wpa.c @@ -0,0 +1,402 @@ +/* + *************************************************************************** + * 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" + +void inc_byte_array(UCHAR *counter, int len); + +/* + ======================================================================== + + 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( + IN PRTMP_ADAPTER pAd, + IN 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 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, + MLME_CNTL_STATE_MACHINE, + OID_802_11_MIC_FAILURE_REPORT_FRAME, + 1, + &unicastKey, 0); + + if (pAd->StaCfg.MicErrCnt == 2) + { + RTMPSetTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, 100); + } +} + + +#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 PRTMP_ADAPTER pAd, + IN PUCHAR 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 */ + +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.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, 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.WepStatus == Ndis802_11Encryption3Enabled) + { /* 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( + IN PRTMP_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_11Encryption2Enabled) + pSharedKey->CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) + 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( + IN PRTMP_ADAPTER pAd) +{ + PCIPHER_KEY pSharedKey; + + pSharedKey = &pAd->SharedKey[BSS0][pAd->StaCfg.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_11Encryption2Enabled) + pSharedKey->CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled) + 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.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( + IN PRTMP_ADAPTER pAd, + IN PUCHAR 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/mt7620/src/sta_ate_iwpriv_usage.txt b/mt7620/src/sta_ate_iwpriv_usage.txt new file mode 100755 index 0000000..46b0c2f --- /dev/null +++ b/mt7620/src/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=-89¡K + ¡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/mt7620/src/threadX.MakeFile b/mt7620/src/threadX.MakeFile new file mode 100755 index 0000000..bc6dd0e --- /dev/null +++ b/mt7620/src/threadX.MakeFile @@ -0,0 +1,104 @@ +################################################################################ +## MAKEFILE +## LIB: RT_WIFI +## DESCRIPTION: library to control the swath generator +################################################################################ +!include "..\config.mak" + +################################################################################ +## PREDEFINES - neeeded for MakefileLib +################################################################################ +# Library Name +LIBNAME = rt_wifi + +# SDK Header +SDK_HEADER = -ID:\code_dev\tronfirmware\firmware\dc_sdk\public_include + +#MODE - STA or AP or APSTA. +RT28xx_MODE = STA + +#TARTET - THREADX. +TARGET = THREADX + +#CHIPSET - 2860 or 2870 or 2880 or 2070 or 3070 or 3090 or 3572 or 3062 or 3562 +CHIPSET = 3370 + +#PLATFORM: Target platform +PLATFORM = KODAK_DC + +#RELEASE Package +RELEASE = DPA + +#Include RT_WIFI Makfile +!include "os\threadX\Makefile.nmk" + +# Objects +VARIANT_OBJ_C = $(RT_WIFI_OBJS) + +OBJf = $(VARIANT_OBJ_C) + +# CFLAGS + +# Module CFLAGS +MODULE_CFLAGS = $(SDK_HEADER) $(RT_WIFI_CFLAGS) -DENABLE_WIFI + +# Dependency files +DEPSf = + +# Directory Paths +FWDIR = $(MAKEDIR)\.. +OALIBDIR = $(FWDIR)\oalib + +!if "$(ARCH)" == "ARM9_RV" +MODULE_CFLAGS = --gnu --c99 --signed_chars +!endif + +################################################################################ +## INCLUDES +################################################################################ +!include "$(OALIBDIR)\MakefileLib" + +################################################################################ +## DEFINES +################################################################################ + +################################################################################ +## RULES +################################################################################ + +# Setup Rules for source files that do not reside in the same directory as their related object file + +$(VARIANT_OBJ_C) : $(DEPSf) deps + $(CC) $(SDK_HEADER) $(RT_WIFI_CFLAGS) $(CFLAGS) -o $*.o -c $(*R).c + +################################################################################ +## TARGETS +################################################################################ +hal_fw: $(LIBNAME) + +mfp_fw: $(LIBNAME) + +!IF "$(NETSWITCH)"=="DISABLE_WIFI" +rt_wifi: + @echo **** WIFI DISABLED! **** +!ELSE +rt_wifi: + @echo **** START RT_WIFI building **** + set TARGET_LIBRARY=$(LIBDIR)\$(*B) + set DELIVERY_MODULE=$(DELIVERY_RT_WIFI) + $(MAKE) /$(MAKEFLAGS) $(LIBDIR)\$(*B).l + @echo **** DONE RT_WIFI **** +!ENDIF + +delivery: + @echo **** DELIVERY RT_WIFI **** + set DELIVERY_MODULE=$(DELIVERY_RT_WIFI) + $(MAKE) /$(MAKEFLAGS) delivery_map + +clean: + set DELIVERY_MODULE=$(DELIVERY_RT_WIFI) + $(MAKE) /$(MAKEFLAGS) clean_map + +depreport: + cd $(FWDIR) + deliveryBuilder -s $(NWK_INITDIR) -report -d depdir diff --git a/mt7620/src/tools/Makefile b/mt7620/src/tools/Makefile new file mode 100755 index 0000000..ce4a422 --- /dev/null +++ b/mt7620/src/tools/Makefile @@ -0,0 +1,6 @@ +all: + gcc -g bin2h.c -o bin2h +clean: + rm -f *.o bin2h + + diff --git a/mt7620/src/tools/bin2h b/mt7620/src/tools/bin2h new file mode 100755 index 0000000..1c104c6 Binary files /dev/null and b/mt7620/src/tools/bin2h differ diff --git a/mt7620/src/tools/bin2h.c b/mt7620/src/tools/bin2h.c new file mode 100644 index 0000000..bf3e531 --- /dev/null +++ b/mt7620/src/tools/bin2h.c @@ -0,0 +1,129 @@ +#include +#include +#include + +int main(int argc ,char *argv[]) +{ + FILE *infile, *outfile; + char infname[1024]; + char outfname[1024]; + char *rt28xxdir; + char *chipset; + char *wow, *rt28xx_mode; /* for WOW firmware */ + int i=0;//,n=0; + unsigned char c; + + memset(infname,0,1024); + memset(outfname,0,1024); + + rt28xxdir = (char *)getenv("RT28xx_DIR"); + chipset = (char *)getenv("CHIPSET"); + wow = (char *)getenv("HAS_WOW_SUPPORT"); /* for WOW firmware */ + 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; + } + + strcat(infname,rt28xxdir); + if(strncmp(chipset, "2860",4)==0) + strcat(infname,"/common/rt2860.bin"); + else if(strncmp(chipset, "2870",4)==0) + strcat(infname,"/common/rt2870.bin"); + else if(strncmp(chipset, "3090",4)==0) + strcat(infname,"/common/rt2860.bin"); + else if(strncmp(chipset, "2070",4)==0) + strcat(infname,"/common/rt2870.bin"); + else if(strncmp(chipset, "3070",4)==0) + strcat(infname,"/common/rt2870.bin"); + else if(strncmp(chipset, "3572",4)==0) + strcat(infname,"/common/rt2870.bin"); + else if(strncmp(chipset, "3573",4)==0) + strcat(infname,"/common/rt2870.bin"); + else if(strncmp(chipset, "3370",4)==0) + strcat(infname,"/common/rt2870.bin"); + else if(strncmp(chipset, "5370",4)==0) + strcat(infname,"/common/rt2870.bin"); + else if(strncmp(chipset, "5572",4)==0) + strcat(infname,"/common/rt2870.bin"); + else if(strncmp(chipset, "5592",4)==0) + strcat(infname,"/common/rt2860.bin"); + else if(strncmp(chipset, "USB",3)==0) + strcat(infname,"/common/rt2870.bin"); + else if(strncmp(chipset, "PCI",3)==0) + strcat(infname,"/common/rt2860.bin"); + else + strcat(infname,"/common/rt2860.bin"); + + /* for WOW support firmware */ + if ((wow != NULL) && (strncmp(wow, "y", 1) == 0) && (strncmp(rt28xx_mode, "STA", 3) == 0)) + { + if ((wow = strstr(infname, "rt2870")) != NULL) + { + strcpy(wow, "rt2870_wow.bin"); + fprintf(stderr, "infname %s\n", infname); + } + } + + strcat(outfname,rt28xxdir); + strcat(outfname,"/include/firmware.h"); + + 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); + fputs("UCHAR FirmwareImage [] = { \n",outfile); + 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); + exit(0); +} diff --git a/mt7620/src/vxworks.makefile b/mt7620/src/vxworks.makefile new file mode 100755 index 0000000..e9c2c4c --- /dev/null +++ b/mt7620/src/vxworks.makefile @@ -0,0 +1,43 @@ +#MODE STA or AP or APSTA +RT28xx_MODE = AP +#RT28xx_MODE = STA + +#TARTET = LINUX or UCOS +TARGET = VXWORKS + +#CHIPSET = 2860 or 2870 or 2880 +CHIPSET = 2860 + +#RT28xx_DIR = home directory of RT28xx source code +RT28xx_DIR = $(shell pwd) +RTMP_SRC_DIR = $(RT28xx_DIR)/RT$(CHIPSET) + +#PLATFORM: Target platform +PLATFORM = 5VT +#PLATFORM = PC +#PLATFORM = IKANOS_V160 +#PLATFORM = IKANOS_V180 +#PLATFORM = SIGMA +#PLATFORM = SIGMA_8622 +#PLATFORM = INIC +#PLATFORM = STAR +#PLATFORM = IXP +#PLATFORM = INF_TWINPASS +#PLATFORM = INF_DANUBE +#PLATFORM = BRCM_6358 +#PLATFORM = RALINK_2880 + +#RELEASE: DPA or DPB +RELEASE = DPB + +-include os/vxworks/config.mk + +ADDED_CFLAGS = $(WFLAGS) +export RT28xx_DIR RT28xx_MODE PLATFORM RELEASE CHIPSET RTMP_SRC_DIR WFLAGS + + + + + + + diff --git a/mt7620/src/wps_iwpriv_usage.txt b/mt7620/src/wps_iwpriv_usage.txt new file mode 100755 index 0000000..05fd1bc --- /dev/null +++ b/mt7620/src/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